<?php

/*
|--------------------------------------------------------------------------
| OwnStore - Build your own online store
| Author: TakfeDev (MKJUEL)
| All Rights Reserved
|--------------------------------------------------------------------------
*/

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Services\Payments\PaymentManager;
use App\Services\OrderNotificationService;
use App\Models\Product;
use App\Models\Order;
use App\Models\OrderItem;
use App\Models\Currency;
use App\Models\Cart;
use App\Models\PaymentGateway;
use App\Models\UserAddress; 
use Inertia\Inertia;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class PaymentProcessController extends Controller
{
    public function checkout(Request $request, PaymentManager $paymentManager)
    {
        $request->validate([
            'gateway' => 'required|string',
            'currency' => 'required|string|size:3',
            'product_id' => 'nullable|exists:products,id', 
            'cart_ids' => 'nullable|array', 
            'quantity' => 'nullable|integer|min:1',
            'coupon_code' => 'nullable|string',
            'shipping_address_id' => 'required|exists:user_addresses,id',
            'variations' => 'nullable|array'
        ]);

        if (!$request->product_id && empty($request->cart_ids)) {
            return back()->withErrors(['error' => 'No items selected for checkout.']);
        }

        // Store User ID outside the transaction closure for safety
        $userId = auth()->id();

        try {
            return DB::transaction(function () use ($request, $paymentManager, $userId) {
                
                // --- 1. STRICT CURRENCY VALIDATION ---
                $currencies = Currency::where('is_active', true)->get()->keyBy('code');

                if (!isset($currencies[$request->currency])) {
                    throw new \Exception("The currency '{$request->currency}' is not active in the system. Please contact the administrator.");
                }

                $address = UserAddress::with(['country', 'state', 'city'])->find($request->shipping_address_id);
                
                if (!$address || (int) $address->user_id !== (int) $userId) {
                    throw new \Exception("Invalid shipping address selected.");
                }

                $formattedAddress = "{$address->contact_name} (Phone: {$address->contact_phone})\n{$address->address_line_1}";
                if ($address->address_line_2) $formattedAddress .= ", {$address->address_line_2}";
                $formattedAddress .= "\n";
                if ($address->city) $formattedAddress .= "{$address->city?->name}, ";
                if ($address->state) $formattedAddress .= "{$address->state?->name}, ";
                
                $countryName = $address->country?->name ?? 'Unknown Country';
                $formattedAddress .= "{$countryName} - {$address->zip_code}";

                $itemsToProcess = [];
                if ($request->cart_ids) {
                    $cartItems = Cart::with('product.seller')->whereIn('id', $request->cart_ids)->where('user_id', $userId)->get();
                    foreach($cartItems as $cartItem) {
                        $itemsToProcess[] = [
                            'product' => $cartItem->product, 
                            'quantity' => $cartItem->quantity,
                            'variations' => $cartItem->selected_variations ?? []
                        ];
                    }
                } else {
                    $product = Product::with('seller')->findOrFail($request->product_id);
                    $itemsToProcess[] = [
                        'product' => $product, 
                        'quantity' => $request->quantity,
                        'variations' => $request->variations ?? []
                    ];
                }

                $totalFinalBaseUsd = 0;
                $ordersDataBySeller = []; 

                foreach ($itemsToProcess as $data) {
                    $product = $data['product'];
                    $qty = $data['quantity'];
                    $selectedVariations = $data['variations'];

                    // Prevent buying own product
                    if ((int) $userId === (int) $product->seller_id) {
                        throw new \Exception("You cannot purchase your own product: '{$product->title}'.");
                    }

                    if ($qty > $product->stock) {
                        throw new \Exception("Insufficient stock for '{$product->title}'. Only {$product->stock} available.");
                    }
                    if ($qty < $product->moq) {
                        throw new \Exception("Minimum order quantity for {$product->title} is {$product->moq}");
                    }

                    $product->decrement('stock', $qty);

                    $productCurrencyCode = $product->currency_code ?? 'USD';
                    $productRate = isset($currencies[$productCurrencyCode]) ? $currencies[$productCurrencyCode]->exchange_rate : 1;
                    
                    // --- BASE USD PRICE CALCULATION ---
                    $realBaseUsdPrice = ($product->original_price ?? $product->price) / $productRate;
                    
                    // --- VARIATION COST CALCULATION ---
                    foreach ($selectedVariations as $opt) {
                        if (!empty($opt['additional_price'])) {
                            $realBaseUsdPrice += ((float) $opt['additional_price'] / $productRate);
                        }
                    }

                    $baseSubtotalUsd = $realBaseUsdPrice * $qty;

                    // ADVANCED DISCOUNT MATH WITH GLOBAL FLASH SALE LOGIC
                    $discountAmountUsd = 0;
                    $minRequiredUsd = $product->min_order_amount_for_discount ?? 0;

                    // --- FETCH GLOBAL FLASH SALE ---
                    if (!$product->relationLoaded('seller')) {
                        $product->load('seller');
                    }
                    $sellerFlashSale = $product->seller->flash_sale_percentage ?? 0;
                    $productDiscount = $product->discount_percentage ?? 0;
                    
                    // Use whichever discount is higher
                    $effectiveDiscountPct = max($productDiscount, $sellerFlashSale);

                    if ($effectiveDiscountPct > 0 && $baseSubtotalUsd >= $minRequiredUsd) {
                        $applyDiscount = false;
                        if (!empty($product->coupon_code)) {
                            if (strtoupper($request->coupon_code) === strtoupper($product->coupon_code)) {
                                $applyDiscount = true;
                            }
                        } else {
                            $applyDiscount = true;
                        }

                        if ($applyDiscount) {
                            $rawDiscount = $baseSubtotalUsd * ($effectiveDiscountPct / 100);
                            $maxCapOriginal = $product->max_discount_percentage ?? 0;
                            $maxCapUsd = $maxCapOriginal > 0 ? ($maxCapOriginal / $productRate) : 0;
                            $discountAmountUsd = $maxCapUsd > 0 ? min($rawDiscount, $maxCapUsd) : $rawDiscount;
                        }
                    }

                    // ADVANCED SHIPPING MATH
                    if ($product->is_free_shipping) {
                        $realShippingUsd = 0;
                    } else {
                        $shippingRateUsd = ($product->original_shipping_charge ?? $product->shipping_charge ?? 0) / $productRate;
                        if ($product->shipping_charge_type === 'per_item') {
                            $realShippingUsd = $shippingRateUsd * $qty;
                        } else {
                            $realShippingUsd = $shippingRateUsd; // flat_rate
                        }
                    }

                    $itemFinalBaseUsd = $baseSubtotalUsd - $discountAmountUsd + $realShippingUsd;
                    $totalFinalBaseUsd += $itemFinalBaseUsd;

                    $sellerId = $product->seller_id;
                    if (!isset($ordersDataBySeller[$sellerId])) {
                        $ordersDataBySeller[$sellerId] = ['total_amount_usd' => 0, 'items' => []];
                    }
                    
                    $ordersDataBySeller[$sellerId]['total_amount_usd'] += $itemFinalBaseUsd;
                    $ordersDataBySeller[$sellerId]['items'][] = [
                        'product_id' => $product->id, 
                        'quantity' => $qty, 
                        'unit_price_usd' => $realBaseUsdPrice,
                        'selected_variations' => $selectedVariations
                    ];
                }

                if ($totalFinalBaseUsd <= 0) {
                    throw new \Exception("Order total must be greater than zero.");
                }

                // Apply Target Exchange Rate based on user's checkout currency
                $targetRate = $currencies[$request->currency]->exchange_rate;
                $convertedGrandTotal = round($totalFinalBaseUsd * $targetRate, 2);

                $gatewayModel = PaymentGateway::where('code', $request->gateway)->first();
                if (!$gatewayModel || !in_array($request->currency, $gatewayModel->supported_currencies ?? [])) {
                    throw new \Exception("Gateway does not support {$request->currency}");
                }

                $groupOrderNumber = 'ORD-' . strtoupper(uniqid());
                
                foreach ($ordersDataBySeller as $sellerId => $sellerData) {
                    $sellerConvertedTotal = round($sellerData['total_amount_usd'] * $targetRate, 2);
                    $order = Order::create([
                        'order_number' => $groupOrderNumber . '-' . $sellerId, 
                        'buyer_id' => $userId,
                        'seller_id' => $sellerId,
                        'total_amount' => $sellerConvertedTotal, 
                        'currency' => $request->currency,
                        'payment_gateway' => $request->gateway, 
                        'status' => 'pending', 
                        'shipping_address' => $formattedAddress
                    ]);

                    foreach ($sellerData['items'] as $item) {
                        OrderItem::create([
                            'order_id' => $order->id, 
                            'product_id' => $item['product_id'],
                            'quantity' => $item['quantity'], 
                            'unit_price' => round($item['unit_price_usd'] * $targetRate, 2), 
                            'selected_variations' => $item['selected_variations'] 
                        ]);
                    }
                }

                if ($request->cart_ids) {
                    Cart::whereIn('id', $request->cart_ids)->delete();
                }

                $processor = $paymentManager->build($request->gateway);
                $result = $processor->pay($convertedGrandTotal, $request->currency, [
                    'order_number' => $groupOrderNumber,
                    'user_id' => $userId,
                ]);

                return Inertia::location($result['url']);
            });

        } catch (\Exception $e) {
            return back()->withErrors(['error' => $e->getMessage()]);
        }
    }

    public function payPendingOrder(Request $request, Order $order, PaymentManager $paymentManager)
    {
        $request->validate(['gateway' => 'required|string']);

        if ((int) $order->buyer_id !== (int) auth()->id() || $order->status !== 'pending') {
            return back()->withErrors(['error' => 'Invalid order or order is already paid.']);
        }

        try {
            $currencyActive = Currency::where('code', $order->currency)->where('is_active', true)->exists();
            if (!$currencyActive) {
                throw new \Exception("The currency '{$order->currency}' is currently inactive. Please contact support.");
            }

            $gatewayModel = PaymentGateway::where('code', $request->gateway)->first();
            if (!$gatewayModel || !in_array($order->currency, $gatewayModel->supported_currencies ?? [])) {
                throw new \Exception("The selected gateway does not support {$order->currency}.");
            }

            $order->update(['payment_gateway' => $request->gateway]);

            $processor = $paymentManager->build($request->gateway);
            
            $result = $processor->pay($order->total_amount, $order->currency, [
                'order_number' => $order->order_number,
                'user_id' => auth()->id(),
            ]);

            return Inertia::location($result['url']);

        } catch (\Exception $e) {
            return back()->withErrors(['error' => $e->getMessage()]);
        }
    }

    public function callback(Request $request, string $gateway, PaymentManager $paymentManager, OrderNotificationService $notificationService)
    {
        try {
            $processor = $paymentManager->build($gateway);
            $result = $processor->verify($request->all());

            if ($result['success']) {
                $groupOrderNumber = $result['order_number']; 
                $newStatus = $result['payment_status'] ?? 'processing';
                $flashMessage = $result['message'] ?? 'Payment successful! Your order is now being processed by the supplier.';

                $orders = Order::where('order_number', 'like', $groupOrderNumber . '%')
                    ->where('status', 'pending')
                    ->get();

                foreach ($orders as $order) {
                    $order->update(['status' => $newStatus]);
                    
                    if (in_array($newStatus, ['processing', 'pending'])) {
                        $notificationService->sendOrderPlaced($order);
                    }
                }

                return redirect()->route('buyer.orders.index')->with('success', $flashMessage);
            }

            return redirect()->route('buyer.orders.index')->withErrors(['error' => 'Payment verification failed or was cancelled.']);

        } catch (\Exception $e) {
            Log::error("Payment Callback Error for gateway [{$gateway}]: " . $e->getMessage());
            return redirect()->route('buyer.orders.index')->withErrors(['error' => 'Something went wrong while verifying your payment. Please contact support.']);
        }
    }
}