<?php

namespace App\Http\Controllers\Traits;

use Illuminate\Http\Request;
use App\Models\Coupon;
use App\Models\CouponUsage;
use Illuminate\Support\Facades\Auth;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;

trait ApplyCouponTrait
{
    /**
     * Process and apply coupon from request if present
     *
     * @param Request $request The incoming request
     * @param float $originalPrice The original price before discount
     * @param array|null $planIds The selected plan IDs (can be multiple)
     * @return array Response with price details and status
     */
    public function processCouponFromRequest(Request $request, float $originalPrice, ?array $planIds = null)
    {
        $response = [
            'original_price' => $originalPrice,
            'final_price' => $originalPrice,
            'discount_amount' => 0,
            'coupon_applied' => false,
            'coupon_code' => null,
            'coupon_id' => null,
            'message' => null,
            'success' => true
        ];

        // Check if coupon code exists in request
        $couponCode = $request->coupon_code;
        if (!$couponCode) {
            return $response;
        }

        // Validate and apply coupon
        $couponResult = $this->validateAndApplyCoupon($originalPrice, $couponCode, $planIds);
        // If coupon validation failed
        if (!isset($couponResult['success']) || $couponResult['success'] === false) {
            $response['success'] = false;
            $response['message'] = $couponResult['message'] ?? 'Invalid coupon';
            return $response;
        }
        // Update response with coupon details
        $response['coupon_applied'] = true;
        $response['coupon_code'] = $couponCode;
        $response['coupon_id'] = $couponResult['coupon']->id;
        $response['discount_amount'] = $couponResult['discount_amount'];
        $response['final_price'] = $couponResult['discounted_price'];
        $response['message'] = 'Coupon applied successfully';
        return $response;
    }

    /**
     * Validate and apply coupon to price
     *
     * @param float $price Original price
     * @param string $couponCode Coupon code
     * @param array|null $planIds Array of plan IDs
     * @return array Result with discount calculation or error message
     */
    private function validateAndApplyCoupon(float $price, string $couponCode, ?array $planIds = null)
    {
        $response = [
            'success' => false,
            'message' => '',
            'coupon' => null,
            'discount_amount' => 0,
            'discounted_price' => $price
        ];
        // Get coupon by code
        $coupon = Coupon::where('code', $couponCode)->first();
        if (!$coupon) {
            $response['message'] = 'Invalid coupon code.';
            return $response;
        }
        $response['coupon'] = $coupon;
        // Check if coupon is active
        if ($coupon->is_active != 1) {
            $response['message'] = 'This coupon is not active.';
            return $response;
        }
        // Check expiration date
        $now = Carbon::now();
        $expiryDate = Carbon::parse($coupon->expiry_date);
        if ($now->gt($expiryDate)) {
            // Update coupon status to inactive if expired
            $coupon->is_active = 0;
            $coupon->save();
            $response['message'] = 'This coupon has expired.';
            return $response;
        }
        // For plan-specific coupons
        if ($planIds && !empty($planIds)) {
            if (!empty($coupon->included_plan)) {
                $includedPlans = is_array($coupon->included_plan) ? $coupon->included_plan : json_decode($coupon->included_plan, true);
                if (!is_array($includedPlans)) {
                    $includedPlans = [];
                }
                $invalidPlans = [];
                foreach ($planIds as $planId) {
                    if (!in_array($planId, $includedPlans)) {
                        $invalidPlans[] = $planId;
                    }
                }
                // If any plan is not in the included plans list, reject the coupon
                if (!empty($invalidPlans)) {
                    $response['message'] = 'One or more selected plans are not eligible for this coupon.';
                    $response['invalid_plans'] = $invalidPlans; // Return which plans are invalid
                    return $response;
                }
            }
            // Check if any plan is excluded
            // if (!empty($coupon->excluded_plan)) {
            //     $excludedPlans = is_array($coupon->excluded_plan) ? $coupon->excluded_plan : json_decode($coupon->excluded_plan, true);

            //     // Ensure excludedPlans is an array
            //     if (!is_array($excludedPlans)) {
            //         $excludedPlans = [];
            //     }

            //     $excludedSelectedPlans = [];
            //     foreach ($planIds as $planId) {
            //         if (in_array($planId, $excludedPlans)) {
            //             $excludedSelectedPlans[] = $planId;
            //         }
            //     }

            //     // If any of the selected plans are in the excluded list
            //     if (!empty($excludedSelectedPlans)) {
            //         $response['message'] = 'This coupon cannot be used with one or more of your selected plans.';
            //         $response['excluded_plans'] = $excludedSelectedPlans;
            //         return $response;
            //     }
            // }
        }
        // Check minimum spend
        if ($coupon->minimum_spend > 0 && $price < $coupon->minimum_spend) {
            $response['message'] = "Minimum spend of $" . number_format($coupon->minimum_spend, 2) . " required for this coupon.";
            return $response;
        }
        // Check maximum spend
        if ($coupon->maximum_spend > 0 && $price > $coupon->maximum_spend) {
            $response['message'] = "This coupon is valid only for orders up to $" . number_format($coupon->maximum_spend, 2) . ".";
            return $response;
        }
        // Check global usage limit
        $totalUsageCount = CouponUsage::where('coupon_id', $coupon->id)->count();
        if ($coupon->limit > 0 && $totalUsageCount >= $coupon->limit) {
            $response['message'] = 'This coupon has reached its usage limit.';
            return $response;
        }
        // Check per-user limit
        $userId = Auth::id();
        if (!$userId) {
            $response['message'] = 'User authentication required to apply coupon.';
            return $response;
        }
        $userUsageCount = CouponUsage::where('coupon_id', $coupon->id)
            ->where('user_id', $userId)
            ->count();
        if ($coupon->limit_per_user > 0 && $userUsageCount >= $coupon->limit_per_user) {
            $response['message'] = 'You have already used this coupon the maximum number of times.';
            return $response;
        }
        // Calculate discount
        $discountAmount = 0;
        if ($coupon->type === 'percentage') {
            $discountAmount = $price * ($coupon->discount / 100);
        } else {
            $discountAmount = $coupon->discount;
        }
        // Ensure discount doesn't exceed the price
        $discountAmount = min($discountAmount, $price);
        $discountedPrice = $price - $discountAmount;
        // Update response with success and price details
        $response['success'] = true;
        $response['discount_amount'] = $discountAmount;
        $response['discounted_price'] = $discountedPrice;
        return $response;
    }

    /**
     * Record coupon usage after successful order placement
     * 
     * @param int $couponId Coupon ID
     * @param int $orderId Order ID
     * @param float $discountAmount Amount of discount applied
     * @return bool Success status
     */
    public function recordCouponUsage(int $couponId, int $orderId, float $discountAmount)
    {
        $userId = Auth::id();
        if (!$userId) {
            return false;
        }
        try {
            // Record usage
            CouponUsage::create([
                'coupon_id' => $couponId,
                'user_id' => $userId,
                'order_id' => $orderId,
                'discount_amount' => $discountAmount,
                'used_at' => Carbon::now()
            ]);
            // Get current coupon
            $coupon = Coupon::find($couponId);
            // Check if we need to deactivate the coupon due to limit
            if ($coupon) {
                $totalUsageCount = CouponUsage::where('coupon_id', $couponId)->count();

                if ($coupon->limit > 0 && $totalUsageCount >= $coupon->limit) {
                    $coupon->is_active = 0;
                    $coupon->save();
                }
            }
            return true;
        } catch (\Exception $e) {
            // Log the error
            Log::error('Failed to record coupon usage: ' . $e->getMessage());
            return false;
        }
    }
}
