<?php

namespace App\Http\Controllers;

use App\Data\AmadastCities;
use App\Data\PaymentGateways;
use App\Models\DiscountCode;
use App\Models\MobileVerification;
use App\Models\Order;
use App\Models\OrderItem;
use App\Models\Transaction;
use App\Models\Wallet;
use App\Models\Product;
use App\Models\ProductVariant;
use App\Models\Setting;
use App\Models\ShippingMethod;
use App\Models\User;
use App\Models\UserAddress;
use App\Http\Middleware\CaptureVisitorReferrer;
use App\Services\AmadastService;
use App\Services\CustomerClubService;
use App\Services\DigiPayService;
use App\Services\PayamMatni;
use App\Services\TorobPayService;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Validator;

class CheckoutController extends Controller
{
    public function index()
    {
        $cart  = session('cart', []);
        $items = [];

        if (!empty($cart)) {
            $variantIds = array_column($cart, 'variant_id');
            $variants   = ProductVariant::with('product')
                ->whereIn('id', $variantIds)
                ->get()
                ->keyBy('id');

            foreach ($cart as $key => $row) {
                $variant = $variants->get($row['variant_id']);
                if (!$variant) continue;
                $items[] = [
                    'key'     => $key,
                    'variant' => $variant,
                    'product' => $variant->product,
                    'qty'     => $row['qty'],
                ];
            }
        }

        $persianDays  = [0 => 'یک‌شنبه', 1 => 'دوشنبه', 2 => 'سه‌شنبه', 3 => 'چهارشنبه', 4 => 'پنج‌شنبه', 6 => 'شنبه'];
        $shippingDays = [];
        $date         = Carbon::tomorrow();

        while (count($shippingDays) < 6) {
            if ($date->dayOfWeek !== Carbon::FRIDAY) {
                $shippingDays[] = [
                    'dayName' => $persianDays[$date->dayOfWeek] ?? '',
                    'display' => $date->day . ' / ' . $date->month,
                ];
            }
            $date->addDay();
        }

        $addresses = Auth::check()
            ? UserAddress::where('user_id', Auth::id())->latest()->get()
            : collect([]);

        $provinces       = require app_path('Data/IranProvinces.php');
        $shippingMethods = ShippingMethod::active()->get();

        $cityIdMap = [];
        if ($shippingMethods->where('type', 'amadast')->isNotEmpty()) {
            foreach (AmadastCities::allCitiesWithFullName() as $c) {
                $cityIdMap[$c['province'] . ':' . $c['city_name']] = $c['id'];
            }
        }

        $paymentMethods = PaymentGateways::activeForCheckout();
        $walletBalance  = Auth::check() ? (int) Wallet::forUser(Auth::user())->balance : 0;

        // fallback cost در تومان از تنظیمات
        $fallbackRial  = (int) Setting::get('amadast_fallback_cost', 0);
        $fallbackToman = (int) round($fallbackRial / 10);

        return view('site.checkout', compact(
            'items', 'shippingDays', 'addresses', 'provinces', 'shippingMethods', 'cityIdMap', 'paymentMethods', 'walletBalance', 'fallbackToman'
        ));
    }

    public function ajaxShippingCost(Request $request)
    {
        if (!Auth::check()) {
            return response()->json(['success' => false, 'message' => 'ابتدا وارد شوید.'], 401);
        }

        $methodId = (int) $request->input('shipping_method_id');
        $toCityId = (int) $request->input('city_amadast_id');

        if (!$methodId || !$toCityId) {
            return response()->json(['success' => false, 'message' => 'اطلاعات ناقص است.'], 422);
        }

        $method = ShippingMethod::find($methodId);
        if (!$method || $method->type !== 'amadast') {
            return response()->json(['success' => false, 'message' => 'روش ارسال نامعتبر.'], 422);
        }

        $fromCityId    = (int) Setting::get('amadast_from_city_id', 0);
        $defaultWeight = max(10, (int) Setting::get('amadast_default_weight', 500));
        $pkgType       = (int) Setting::get('amadast_default_pkg_type', 1);
        $extraCost     = (int) Setting::get('amadast_extra_cost', 0);   // ریال
        $extraPct      = (float) Setting::get('amadast_extra_cost_percent', 0);
        $fallbackRial  = (int) Setting::get('amadast_fallback_cost', 0); // ریال
        $fallbackToman = (int) round($fallbackRial / 10);

        // دریافت fallback cost از frontend (اگر ارسال شده)
        $frontendFallback = (int) $request->input('_fallback', 0);
        if ($frontendFallback > 0) {
            $fallbackToman = $frontendFallback;
        }

        if (!$fromCityId) {
            return response()->json(['success' => true, 'price' => $fallbackToman, 'is_fallback' => true]);
        }

        // وزن و ارزش سبد از محصولات واقعی
        $cart = session('cart', []);
        $cartValueToman = 0;
        $totalWeight    = 0;

        if (!empty($cart)) {
            $variantIds = array_column($cart, 'variant_id');
            $variants   = ProductVariant::whereIn('id', $variantIds)->get()->keyBy('id');
            foreach ($cart as $row) {
                $v   = $variants->get($row['variant_id'] ?? 0);
                $qty = (int)($row['qty'] ?? 1);
                if (!$v) continue;
                $cartValueToman += (float)($v->discount_price ?? $v->price ?? 0) * $qty;
                $variantWeight   = (int)($v->weight ?? 0);
                $totalWeight    += ($variantWeight > 0 ? $variantWeight : $defaultWeight) * $qty;
            }
        }

        $weight        = max(10, $totalWeight > 0 ? $totalWeight : $defaultWeight);
        $cartValueRial = (int) round($cartValueToman * 10);

        $apiUrl  = 'https://api.amadast.com/api/v2.0/tool/shipping-calculator';
        $headers = [
            'Content-Type' => 'application/json',
            'Accept'       => 'application/json',
            'User-Agent'   => 'Amadast-WP-Plugin/3.1.1',
        ];

        try {
            // مرحله ۱: POST برای دریافت request_id
            $post = Http::withoutVerifying()
                ->withHeaders($headers)
                ->timeout(20)
                ->post($apiUrl, [
                    'from_city'    => $fromCityId,
                    'to_city'      => $toCityId,
                    'weight'       => $weight,
                    'package_type' => $pkgType,
                    'value'        => $cartValueRial,
                    'couriers'     => [$method->amadast_courier_id],
                    'meta_data'    => ['source' => config('app.url')],
                ]);

            $requestId = $post->json('data.request_id');
            if ($post->failed() || !$requestId) {
                return response()->json(['success' => true, 'price' => $fallbackToman, 'is_fallback' => true]);
            }

            // مرحله ۲: polling تا آماده شود (حداکثر ۲۰×۰.۵ ثانیه)
            $pollUrl   = $apiUrl . '/' . $requestId;
            $priceRial = null;

            for ($i = 0; $i < 20; $i++) {
                usleep(500000);

                $poll = Http::withoutVerifying()->withHeaders($headers)->timeout(15)->get($pollUrl);
                if ($poll->failed()) continue;

                $pd      = $poll->json();
                $percent = $pd['data']['progress_detail']['percent'] ?? 0;
                $items   = $pd['data']['data']['items'] ?? null;

                if ($percent < 100 && $items === null) continue;

                $courierId = $method->amadast_courier_id;
                foreach ((array) $items as $svc) {
                    if (\App\Data\AmadastCouriers::itemMatches((array) $svc, (int) $courierId)) {
                        $raw = $svc['discounted_price'] ?? $svc['price'] ?? null;
                        if ($raw !== null && (float)$raw > 0) {
                            $priceRial = (int) $raw;
                        }
                        break;
                    }
                }
                break;
            }

            if (!$priceRial) {
                return response()->json(['success' => true, 'price' => $fallbackToman, 'is_fallback' => true]);
            }

            // اعمال هزینه‌های اضافی (ریال)
            $priceRial += $extraCost;
            if ($extraPct > 0) {
                $priceRial += (int) round($priceRial * $extraPct / 100);
            }

            // تبدیل ریال به تومان
            $priceToman = (int) round($priceRial / 10);

            return response()->json(['success' => true, 'price' => $priceToman, 'is_fallback' => false]);

        } catch (\Exception $e) {
            return response()->json(['success' => true, 'price' => $fallbackToman, 'is_fallback' => true]);
        }
    }

    public function applyCoupon(Request $request)
    {
        $code = trim($request->input('code', ''));

        if ($code === '') {
            return response()->json(['success' => false, 'message' => 'کد تخفیف را وارد کنید.'], 422);
        }

        $dc = DiscountCode::where('code', $code)->first();

        if (!$dc) {
            return response()->json(['success' => false, 'message' => 'کد تخفیف وارد شده معتبر نمی باشد'], 422);
        }

        if (!$dc->isValid()) {
            return response()->json(['success' => false, 'message' => 'کد تخفیف وارد شده قابل استفاده در این سفارش نیست'], 422);
        }

        if ($dc->max_uses_per_user !== null && Auth::check()) {
            $usedByUser = Order::where('coupon_code', $dc->code)
                ->where('user_id', Auth::id())
                ->whereNotIn('status', ['failed', 'canceled'])
                ->count();
            if ($usedByUser >= $dc->max_uses_per_user) {
                return response()->json(['success' => false, 'message' => 'این کد تخفیف قبلاً توسط شما استفاده شده است.'], 422);
            }
        }

        if ($dc->scope === 'user') {
            if (!Auth::check() || Auth::id() !== $dc->user_id) {
                return response()->json(['success' => false, 'message' => 'کد تخفیف وارد شده قابل استفاده در این سفارش نیست'], 422);
            }
        }

        $cart = session('cart', []);
        if (empty($cart)) {
            return response()->json(['success' => false, 'message' => 'سبد خرید شما خالی است.'], 422);
        }

        $variantIds = array_column($cart, 'variant_id');
        $variants   = ProductVariant::whereIn('id', $variantIds)->get()->keyBy('id');

        $productIds = [];
        if ($dc->scope === 'products') {
            $productIds = $dc->products()->pluck('products.id')->toArray();
        }

        $cartTotal          = 0;
        $applicableSubtotal = 0;

        foreach ($cart as $row) {
            $variant = $variants->get($row['variant_id'] ?? 0);
            if (!$variant) continue;
            $qty   = (int)$row['qty'];
            $final = (float)($variant->discount_price ?? $variant->price ?? 0);
            $cartTotal += $final * $qty;

            if ($dc->scope === 'products') {
                if (in_array($variant->product_id, $productIds)) {
                    $applicableSubtotal += $final * $qty;
                }
            } else {
                $applicableSubtotal += $final * $qty;
            }
        }

        if ($dc->min_order && $cartTotal < $dc->min_order) {
            return response()->json(['success' => false, 'message' => 'کد تخفیف وارد شده قابل استفاده در این سفارش نیست'], 422);
        }

        if ($applicableSubtotal <= 0) {
            return response()->json(['success' => false, 'message' => 'کد تخفیف وارد شده قابل استفاده در این سفارش نیست'], 422);
        }

        $discountAmount = $dc->type === 'percent'
            ? (int)round($applicableSubtotal * $dc->value / 100)
            : (int)min($dc->value, $applicableSubtotal);

        session(['applied_coupon' => ['code' => $code, 'id' => $dc->id, 'discount' => $discountAmount]]);

        return response()->json(['success' => true, 'discount' => $discountAmount]);
    }

    public function ajaxLogin(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'mobile'   => ['required', 'regex:/^09[0-9]{9}$/'],
            'password' => 'required',
        ], [
            'mobile.required'   => 'شماره موبایل الزامی است.',
            'mobile.regex'      => 'شماره موبایل معتبر نیست.',
            'password.required' => 'رمز عبور الزامی است.',
        ]);

        if ($validator->fails()) {
            return response()->json(['success' => false, 'errors' => $validator->errors()], 422);
        }

        if (!Auth::attempt(['mobile' => $request->mobile, 'password' => $request->password])) {
            return response()->json(['success' => false, 'errors' => ['mobile' => ['شماره موبایل یا رمز عبور اشتباه است.']]], 422);
        }

        if (!Auth::user()->mobile_verify) {
            Auth::logout();
            return response()->json(['success' => false, 'errors' => ['mobile' => ['حساب کاربری شما تأیید نشده است.']]], 422);
        }

        return response()->json(['success' => true]);
    }

    public function ajaxRegister(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'first_name'            => ['required', 'string', 'max:255', 'regex:/^[\x{0600}-\x{06FF}\x{200C}\s]+$/u'],
            'last_name'             => ['required', 'string', 'max:255', 'regex:/^[\x{0600}-\x{06FF}\x{200C}\s]+$/u'],
            'mobile'                => ['required', 'string', 'regex:/^09[0-9]{9}$/', 'unique:users'],
            'password'              => 'required|string|min:8|confirmed',
        ], [
            'first_name.required' => 'نام الزامی است.',
            'first_name.regex'    => 'نام باید فارسی باشد.',
            'last_name.required'  => 'نام خانوادگی الزامی است.',
            'last_name.regex'     => 'نام خانوادگی باید فارسی باشد.',
            'mobile.required'     => 'شماره موبایل الزامی است.',
            'mobile.regex'        => 'شماره موبایل معتبر نیست.',
            'mobile.unique'       => 'این شماره موبایل قبلاً ثبت شده است.',
            'password.required'   => 'رمز عبور الزامی است.',
            'password.min'        => 'رمز عبور باید حداقل ۸ کاراکتر باشد.',
            'password.confirmed'  => 'تکرار رمز عبور مطابقت ندارد.',
        ]);

        if ($validator->fails()) {
            return response()->json(['success' => false, 'errors' => $validator->errors()], 422);
        }

        $user = User::create([
            'first_name' => $request->first_name,
            'last_name'  => $request->last_name,
            'mobile'     => $request->mobile,
            'password'   => Hash::make($request->password),
        ]);

        $now  = now();
        $code = str_pad(random_int(10000, 99999), 5, '0', STR_PAD_LEFT);

        MobileVerification::updateOrCreate(
            ['mobile' => $user->mobile],
            [
                'code'          => $code,
                'expires_at'    => $now->copy()->addMinutes(5),
                'last_sent_at'  => $now,
                'sent_count'    => 1,
                'first_sent_at' => $now,
            ]
        );

        PayamMatni::sendOtp($user->mobile, $code);

        session(['checkout_otp_mobile' => $user->mobile]);

        return response()->json(['success' => true]);
    }

    public function ajaxOtpVerify(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'code' => 'required|digits:5',
        ], [
            'code.required' => 'کد تأیید الزامی است.',
            'code.digits'   => 'کد تأیید باید ۵ رقم باشد.',
        ]);

        if ($validator->fails()) {
            return response()->json(['success' => false, 'errors' => $validator->errors()], 422);
        }

        $mobile = session('checkout_otp_mobile');

        if (!$mobile) {
            return response()->json(['success' => false, 'errors' => ['code' => ['جلسه منقضی شده. لطفاً مجدداً ثبت‌نام کنید.']]], 422);
        }

        $verification = MobileVerification::where('mobile', $mobile)->first();

        if (!$verification || now()->isAfter($verification->expires_at)) {
            return response()->json(['success' => false, 'errors' => ['code' => ['کد تأیید منقضی شده است. کد جدید دریافت کنید.']]], 422);
        }

        if ($request->code !== $verification->code) {
            return response()->json(['success' => false, 'errors' => ['code' => ['کد وارد شده اشتباه است.']]], 422);
        }

        $user = User::where('mobile', $mobile)->first();

        if (!$user) {
            return response()->json(['success' => false, 'errors' => ['code' => ['کاربر یافت نشد.']]], 422);
        }

        $user->mobile_verify = true;
        $user->save();

        $verification->delete();
        session()->forget('checkout_otp_mobile');

        Auth::login($user, true);

        return response()->json(['success' => true]);
    }

    public function ajaxOtpResend(Request $request)
    {
        $mobile = session('checkout_otp_mobile');

        if (!$mobile) {
            return response()->json(['success' => false, 'message' => 'جلسه منقضی شده. لطفاً مجدداً ثبت‌نام کنید.'], 422);
        }

        $now          = now();
        $verification = MobileVerification::where('mobile', $mobile)->first();

        if ($verification && $verification->last_sent_at &&
            ($now->timestamp - $verification->last_sent_at->timestamp) < 90) {
            $cooldown = 90 - ($now->timestamp - $verification->last_sent_at->timestamp);
            return response()->json(['success' => false, 'message' => "لطفاً {$cooldown} ثانیه صبر کنید."], 422);
        }

        $code = str_pad(random_int(10000, 99999), 5, '0', STR_PAD_LEFT);

        MobileVerification::updateOrCreate(
            ['mobile' => $mobile],
            [
                'code'         => $code,
                'expires_at'   => $now->copy()->addMinutes(5),
                'last_sent_at' => $now,
                'sent_count'   => ($verification?->sent_count ?? 0) + 1,
            ]
        );

        PayamMatni::sendOtp($mobile, $code);

        return response()->json(['success' => true]);
    }

    public function placeOrder(Request $request)
    {
        if (!Auth::check()) {
            return response()->json(['success' => false, 'message' => 'برای ثبت سفارش باید وارد شوید.'], 401);
        }

        $validator = Validator::make($request->all(), [
            'address_id'         => 'required|exists:user_addresses,id',
            'shipping_method_id' => 'required|exists:shipping_methods,id',
            'payment_method'     => 'required|string',
            'use_wallet'         => 'boolean',
            'shipping_cost'      => 'integer|min:0',
        ], [
            'address_id.required'         => 'لطفاً یک آدرس انتخاب کنید.',
            'address_id.exists'           => 'آدرس انتخابی معتبر نیست.',
            'shipping_method_id.required' => 'لطفاً روش ارسال را انتخاب کنید.',
            'shipping_method_id.exists'   => 'روش ارسال انتخابی معتبر نیست.',
            'payment_method.required'     => 'لطفاً روش پرداخت را انتخاب کنید.',
        ]);

        if ($validator->fails()) {
            return response()->json(['success' => false, 'message' => $validator->errors()->first()], 422);
        }

        // Verify address belongs to auth user
        $address = UserAddress::where('id', $request->address_id)
            ->where('user_id', Auth::id())
            ->first();

        if (!$address) {
            return response()->json(['success' => false, 'message' => 'آدرس انتخابی معتبر نیست.'], 422);
        }

        // Load and validate shipping method
        $shippingMethod = ShippingMethod::find($request->shipping_method_id);
        if (!$shippingMethod) {
            return response()->json(['success' => false, 'message' => 'روش ارسال انتخابی معتبر نیست.'], 422);
        }

        if ($shippingMethod->type === 'fixed') {
            $shippingCostUsed = (int) $shippingMethod->fixed_cost;
        } elseif ($shippingMethod->type === 'amadast') {
            $shippingCostUsed = min((int) $request->input('shipping_cost', 0), 500000);
        } else {
            $shippingCostUsed = (int) $shippingMethod->fixed_cost;
        }

        // Verify payment method
        $activeGateways   = PaymentGateways::activeForCheckout();
        $activeGatewayIds = array_column($activeGateways, 'id');
        if (!in_array($request->payment_method, $activeGatewayIds)) {
            return response()->json(['success' => false, 'message' => 'روش پرداخت انتخابی معتبر نیست.'], 422);
        }

        // Find payment method name
        $paymentMethodName = '';
        foreach ($activeGateways as $gw) {
            if ($gw['id'] === $request->payment_method) {
                $paymentMethodName = $gw['name'];
                break;
            }
        }

        // Load cart
        $cart = session('cart', []);
        if (empty($cart)) {
            return response()->json(['success' => false, 'message' => 'سبد خرید شما خالی است.'], 422);
        }

        $variantIds = array_column($cart, 'variant_id');
        $variants   = ProductVariant::with('product')
            ->whereIn('id', $variantIds)
            ->get()
            ->keyBy('id');

        // Calculate cart totals
        $subtotal        = 0;
        $productDiscount = 0;
        $orderItems      = [];

        foreach ($cart as $row) {
            $variant = $variants->get($row['variant_id'] ?? 0);
            if (!$variant || !$variant->product) continue;

            $qty           = (int) $row['qty'];
            $originalPrice = (int) ($variant->price ?? 0);
            $finalPrice    = (int) ($variant->discount_price ?? $originalPrice);

            $subtotal        += $originalPrice * $qty;
            $productDiscount += ($originalPrice - $finalPrice) * $qty;

            $orderItems[] = [
                'product_id'    => $variant->product_id,
                'variant_id'    => $variant->id,
                'product_title' => $variant->product->title,
                'variant_title' => $variant->title ?? null,
                'original_price'=> $originalPrice,
                'final_price'   => $finalPrice,
                'qty'           => $qty,
                'subtotal'      => $finalPrice * $qty,
            ];
        }

        if (empty($orderItems)) {
            return response()->json(['success' => false, 'message' => 'محصولات سبد خرید معتبر نیستند.'], 422);
        }

        // Coupon
        $couponCode     = null;
        $couponDiscount = 0;
        $appliedCoupon  = session('applied_coupon');

        if ($appliedCoupon && isset($appliedCoupon['code'])) {
            $dc = DiscountCode::where('code', $appliedCoupon['code'])->first();
            if ($dc && $dc->isValidForUser(Auth::id())) {
                $couponCode     = $appliedCoupon['code'];
                $couponDiscount = (int) $appliedCoupon['discount'];
            }
        }

        // Totals
        $totalAmount = ($subtotal - $productDiscount - $couponDiscount) + $shippingCostUsed;
        $totalAmount = max(0, $totalAmount);

        // Wallet
        $walletUsed = 0;
        if ($request->boolean('use_wallet')) {
            $wallet     = Wallet::forUser(Auth::user());
            $walletUsed = min((int) $wallet->balance, $totalAmount);
        }

        $payableAmount = max(0, $totalAmount - $walletUsed);

        // DB transaction
        try {
            $orderReferrer = $this->resolveOrderReferrer();

            $order = DB::transaction(function () use (
                $subtotal, $productDiscount, $couponCode, $couponDiscount,
                $shippingCostUsed, $walletUsed, $totalAmount, $payableAmount,
                $shippingMethod, $address, $request, $paymentMethodName,
                $orderItems, $orderReferrer
            ) {
                $order = Order::create([
                    'order_number'         => Order::generateOrderNumber(),
                    'shamsi_date'          => Order::toJalaliString(now()),
                    'user_id'              => Auth::id(),
                    'status'               => 'failed',
                    'subtotal'             => $subtotal,
                    'product_discount'     => $productDiscount,
                    'coupon_code'          => $couponCode,
                    'coupon_discount'      => $couponDiscount,
                    'shipping_cost'        => $shippingCostUsed,
                    'wallet_used'          => $walletUsed,
                    'total_amount'         => $totalAmount,
                    'payable_amount'       => $payableAmount,
                    'shipping_method_id'   => $shippingMethod->id,
                    'shipping_method_name' => $shippingMethod->name,
                    'shipping_method_type' => $shippingMethod->type,
                    'address_id'           => $address->id,
                    'address_snapshot'     => $address->only(['name', 'province', 'city', 'postal_code', 'address']),
                    'payment_method'       => $request->payment_method,
                    'payment_method_name'  => $paymentMethodName,
                    'referrer'             => $orderReferrer,
                ]);

                foreach ($orderItems as $item) {
                    OrderItem::create(array_merge($item, ['order_id' => $order->id]));
                }

                Transaction::create([
                    'order_id'     => $order->id,
                    'user_id'      => Auth::id(),
                    'gateway'      => $request->payment_method,
                    'gateway_name' => $paymentMethodName,
                    'amount'       => $payableAmount,
                    'status'       => 'pending',
                ]);

                // Increment coupon usage
                if ($couponCode) {
                    DiscountCode::where('code', $couponCode)->increment('used_count');
                }

                // Deduct wallet
                if ($walletUsed > 0) {
                    $wallet = Wallet::forUser(Auth::user());
                    $wallet->debit($walletUsed, 'کسر اعتبار برای سفارش #' . $order->order_number, Auth::id());
                }

                return $order;
            });
        } catch (\Exception $e) {
            return response()->json(['success' => false, 'message' => 'خطا در ثبت سفارش: ' . $e->getMessage()], 500);
        }

        // Reload order with transaction
        $order->load('transactions');
        $transaction = $order->transactions->first();

        // If payable amount is 0, mark as paid immediately
        if ($payableAmount == 0) {
            $order->update(['status' => 'paid', 'paid_at' => now()]);
            if ($transaction) {
                $transaction->update(['status' => 'success', 'paid_at' => now()]);
            }
            $order->load('items');
            $this->deductStock($order);
            $this->incrementSales($order);
            if ($order->shipping_method_type === 'amadast') {
                AmadastService::submitOrder($order);
            }
            $this->dispatchNewOrderSms($order);
            CustomerClubService::grantSpinForOrder($order);
            session()->forget(['cart', 'applied_coupon']);
            $this->clearVisitorReferrer();
            return response()->json(['success' => true, 'redirect' => route('checkout.success', $order)]);
        }

        // Zibal gateway
        if ($request->payment_method === 'zibal') {
            $isTestMode = (bool) Setting::get('zibal_test_mode', false);
            $merchant   = $isTestMode ? 'zibal' : trim((string) Setting::get('zibal_merchant', ''));
            $amountRial = $payableAmount * 10;

            if (!$isTestMode && $merchant === '') {
                $order->update(['status' => 'failed']);
                $transaction->update([
                    'status'        => 'failed',
                    'error_message' => 'کلید پذیرنده زیبال تنظیم نشده است.',
                ]);
                return response()->json(['success' => false, 'message' => 'درگاه پرداخت به‌درستی پیکربندی نشده است. با پشتیبانی تماس بگیرید.'], 500);
            }

            try {
                $resp = Http::withoutVerifying()
                    ->timeout(30)
                    ->post('https://gateway.zibal.ir/v1/request', [
                        'merchant'    => $merchant,
                        'amount'      => $amountRial,
                        'callbackUrl' => route('checkout.callback.zibal'),
                        'orderId'     => $order->order_number,
                        'mobile'      => Auth::user()->mobile ?? '',
                        'description' => 'سفارش ' . $order->order_number,
                    ]);

                $data   = $resp->json();
                $result = $data['result'] ?? null;

                if ($result == 100) {
                    $trackId = $data['trackId'];
                    $transaction->update(['track_id' => $trackId]);
                    return response()->json([
                        'success'  => true,
                        'redirect' => 'https://gateway.zibal.ir/start/' . $trackId,
                    ]);
                } else {
                    $order->update(['status' => 'failed']);
                    $transaction->update([
                        'status'        => 'failed',
                        'error_code'    => (string) $result,
                        'error_message' => $data['message'] ?? 'خطا در درگاه پرداخت',
                        'gateway_response' => $data,
                    ]);
                    return response()->json([
                        'success' => false,
                        'message' => 'خطا در اتصال به درگاه پرداخت: ' . ($data['message'] ?? 'خطای ناشناخته'),
                    ], 500);
                }
            } catch (\Exception $e) {
                $order->update(['status' => 'failed']);
                $transaction->update(['status' => 'failed', 'error_message' => $e->getMessage()]);
                return response()->json(['success' => false, 'message' => 'خطا در اتصال به درگاه پرداخت.'], 500);
            }
        }

        // Card-to-card
        if ($request->payment_method === 'card_to_card') {
            $order->update(['status' => 'paid']);
            $order->load('items');
            $this->incrementSales($order);
            $this->dispatchNewOrderSms($order);
            CustomerClubService::grantSpinForOrder($order);
            session()->forget(['cart', 'applied_coupon']);
            $this->clearVisitorReferrer();
            return response()->json(['success' => true, 'redirect' => route('checkout.success', $order)]);
        }

        // TorobPay installment gateway
        if ($request->payment_method === 'torobpay') {
            $torobPay = app(TorobPayService::class);

            if (!$torobPay->isConfigured()) {
                $order->update(['status' => 'failed']);
                $transaction->update([
                    'status'        => 'failed',
                    'error_message' => 'درگاه ترب‌پی پیکربندی نشده است.',
                ]);
                return response()->json([
                    'success' => false,
                    'message' => 'درگاه پرداخت به‌درستی پیکربندی نشده است. با پشتیبانی تماس بگیرید.',
                ], 500);
            }

            $returnUrl = route('checkout.callback.torobpay', ['order' => $order->order_number]);
            $result    = $torobPay->createPayment($order, $returnUrl);

            if (!($result['success'] ?? false)) {
                $order->update(['status' => 'failed']);
                $transaction->update([
                    'status'           => 'failed',
                    'track_id'         => $result['transactionId'] ?? null,
                    'error_message'    => $result['error'] ?? 'خطا در اتصال به درگاه ترب‌پی',
                    'gateway_response' => $result['raw'] ?? null,
                ]);

                if ($order->wallet_used > 0) {
                    try {
                        Wallet::forUser(Auth::user())->credit(
                            $order->wallet_used,
                            'بازگشت وجه کیف پول - سفارش #' . $order->order_number,
                            null
                        );
                    } catch (\Exception $e) {
                        // ignore
                    }
                }

                return response()->json([
                    'success' => false,
                    'message' => 'خطا در اتصال به درگاه پرداخت: ' . ($result['error'] ?? 'خطای ناشناخته'),
                ], 500);
            }

            $stockReducedEarly = false;
            if ((bool) Setting::get('torobpay_overselling_prevention', false)) {
                $order->load('items');
                $this->deductStock($order);
                $stockReducedEarly = true;
            }

            $transaction->update([
                'track_id'         => $result['transactionId'],
                'ref_number'       => $result['paymentToken'],
                'gateway_response' => [
                    'paymentToken'        => $result['paymentToken'],
                    'paymentPageUrl'      => $result['paymentPageUrl'],
                    'transactionId'       => $result['transactionId'],
                    'stock_reduced_early' => $stockReducedEarly,
                ],
            ]);

            return response()->json([
                'success'  => true,
                'redirect' => $result['paymentPageUrl'],
            ]);
        }

        // DigiPay installment / UPG gateway
        if ($request->payment_method === 'digipay') {
            $digiPay = app(DigiPayService::class);

            if (!$digiPay->isConfigured()) {
                $order->update(['status' => 'failed']);
                $transaction->update([
                    'status'        => 'failed',
                    'error_message' => 'درگاه دیجی‌پی پیکربندی نشده است.',
                ]);
                return response()->json([
                    'success' => false,
                    'message' => 'درگاه پرداخت به‌درستی پیکربندی نشده است. با پشتیبانی تماس بگیرید.',
                ], 500);
            }

            $returnUrl = route('checkout.callback.digipay', ['order' => $order->order_number]);
            $result    = $digiPay->createPayment($order, $returnUrl);

            if (!($result['success'] ?? false)) {
                $order->update(['status' => 'failed']);
                $transaction->update([
                    'status'           => 'failed',
                    'track_id'         => $result['providerId'] ?? null,
                    'error_message'    => $result['error'] ?? 'خطا در اتصال به درگاه دیجی‌پی',
                    'gateway_response' => $result['raw'] ?? null,
                ]);

                if ($order->wallet_used > 0) {
                    try {
                        Wallet::forUser(Auth::user())->credit(
                            $order->wallet_used,
                            'بازگشت وجه کیف پول - سفارش #' . $order->order_number,
                            null
                        );
                    } catch (\Exception $e) {
                        // ignore
                    }
                }

                return response()->json([
                    'success' => false,
                    'message' => 'خطا در اتصال به درگاه پرداخت: ' . ($result['error'] ?? 'خطای ناشناخته'),
                ], 500);
            }

            $stockReducedEarly = false;
            if ((bool) Setting::get('digipay_overselling_prevention', false)) {
                $order->load('items');
                $this->deductStock($order);
                $stockReducedEarly = true;
            }

            $transaction->update([
                'track_id'         => $result['providerId'],
                'ref_number'       => $result['ticket'],
                'gateway_response' => [
                    'ticket'              => $result['ticket'],
                    'redirectUrl'         => $result['redirectUrl'],
                    'providerId'          => $result['providerId'],
                    'stock_reduced_early' => $stockReducedEarly,
                ],
            ]);

            return response()->json([
                'success'  => true,
                'redirect' => $result['redirectUrl'],
            ]);
        }

        return response()->json(['success' => false, 'message' => 'روش پرداخت انتخابی پشتیبانی نمی‌شود.'], 422);
    }

    public function digipayCallback(Request $request, DigiPayService $digiPay)
    {
        $orderNumber  = $request->query('order') ?: $request->input('order');
        $trackingCode = $request->input('trackingCode') ?: $request->query('trackingCode');
        $providerId   = $request->input('providerId') ?: $request->query('providerId');
        $type         = $request->input('type') ?? $request->query('type');
        $resultCode   = $request->input('result') ?? $request->query('result');

        $order = null;
        if ($orderNumber) {
            $order = Order::where('order_number', $orderNumber)
                ->where('payment_method', 'digipay')
                ->first();
        }

        if (!$order && $providerId) {
            $txLookup = Transaction::where('gateway', 'digipay')
                ->where('track_id', $providerId)
                ->latest('id')
                ->first();
            $order = $txLookup?->order;
        }

        if (!$order) {
            return redirect()->route('checkout.failed')->with('error', 'سفارش یافت نشد.');
        }

        $transaction = Transaction::where('order_id', $order->id)
            ->where('gateway', 'digipay')
            ->latest('id')
            ->first();

        if (!$transaction) {
            return redirect()->route('checkout.failed', ['order' => $order->order_number])
                ->with('error', 'تراکنش یافت نشد.');
        }

        if ($order->status === 'paid' || $transaction->status === 'success') {
            return redirect()->route('checkout.success', $order);
        }

        $gatewayData = is_array($transaction->gateway_response) ? $transaction->gateway_response : [];
        $providerId  = $providerId ?: ($gatewayData['providerId'] ?? $transaction->track_id);

        $failMessage = function (string $message) use ($order, $transaction, $gatewayData) {
            $order->update(['status' => 'failed']);
            $transaction->update([
                'status'           => 'failed',
                'error_message'    => $message,
                'gateway_response' => array_merge($gatewayData, ['callback' => request()->all()]),
            ]);

            if ($order->wallet_used > 0) {
                try {
                    Wallet::forUser($order->user)->credit(
                        $order->wallet_used,
                        'بازگشت وجه کیف پول - سفارش #' . $order->order_number,
                        null
                    );
                } catch (\Exception $e) {
                    // ignore
                }
            }

            if (!empty($gatewayData['stock_reduced_early'])) {
                try {
                    $order->load('items');
                    foreach ($order->items as $item) {
                        if ($item->variant_id) {
                            ProductVariant::where('id', $item->variant_id)->increment('stock', $item->qty);
                        }
                    }
                } catch (\Exception $e) {
                    // ignore
                }
            }

            $tpl = Setting::get('digipay_failed_message', $message);
            $msg = str_replace('{fault}', $message, $tpl);

            return redirect()->route('checkout.failed', ['order' => $order->order_number])
                ->with('error', $msg);
        };

        // result=0 means success in DigiPay; missing result → still try verify if tracking present
        if ($resultCode !== null && $resultCode !== '' && (int) $resultCode !== 0) {
            $tpl = Setting::get(
                'digipay_cancelled_message',
                'پرداخت به دلیل انصراف یا ناموفق بودن ناتمام باقی ماند.'
            );
            return $failMessage($tpl);
        }

        if (!$trackingCode || !$providerId) {
            return $failMessage('اطلاعات بازگشت از درگاه ناقص است.');
        }

        $paymentType = is_numeric($type) ? (int) $type : DigiPayService::TICKET_TYPE_UPG;

        $verify = $digiPay->verifyPayment((string) $trackingCode, (string) $providerId, $paymentType);
        if (!($verify['success'] ?? false)) {
            return $failMessage($verify['error'] ?? 'پرداخت تأیید نشد.');
        }

        DB::transaction(function () use ($order, $transaction, $verify, $gatewayData, $trackingCode, $providerId, $paymentType) {
            $order->update([
                'status'  => 'paid',
                'paid_at' => now(),
            ]);
            $transaction->update([
                'status'           => 'success',
                'ref_number'       => $trackingCode,
                'track_id'         => $providerId,
                'paid_at'          => now(),
                'gateway_response' => array_merge($gatewayData, [
                    'trackingCode'  => $trackingCode,
                    'providerId'    => $providerId,
                    'payment_type'  => $paymentType,
                    'verify'        => $verify['raw'] ?? null,
                    'callback'      => request()->all(),
                ]),
            ]);
        });

        $order->load('items');
        if (empty($gatewayData['stock_reduced_early'])) {
            $this->deductStock($order);
        }
        $this->incrementSales($order);
        if ($order->shipping_method_type === 'amadast') {
            AmadastService::submitOrder($order);
        }
        $this->dispatchNewOrderSms($order);
        CustomerClubService::grantSpinForOrder($order);
        session()->forget(['cart', 'applied_coupon']);
        $this->clearVisitorReferrer();

        $successTpl = Setting::get(
            'digipay_success_message',
            'با تشکر از شما . سفارش شما با موفقیت پرداخت شد .'
        );
        $successMsg = str_replace(
            ['{trackingCode}', '{providerId}'],
            [(string) $trackingCode, (string) $providerId],
            $successTpl
        );

        return redirect()->route('checkout.success', $order)->with('success', $successMsg);
    }

    public function torobpayCallback(Request $request, TorobPayService $torobPay)
    {
        $orderNumber = $request->query('order') ?: $request->input('order');
        $state       = strtoupper((string) ($request->input('state') ?: $request->query('state') ?: ''));

        if (!$orderNumber) {
            return redirect()->route('checkout.failed')->with('error', 'شماره سفارش یافت نشد.');
        }

        $order = Order::where('order_number', $orderNumber)
            ->where('payment_method', 'torobpay')
            ->first();

        if (!$order) {
            return redirect()->route('checkout.failed')->with('error', 'سفارش یافت نشد.');
        }

        $transaction = Transaction::where('order_id', $order->id)
            ->where('gateway', 'torobpay')
            ->latest('id')
            ->first();

        if (!$transaction) {
            return redirect()->route('checkout.failed', ['order' => $order->order_number])
                ->with('error', 'تراکنش یافت نشد.');
        }

        // Already paid — idempotent success
        if ($order->status === 'paid' || $transaction->status === 'success') {
            return redirect()->route('checkout.success', $order);
        }

        $gatewayData   = is_array($transaction->gateway_response) ? $transaction->gateway_response : [];
        $paymentToken  = $transaction->ref_number
            ?: ($gatewayData['paymentToken'] ?? null);

        $failMessage = function (string $message) use ($order, $transaction, $gatewayData) {
            $order->update(['status' => 'failed']);
            $transaction->update([
                'status'           => 'failed',
                'error_message'    => $message,
                'gateway_response' => array_merge($gatewayData, ['callback_state' => request()->all()]),
            ]);

            if ($order->wallet_used > 0) {
                try {
                    Wallet::forUser($order->user)->credit(
                        $order->wallet_used,
                        'بازگشت وجه کیف پول - سفارش #' . $order->order_number,
                        null
                    );
                } catch (\Exception $e) {
                    // ignore
                }
            }

            // Restore early-reduced stock if any
            if (!empty($gatewayData['stock_reduced_early'])) {
                try {
                    $order->load('items');
                    foreach ($order->items as $item) {
                        if ($item->variant_id) {
                            ProductVariant::where('id', $item->variant_id)->increment('stock', $item->qty);
                        }
                    }
                } catch (\Exception $e) {
                    // ignore
                }
            }

            $tpl = Setting::get('torobpay_failed_message', $message);
            $msg = str_replace('{fault}', $message, $tpl);

            return redirect()->route('checkout.failed', ['order' => $order->order_number])
                ->with('error', $msg);
        };

        if ($state === 'CANCELLED' || $state === 'CANCELED') {
            $tpl = Setting::get(
                'torobpay_cancelled_message',
                'پرداخت به دلیل انصراف شما ناتمام باقی ماند .'
            );
            return $failMessage($tpl);
        }

        if (!$paymentToken) {
            return $failMessage('توکن پرداخت نامعتبر است.');
        }

        $verify = $torobPay->verifyPayment($paymentToken);
        if (!($verify['success'] ?? false)) {
            $code = $verify['errorCode'] ?? '';
            $msg  = ($code === '1053')
                ? 'پرداخت ناموفق بود.'
                : ($verify['error'] ?? 'پرداخت تأیید نشد.');
            return $failMessage($msg);
        }

        // Browser may omit state=OK; trust verify success (plugin behavior)
        $settle = $torobPay->settlePayment($paymentToken);
        if (!($settle['success'] ?? false)) {
            $transaction->update([
                'gateway_response' => array_merge($gatewayData, [
                    'verify' => $verify['raw'] ?? null,
                    'settle' => $settle['raw'] ?? null,
                    'settle_failed' => true,
                ]),
                'error_message' => $settle['error'] ?? 'تسویه ناموفق بود.',
            ]);

            return redirect()->route('checkout.failed', ['order' => $order->order_number])
                ->with('error', 'پرداخت تأیید شد اما تسویه نهایی انجام نشد. با پشتیبانی تماس بگیرید.');
        }

        DB::transaction(function () use ($order, $transaction, $verify, $settle, $gatewayData, $paymentToken) {
            $order->update([
                'status'  => 'paid',
                'paid_at' => now(),
            ]);
            $transaction->update([
                'status'           => 'success',
                'ref_number'       => $paymentToken,
                'paid_at'          => now(),
                'gateway_response' => array_merge($gatewayData, [
                    'verify' => $verify['raw'] ?? null,
                    'settle' => $settle['raw'] ?? null,
                    'settled' => true,
                ]),
            ]);
        });

        $order->load('items');
        if (empty($gatewayData['stock_reduced_early'])) {
            $this->deductStock($order);
        }
        $this->incrementSales($order);
        if ($order->shipping_method_type === 'amadast') {
            AmadastService::submitOrder($order);
        }
        $this->dispatchNewOrderSms($order);
        CustomerClubService::grantSpinForOrder($order);
        session()->forget(['cart', 'applied_coupon']);
        $this->clearVisitorReferrer();

        $successTpl = Setting::get(
            'torobpay_success_message',
            'با تشکر از شما . سفارش شما با موفقیت پرداخت شد .'
        );
        $successMsg = str_replace(
            ['{referenceID}', '{transactionId}', '{paymentToken}'],
            [
                $transaction->track_id ?: $paymentToken,
                $transaction->track_id ?: '',
                $paymentToken,
            ],
            $successTpl
        );

        return redirect()->route('checkout.success', $order)->with('success', $successMsg);
    }

    public function zibalCallback(Request $request)
    {
        $trackId = $request->input('trackId');
        $success = $request->input('success');

        $transaction = Transaction::where('track_id', $trackId)
            ->where('gateway', 'zibal')
            ->where('status', 'pending')
            ->first();

        if (!$transaction) {
            return redirect()->route('checkout.failed')->with('error', 'تراکنش یافت نشد.');
        }

        $order = $transaction->order;

        if ((int) $success !== 1) {
            $order->update(['status' => 'failed']);
            $transaction->update([
                'status'        => 'failed',
                'error_code'    => (string) $request->input('status', ''),
                'error_message' => 'پرداخت توسط کاربر لغو شد.',
            ]);
            return redirect()->route('checkout.failed', ['order' => $order->order_number]);
        }

        // Verify with Zibal — must use the same merchant that created the transaction
        $isTestMode = (bool) Setting::get('zibal_test_mode', false);
        $merchant   = $isTestMode ? 'zibal' : trim((string) Setting::get('zibal_merchant', ''));

        try {
            $resp = Http::withoutVerifying()
                ->timeout(30)
                ->post('https://gateway.zibal.ir/v1/verify', [
                    'merchant' => $merchant,
                    'trackId'  => $trackId,
                ]);

            $data   = $resp->json();
            $result = $data['result'] ?? null;

            if ($result == 100 || $result == 201) {
                DB::transaction(function () use ($order, $transaction, $data) {
                    $order->update([
                        'status'  => 'paid',
                        'paid_at' => now(),
                    ]);
                    $transaction->update([
                        'status'           => 'success',
                        'ref_number'       => (string) ($data['refNumber'] ?? ''),
                        'card_number'      => $data['cardNumber'] ?? null,
                        'paid_at'          => now(),
                        'gateway_response' => $data,
                    ]);
                });

                $order->load('items');
                $this->deductStock($order);
                $this->incrementSales($order);
                if ($order->shipping_method_type === 'amadast') {
                    AmadastService::submitOrder($order);
                }
                $this->dispatchNewOrderSms($order);
                CustomerClubService::grantSpinForOrder($order);
                session()->forget(['cart', 'applied_coupon']);
            $this->clearVisitorReferrer();
                return redirect()->route('checkout.success', $order);
            } else {
                $order->update(['status' => 'failed']);
                $transaction->update([
                    'status'           => 'failed',
                    'error_code'       => (string) $result,
                    'error_message'    => $data['message'] ?? 'خطا در تأیید پرداخت',
                    'gateway_response' => $data,
                ]);

                // Refund wallet if was used
                if ($order->wallet_used > 0) {
                    try {
                        $wallet = Wallet::forUser($order->user);
                        $wallet->credit($order->wallet_used, 'بازگشت وجه کیف پول - سفارش #' . $order->order_number, null);
                    } catch (\Exception $e) {
                        // log silently
                    }
                }

                return redirect()->route('checkout.failed', ['order' => $order->order_number]);
            }
        } catch (\Exception $e) {
            $order->update(['status' => 'failed']);
            $transaction->update(['status' => 'failed', 'error_message' => $e->getMessage()]);

            // Refund wallet if was used
            if ($order->wallet_used > 0) {
                try {
                    $wallet = Wallet::forUser($order->user);
                    $wallet->credit($order->wallet_used, 'بازگشت وجه کیف پول - سفارش #' . $order->order_number, null);
                } catch (\Exception $ex) {
                    // log silently
                }
            }

            return redirect()->route('checkout.failed', ['order' => $order->order_number]);
        }
    }

    public function paymentSuccess(Order $order)
    {
        if ($order->user_id !== Auth::id()) {
            abort(403);
        }

        $order->load(['items.product', 'transactions']);

        return view('site.payment.success', compact('order'));
    }

    public function paymentFailed(Request $request)
    {
        $order = null;

        if ($request->has('order')) {
            $found = Order::where('order_number', $request->input('order'))->first();
            if ($found && Auth::check() && $found->user_id === Auth::id()) {
                $order = $found;
            }
        }

        return view('site.payment.failed', compact('order'));
    }

    private function dispatchNewOrderSms(Order $order): void
    {
        $order->loadMissing('user');
        $user = $order->user;

        PayamMatni::sendIfEnabled(
            $user->mobile,
            'sms_new_order_user_enabled',
            'sms_new_order_user_text',
            [
                'order_number' => $order->order_number,
                'first_name'   => $user->first_name,
                'last_name'    => $user->last_name,
                'total_amount' => number_format($order->payable_amount),
            ]
        );

        $adminMobiles = array_filter(array_map('trim', explode(',', \App\Models\Setting::get('sms_admin_mobile', ''))));
        foreach ($adminMobiles as $adminMobile) {
            PayamMatni::sendIfEnabled(
                $adminMobile,
                'sms_new_order_admin_enabled',
                'sms_new_order_admin_text',
                [
                    'order_number' => $order->order_number,
                    'total_amount' => number_format($order->payable_amount),
                    'first_name'   => $user->first_name,
                    'last_name'    => $user->last_name,
                ]
            );
        }
    }

    private function deductStock(Order $order): void
    {
        foreach ($order->items as $item) {
            if ($item->variant_id) {
                ProductVariant::where('id', $item->variant_id)
                    ->where('stock', '>', 0)
                    ->decrement('stock', $item->qty);
            }
        }
    }

    private function incrementSales(Order $order): void
    {
        foreach ($order->items as $item) {
            if ($item->product_id) {
                Product::where('id', $item->product_id)
                    ->increment('sales', $item->qty);
            }
        }
    }

    public function ajaxAddAddress(Request $request)
    {
        if (!Auth::check()) {
            return response()->json(['success' => false, 'message' => 'لطفاً ابتدا وارد شوید.'], 401);
        }

        $validator = Validator::make($request->all(), [
            'name'        => 'required|string|max:100',
            'province'    => 'required|string|max:100',
            'city'        => 'required|string|max:100',
            'postal_code' => ['required', 'bail', 'numeric', 'digits:10'],
            'address'     => 'required|string|max:500',
        ], [
            'name.required'        => 'نام آدرس الزامی است.',
            'province.required'    => 'انتخاب استان الزامی است.',
            'city.required'        => 'انتخاب شهر الزامی است.',
            'postal_code.required' => 'کد پستی الزامی است.',
            'postal_code.numeric'  => 'لطفا کد پستی را بصورت عددی وارد کنید',
            'postal_code.digits'   => 'کد پستی باید 10 رقم باشد',
            'address.required'     => 'آدرس کامل الزامی است.',
        ]);

        if ($validator->fails()) {
            return response()->json(['success' => false, 'errors' => $validator->errors()], 422);
        }

        if (UserAddress::where('user_id', Auth::id())->where('name', $request->name)->exists()) {
            return response()->json(['success' => false, 'errors' => ['name' => ['این نام آدرس قبلاً ثبت شده است.']]], 422);
        }

        $addr = UserAddress::create([
            'user_id'     => Auth::id(),
            'name'        => $request->name,
            'province'    => $request->province,
            'city'        => $request->city,
            'postal_code' => $request->postal_code,
            'address'     => $request->address,
        ]);

        return response()->json(['success' => true, 'address' => $addr]);
    }

    /**
     * Referrer for THIS order only (current visit session).
     * Never falls back to a permanent user-level referrer.
     */
    private function resolveOrderReferrer(): ?string
    {
        $ref = trim((string) session(CaptureVisitorReferrer::SESSION_KEY, ''));
        if ($ref === '') {
            return CaptureVisitorReferrer::DIRECT;
        }

        return mb_substr($ref, 0, 2000);
    }

    private function clearVisitorReferrer(): void
    {
        session()->forget(CaptureVisitorReferrer::SESSION_KEY);
    }
}
