<?php

namespace App\Services;

use App\Models\Order;
use App\Models\ReferralReward;
use App\Models\User;
use Illuminate\Support\Str;

class ReferralService
{
    private const REFERRER_REWARD_MINOR = 2500;

    private const REFERRED_REWARD_MINOR = 1000;

    public function __construct(
        private WalletService $wallets,
        private AuditLogService $audit,
    ) {}

    public function generateCode(): string
    {
        do {
            $code = 'RN'.strtoupper(Str::random(6));
        } while (User::where('referral_code', $code)->exists());

        return $code;
    }

    public function findReferrer(?string $code): ?User
    {
        if (! $code) {
            return null;
        }

        return User::where('referral_code', strtoupper(trim($code)))
            ->where('status', 'active')
            ->first();
    }

    public function applyFirstPaidOrderReward(Order $order, User $referredUser): void
    {
        $referredUser->refresh();

        if (! $referredUser->referred_by_user_id || $order->payment_status !== 'paid') {
            return;
        }

        if (ReferralReward::where('referred_user_id', $referredUser->id)->exists()) {
            return;
        }

        $paidOrders = Order::where('user_id', $referredUser->id)->where('payment_status', 'paid')->count();

        if ($paidOrders !== 1) {
            return;
        }

        $referrer = User::find($referredUser->referred_by_user_id);

        if (! $referrer || $referrer->is($referredUser)) {
            return;
        }

        $reward = ReferralReward::create([
            'referrer_user_id' => $referrer->id,
            'referred_user_id' => $referredUser->id,
            'order_id' => $order->id,
            'currency_code' => $order->currency_code,
            'referrer_reward_minor' => self::REFERRER_REWARD_MINOR,
            'referred_reward_minor' => self::REFERRED_REWARD_MINOR,
            'status' => 'paid',
            'snapshot' => [
                'order_number' => $order->order_number,
                'referrer_public_id' => $referrer->public_id,
                'referred_public_id' => $referredUser->public_id,
            ],
        ]);

        $referrerWallet = $this->wallets->ensureWallet($referrer, $order->currency_code);
        $this->wallets->credit($referrerWallet, self::REFERRER_REWARD_MINOR, 'referral_reward', 'Referral reward for '.$referredUser->public_id, ReferralReward::class, $reward->id);

        $referredWallet = $this->wallets->ensureWallet($referredUser, $order->currency_code);
        $this->wallets->credit($referredWallet, self::REFERRED_REWARD_MINOR, 'referral_bonus', 'Referral welcome bonus', ReferralReward::class, $reward->id);

        $this->audit->record('referral.reward_paid', $reward, [
            'order_number' => $order->order_number,
            'referrer_reward_minor' => self::REFERRER_REWARD_MINOR,
            'referred_reward_minor' => self::REFERRED_REWARD_MINOR,
        ], $referrer);
    }
}
