<?php

namespace App\Services;

use App\Models\PartnerWallet;
use App\Models\PartnerWalletSetting;
use App\Models\PartnerWalletTransaction;
use Illuminate\Support\Facades\DB;

class PartnerWalletService
{
    /**
     * الحصول على محفظة الشريك أو إنشاؤها
     */
    public static function getOrCreateWallet(string $ownerType, int $ownerId): PartnerWallet
    {
        return PartnerWallet::getOrCreateFor($ownerType, $ownerId);
    }

    /**
     * استقطاع رسوم التطبيق من المحفظة (عند اكتمال الطلب)
     * الرصيد يمكن أن يصبح سالباً (ماينص)
     */
    public static function deductForOrder(
        string $ownerType,
        int $ownerId,
        float $amount,
        string $referenceType,
        int $referenceId,
        string $orderNumber,
        string $description = null
    ): PartnerWalletTransaction {
        if ($amount <= 0) {
            throw new \InvalidArgumentException('المبلغ يجب أن يكون أكبر من صفر');
        }

        $wallet = PartnerWallet::getOrCreateFor($ownerType, $ownerId);
        $settings = $wallet->settings;

        // التحقق من السماح بالرصيد السالب
        if ($settings && !$settings->allow_negative_balance && (float) $wallet->balance < $amount) {
            throw new \Exception('الرصيد غير كافي ولا يسمح بالرصيد السالب');
        }

        return DB::transaction(function () use ($wallet, $amount, $referenceType, $referenceId, $orderNumber, $description) {
            $wallet = PartnerWallet::where('id', $wallet->id)->lockForUpdate()->first();
            $balanceBefore = (float) $wallet->balance;
            $balanceAfter = $balanceBefore - $amount;

            $wallet->update(['balance' => $balanceAfter]);

            $transaction = PartnerWalletTransaction::create([
                'partner_wallet_id' => $wallet->id,
                'type' => PartnerWalletTransaction::TYPE_DEDUCTION,
                'amount' => $amount,
                'balance_before' => $balanceBefore,
                'balance_after' => $balanceAfter,
                'payment_method' => null,
                'reference_type' => $referenceType,
                'reference_id' => $referenceId,
                'description' => $description ?? "استقطاع رسوم التطبيق - طلبية #{$orderNumber}",
                'meta' => ['order_number' => $orderNumber],
                'status' => PartnerWalletTransaction::STATUS_COMPLETED,
            ]);

            return $transaction;
        });
    }

    /**
     * تعبئة المحفظة (زين كاش / ماستر كارد)
     * عند التعبئة: إذا كان الرصيد سالباً (ماينص) يُخصم أولاً من المبلغ المعبّأ، ثم الباقي يُضاف للرصيد
     */
    public static function topUp(
        int $partnerWalletId,
        float $amount,
        string $paymentMethod,
        string $externalId = null,
        string $description = null
    ): PartnerWalletTransaction {
        if ($amount <= 0) {
            throw new \InvalidArgumentException('المبلغ يجب أن يكون أكبر من صفر');
        }

        $wallet = PartnerWallet::with('settings')->findOrFail($partnerWalletId);
        $settings = $wallet->settings;

        if ($settings) {
            if ((float) $settings->min_topup_amount > 0 && $amount < (float) $settings->min_topup_amount) {
                throw new \Exception('المبلغ أقل من الحد الأدنى للتعبئة: ' . $settings->min_topup_amount . ' د.ع');
            }
            if ($settings->max_topup_amount !== null && $amount > (float) $settings->max_topup_amount) {
                throw new \Exception('المبلغ يتجاوز الحد الأقصى للتعبئة');
            }
            $methods = $settings->payment_methods ?? [];
            if (!in_array($paymentMethod, $methods)) {
                throw new \Exception('وسيلة الدفع غير مفعّلة');
            }
        }

        return DB::transaction(function () use ($wallet, $amount, $paymentMethod, $externalId, $description) {
            $wallet = PartnerWallet::where('id', $wallet->id)->lockForUpdate()->first();
            $balanceBefore = (float) $wallet->balance;
            $balanceAfter = $balanceBefore + $amount;

            $wallet->update(['balance' => $balanceAfter]);

            $transaction = PartnerWalletTransaction::create([
                'partner_wallet_id' => $wallet->id,
                'type' => PartnerWalletTransaction::TYPE_TOPUP,
                'amount' => $amount,
                'balance_before' => $balanceBefore,
                'balance_after' => $balanceAfter,
                'payment_method' => $paymentMethod,
                'reference_type' => PartnerWalletTransaction::REFERENCE_TOPUP,
                'reference_id' => null,
                'description' => $description ?? 'تعبئة رصيد - ' . self::paymentMethodName($paymentMethod),
                'meta' => ['external_id' => $externalId],
                'status' => PartnerWalletTransaction::STATUS_COMPLETED,
                'external_id' => $externalId,
            ]);

            return $transaction;
        });
    }

    private static function paymentMethodName(string $method): string
    {
        return match ($method) {
            'zain_cash' => 'زين كاش',
            'mastercard' => 'ماستر كارد',
            'aman_card' => 'بطاقة أمان',
            default => $method,
        };
    }
}
