<?php

namespace App\Domain\Financial\Services;

use App\Domain\Financial\Events\WalletDeposited;
use App\Domain\Financial\Models\Wallet;
use App\Domain\Financial\Models\WalletTransaction;
use App\Models\User;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
use InvalidArgumentException;

class WalletService
{
    public function getOrCreateWallet(Model $owner, int $academyId): Wallet
    {
        return Wallet::firstOrCreate([
            'academy_id' => $academyId,
            'owner_type' => $owner->getMorphClass(),
            'owner_id' => $owner->getKey(),
        ], [
            'balance' => 0,
            'currency' => 'EGP',
            'is_active' => true,
        ]);
    }

    public function deposit(Wallet $wallet, int $amount, string $description, ?Model $reference = null, ?User $creator = null): WalletTransaction
    {
        if ($amount <= 0) {
            throw new InvalidArgumentException('Deposit amount must be positive');
        }

        if (!$wallet->is_active) {
            throw new InvalidArgumentException('المحفظة مجمدة — لا يمكن الإيداع');
        }

        return DB::transaction(function () use ($wallet, $amount, $description, $reference, $creator) {
            $wallet->lockForUpdate();
            $balanceBefore = $wallet->balance;

            $wallet->increment('balance', $amount);

            $transaction = WalletTransaction::create([
                'wallet_id' => $wallet->id,
                'type' => 'deposit',
                'direction' => 'credit',
                'amount' => $amount,
                'balance_before' => $balanceBefore,
                'balance_after' => $balanceBefore + $amount,
                'reference_type' => $reference?->getMorphClass(),
                'reference_id' => $reference?->getKey(),
                'description' => $description,
                'created_by' => $creator?->id,
            ]);

            if ($creator) {
                WalletDeposited::dispatch($wallet, $amount, $creator);
            }

            return $transaction;
        });
    }

    public function withdraw(Wallet $wallet, int $amount, string $description, ?Model $reference = null, ?User $creator = null): WalletTransaction
    {
        if ($amount <= 0) {
            throw new InvalidArgumentException('Withdrawal amount must be positive');
        }

        if (!$wallet->is_active) {
            throw new InvalidArgumentException('المحفظة مجمدة — لا يمكن السحب');
        }

        return DB::transaction(function () use ($wallet, $amount, $description, $reference, $creator) {
            $wallet->lockForUpdate();

            if ($wallet->balance < $amount) {
                throw new InvalidArgumentException('Insufficient wallet balance');
            }

            $balanceBefore = $wallet->balance;
            $wallet->decrement('balance', $amount);

            return WalletTransaction::create([
                'wallet_id' => $wallet->id,
                'type' => 'withdrawal',
                'direction' => 'debit',
                'amount' => $amount,
                'balance_before' => $balanceBefore,
                'balance_after' => $balanceBefore - $amount,
                'reference_type' => $reference?->getMorphClass(),
                'reference_id' => $reference?->getKey(),
                'description' => $description,
                'created_by' => $creator?->id,
            ]);
        });
    }
}
