<?php

namespace App\Services;

use App\Models\LoyaltyTransaction;
use App\Models\Order;
use App\Models\PointSetting;
use App\Models\User;
use Illuminate\Support\Facades\DB;

class PointsService
{
    /**
     * احسب عدد النقاط المستحقة بناءً على قيمة الطلب.
     * مثال: إذا egp_per_point = 10 وقيمة الطلب = 275 ج.م => النقاط = 27
     */
    public function calculateEarnedPoints(float $orderTotal): int
    {
        $settings = PointSetting::current();
        $egpPerPoint = (float) $settings->egp_per_point;

        if ($egpPerPoint <= 0) {
            return 0;
        }

        return (int) floor($orderTotal / $egpPerPoint);
    }

    /**
     * احسب قيمة الخصم بالجنيه عند استبدال عدد معين من النقاط.
     * مثال: إذا point_value_in_egp = 1 واستبدل 50 نقطة => الخصم = 50 ج.م
     */
    public function calculateRedemptionDiscount(int $points): float
    {
        $settings = PointSetting::current();
        return round($points * (float) $settings->point_value_in_egp, 2);
    }

    /**
     * أقصى عدد نقاط يمكن للتاجر استبدالها (لا يتجاوز رصيده ولا قيمة الطلب).
     */
    public function getMaxRedeemablePoints(User $user, float $orderTotal): int
    {
        $settings = PointSetting::current();
        $pointValue = (float) $settings->point_value_in_egp;

        if ($pointValue <= 0) {
            return 0;
        }

        $userBalance = (int) floor($user->points_balance);
        $maxByOrderTotal = (int) floor($orderTotal / $pointValue);

        return min($userBalance, $maxByOrderTotal);
    }

    /**
     * تفعيل النقاط المكتسبة عند وصول الطلب لحالة "تم التسليم".
     * لا تُستحق النقاط إلا عند delivered.
     */
    public function finalizePoints(Order $order): void
    {
        if ($order->status !== Order::STATUS_DELIVERED) {
            return;
        }

        if ($order->points_earned <= 0) {
            return;
        }

        $alreadyFinalized = LoyaltyTransaction::where('order_id', $order->id)
            ->where('type', 'earned')
            ->exists();

        if ($alreadyFinalized) {
            return;
        }

        DB::transaction(function () use ($order) {
            LoyaltyTransaction::create([
                'user_id' => $order->user_id,
                'order_id' => $order->id,
                'points' => $order->points_earned,
                'type' => 'earned',
                'description' => "نقاط مكتسبة من الطلب #{$order->id}",
            ]);

            $order->user->increment('points_balance', $order->points_earned);
        });
    }

    /**
     * خصم نقاط من رصيد التاجر عند استخدامها كخصم في طلب.
     */
    public function redeemPoints(User $user, Order $order, int $points): float
    {
        if ($points <= 0) {
            return 0;
        }

        $points = min($points, (int) floor($user->points_balance));
        $discount = $this->calculateRedemptionDiscount($points);

        DB::transaction(function () use ($user, $order, $points) {
            LoyaltyTransaction::create([
                'user_id' => $user->id,
                'order_id' => $order->id,
                'points' => $points,
                'type' => 'redeemed',
                'description' => "استبدال نقاط في الطلب #{$order->id}",
            ]);

            $user->decrement('points_balance', $points);
        });

        return $discount;
    }

    /**
     * إلغاء النقاط المكتسبة (مثلاً عند إرجاع طلب).
     */
    public function reverseEarnedPoints(Order $order): void
    {
        $earnedTransaction = LoyaltyTransaction::where('order_id', $order->id)
            ->where('type', 'earned')
            ->first();

        if (! $earnedTransaction) {
            return;
        }

        $alreadyReversed = LoyaltyTransaction::where('order_id', $order->id)
            ->where('type', 'earned_reversed')
            ->exists();

        if ($alreadyReversed) {
            return;
        }

        DB::transaction(function () use ($order, $earnedTransaction) {
            LoyaltyTransaction::create([
                'user_id' => $order->user_id,
                'order_id' => $order->id,
                'points' => $earnedTransaction->points,
                'type' => 'earned_reversed',
                'description' => "إلغاء نقاط مكتسبة - مرتجع الطلب #{$order->id}",
            ]);

            $order->user->decrement('points_balance', $earnedTransaction->points);
        });
    }

    /**
     * إعادة النقاط المستبدلة إلى رصيد التاجر عند إرجاع الطلب.
     */
    public function reverseRedeemedPoints(Order $order): void
    {
        if ($order->points_redeemed <= 0) {
            return;
        }

        $alreadyRefunded = LoyaltyTransaction::where('order_id', $order->id)
            ->where('type', 'redeemed_refund')
            ->exists();

        if ($alreadyRefunded) {
            return;
        }

        DB::transaction(function () use ($order) {
            LoyaltyTransaction::create([
                'user_id' => $order->user_id,
                'order_id' => $order->id,
                'points' => $order->points_redeemed,
                'type' => 'redeemed_refund',
                'description' => "استرداد نقاط مستبدلة - مرتجع الطلب #{$order->id}",
            ]);

            $order->user->increment('points_balance', $order->points_redeemed);
        });
    }
}
