<?php

namespace App\Services;

use App\Models\Order;
use App\Models\OrderItem;
use App\Models\Payment;
use App\Models\Shipment;
use App\Models\Voucher;
use App\Models\Address;
use App\Models\CartItem;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\DB;
use App\Services\ShippingService;

class OrderService
{
    protected $productService;
    protected $cartService;
    protected $shippingService;

    public function __construct(ProductService $productService, CartService $cartService, ShippingService $shippingService)
    {
        $this->productService = $productService;
        $this->cartService = $cartService;
        $this->shippingService = $shippingService;
    }

    public function createOrder(
        int $userId,
        ?int $addressId,
        string $courier,
        string $service,
        ?string $voucherCode = null,
        string $paymentMethod = 'midtrans',
        ?string $selectedItems = null,
        string $paymentType = 'full',
        string $shippingMethod = 'courier',
        ?array $customFormData = null
    ): Order {
        return DB::transaction(function() use ($userId, $addressId, $courier, $service, $voucherCode, $paymentMethod, $selectedItems, $paymentType, $shippingMethod, $customFormData) {
            if ($selectedItems && str_starts_with($selectedItems, 'buy_now:')) {
                $parts = explode(':', $selectedItems);
                $productId = $parts[1] ?? null;
                $variantId = $parts[2] ?? null;
                $qty = (int)($parts[3] ?? 1);
                $isFlashSaleRequest = isset($parts[4]) ? $parts[4] === '1' : false;
                
                $product = \App\Models\Product::findOrFail($productId);
                $variant = $variantId ? \App\Models\ProductVariant::find($variantId) : null;
                
                $price = $product->price;
                $isFlashSale = false;
                
                if ($isFlashSaleRequest) {
                    $now = now();
                    $flashSaleProduct = $product->flashSaleProducts()
                        ->where(function($q) use ($variantId) {
                            if ($variantId) {
                                $q->where('variant_id', $variantId);
                            } else {
                                $q->whereNull('variant_id');
                            }
                        })
                        ->whereHas('flashSale', function ($query) use ($now) {
                            $query->where('is_active', true)
                                ->where('start_time', '<=', $now)
                                ->where('end_time', '>=', $now);
                        })
                        ->first();

                    if ($flashSaleProduct) {
                        $price = $flashSaleProduct->flash_sale_price;
                        $isFlashSale = true;
                    }
                }
                
                if (!$isFlashSale && $product->discount_percent > 0) {
                    $price = $product->price - ($product->price * $product->discount_percent / 100);
                }
                
                if ($variant && !$isFlashSale && $variant->price) {
                    $price = $variant->price;
                    if ($product->discount_percent > 0) {
                        $price = $variant->price - ($variant->price * $product->discount_percent / 100);
                    }
                }

                $item = new \App\Models\CartItem([
                    'id' => 999999,
                    'product_id' => $product->id,
                    'variant_id' => $variant ? $variant->id : null,
                    'qty' => $qty,
                    'is_flash_sale' => $isFlashSale
                ]);
                $item->setRelation('product', $product);
                if ($variant) {
                    $item->setRelation('variant', $variant);
                }

                $cart = new \App\Models\Cart();
                $cart->setRelation('items', collect([$item]));
            } else {
                $cart = $this->cartService->getCartDetails($userId);
                if (!$cart || $cart->items->isEmpty()) {
                    throw new \Exception("Your cart is empty.");
                }

                if ($selectedItems) {
                    $selectedItemIds = explode(',', $selectedItems);
                    $cart->setRelation('items', $cart->items->filter(function($item) use ($selectedItemIds) {
                        return in_array($item->id, $selectedItemIds);
                    }));
                    if ($cart->items->isEmpty()) {
                        throw new \Exception("Selected items are not in your cart.");
                    }
                }
            }

            // 1. Check Product Type & Minimum Purchase Validation
            $hasPhysical = false;
            foreach ($cart->items as $item) {
                if ($item->qty < $item->product->min_purchase) {
                    throw new \Exception("Minimal pembelian produk {$item->product->name} adalah {$item->product->min_purchase} pcs.");
                }
                if ($item->product->type === 'physical') {
                    $hasPhysical = true;
                }
            }

            // 2. Validate Courier if courier shipping is selected and order contains physical items
            if ($hasPhysical && $shippingMethod === 'courier') {
                $enabledCouriersStr = \App\Models\Setting::get('shipping_couriers_enabled', 'jne,pos,tiki,j&t,sicepat');
                $enabledCouriers = explode(',', $enabledCouriersStr);
                if (!in_array(strtolower($courier), $enabledCouriers)) {
                    throw new \Exception("Kurir " . strtoupper($courier) . " sedang dinonaktifkan oleh administrator.");
                }
            }

            // Get shipping address details
            if ($addressId) {
                $address = Address::where('user_id', $userId)->find($addressId);
                if ($address) {
                    $villagePart = $address->village_name ? "{$address->village_name}, " : "";
                    $subdistrictPart = $address->subdistrict_name ? "{$address->subdistrict_name}, " : "";
                    $fullAddressText = "{$address->receiver_name} ({$address->phone}) - {$address->full_address}, {$villagePart}{$subdistrictPart}{$address->city_name}, {$address->province_name}, {$address->postal_code}";
                } else {
                    $user = \App\Models\User::find($userId);
                    $fullAddressText = "Non-Fisik / Digital Delivery - Email: {$user->email}" . ($user->whatsapp ? " (WA: {$user->whatsapp})" : "");
                }
            } else {
                $user = \App\Models\User::find($userId);
                $fullAddressText = "Non-Fisik / Digital Delivery - Email: {$user->email}" . ($user->whatsapp ? " (WA: {$user->whatsapp})" : "");
            }

            // Calculate totals
            $subtotal = 0.00;
            $totalWeight = 0;
            $itemCount = 0;
            foreach ($cart->items as $item) {
                // Use dynamic item price (which handles variants and flash sales correctly)
                $price = $item->price;
                $weight = $item->variant && $item->variant->weight ? $item->variant->weight : $item->product->weight;
                $subtotal += ($price * $item->qty);
                $totalWeight += ($weight * $item->qty);
                $itemCount += $item->qty;
            }
            $totals = [
                'subtotal' => $subtotal,
                'total_weight' => $totalWeight,
                'item_count' => $itemCount
            ];
            
            // Calculate shipping cost using ShippingService
            $shippingCost = 0;
            if ($hasPhysical) {
                if ($shippingMethod === 'courier') {
                    $originCityId = (int) \App\Models\Setting::get('shipping_origin_city_id', 23);
                    $destinationCityId = $address->city_id;
                    $weight = max(100, $totals['total_weight']); // min 100g

                    $shippingCost = 15000; // Default fallback
                    try {
                        $costs = $this->shippingService->calculateCost(
                            $originCityId,
                            $destinationCityId,
                            $weight,
                            $courier,
                            $address->subdistrict_id
                        );

                        if (!empty($costs) && isset($costs[0]['costs'])) {
                            foreach ($costs[0]['costs'] as $costOption) {
                                if (strtolower($costOption['service']) === strtolower($service)) {
                                    $shippingCost = (int) ($costOption['cost'][0]['value'] ?? 15000);
                                    break;
                                }
                            }
                        }
                    } catch (\Exception $e) {
                        // Fallback to flat rate
                        $weightInKg = max(0.1, $totals['total_weight'] / 1000);
                        $shippingCost = ceil($weightInKg) * 15000;
                    }
                } elseif ($shippingMethod === 'custom') {
                    $isCustomActive = \App\Models\Setting::get('shipping_alternative_active', 'true') === 'true';
                    if (!$isCustomActive) {
                        throw new \Exception("Metode pengiriman alternatif sedang dinonaktifkan oleh administrator.");
                    }

                    $shippingCost = 15000;
                    $servicesJson = \App\Models\Setting::get('shipping_alternative_services', '[]');
                    $services = json_decode($servicesJson, true);
                    if (is_array($services)) {
                        foreach ($services as $srv) {
                            if (isset($srv['service_name']) && $srv['service_name'] === $service) {
                                $shippingCost = (int) ($srv['cost'] ?? 15000);
                                break;
                            }
                        }
                    }
                } else {
                    $isPickupActive = \App\Models\Setting::get('shipping_self_pickup_active', 'true') === 'true';
                    if (!$isPickupActive) {
                        throw new \Exception("Metode pengiriman Ambil Sendiri sedang dinonaktifkan oleh administrator.");
                    }
                    $shippingCost = 0; // Self pickup
                }
            }

            // Apply Voucher
            $discount = 0.00;
            $voucherId = null;
            if ($voucherCode) {
                $voucher = Voucher::where('code', $voucherCode)->first();
                if ($voucher && $voucher->isValid()) {
                    $discount = $voucher->calculateDiscount($totals['subtotal']);
                    if ($discount > 0) {
                        $voucherId = $voucher->id;
                        $voucher->decrement('stock');
                    }
                }
            }

            // Calculate Tax
            $taxAmount = 0.00;
            $taxActive = \App\Models\Setting::get('tax_active', 'true') === 'true';
            if ($taxActive) {
                $taxPercent = (float) \App\Models\Setting::get('tax_percent', '11');
                $taxableAmount = max(0.00, $totals['subtotal'] - $discount);
                $taxAmount = round(($taxableAmount * $taxPercent) / 100, 2);
            }

            $grandTotal = $totals['subtotal'] + $shippingCost - $discount + $taxAmount;

            // Handle Down Payment (DP) Calculations
            $dpAmount = null;
            $remainingPayment = null;
            if ($paymentType === 'dp') {
                $isDpActive = \App\Models\Setting::get('payment_dp_active', 'true') === 'true';
                if (!$isDpActive) {
                    throw new \Exception("Opsi pembayaran DP 50% sedang dinonaktifkan oleh administrator.");
                }
                foreach ($cart->items as $item) {
                    if (!$item->product->allow_dp) {
                        throw new \Exception("Produk '{$item->product->name}' tidak mendukung pembayaran Down Payment (DP).");
                    }
                }
                $dpPercentage = (int) \App\Models\Setting::get('dp_percentage', 50);
                $dpAmount = round(($grandTotal * $dpPercentage) / 100);
                $remainingPayment = $grandTotal - $dpAmount;
            }

            // Generate unique invoice number
            $invoiceNumber = 'INV/' . date('Ymd') . '/' . strtoupper(Str::random(6));

            // Create Order
            $order = Order::create([
                'user_id' => $userId,
                'invoice_number' => $invoiceNumber,
                'status' => 'pending',
                'total' => $grandTotal,
                'shipping_cost' => $shippingCost,
                'tax_amount' => $taxAmount,
                'voucher_id' => $voucherId,
                'discount_amount' => $discount,
                'shipping_address' => $fullAddressText,
                'payment_type' => $paymentType,
                'dp_amount' => $dpAmount,
                'remaining_payment' => $remainingPayment,
                'dp_status' => 'unpaid'
            ]);

            // Create Order Items and Deduct Stock
            foreach ($cart->items as $item) {
                $price = $item->price;

                $itemFormData = null;
                if ($customFormData) {
                    if (isset($customFormData[$item->id])) {
                        $itemFormData = $customFormData[$item->id];
                    } elseif (isset($customFormData[$item->product_id])) {
                        $itemFormData = $customFormData[$item->product_id];
                    }
                }

                OrderItem::create([
                    'order_id' => $order->id,
                    'product_id' => $item->product_id,
                    'variant_id' => $item->variant_id,
                    'qty' => $item->qty,
                    'price' => $price,
                    'is_flash_sale' => $item->is_flash_sale,
                    'custom_form_data' => $itemFormData
                ]);

                // Deduct stock
                $this->productService->adjustStock(
                    $item->product_id,
                    $item->variant_id,
                    -$item->qty,
                    'out',
                    "Order: {$invoiceNumber}"
                );

                // Deduct flash sale stock and increase sold if applicable
                if ($item->is_flash_sale) {
                    $now = now();
                    $flashSaleProduct = $item->product->flashSaleProducts()
                        ->where(function($q) use ($item) {
                            if ($item->variant_id) {
                                $q->where('variant_id', $item->variant_id);
                            } else {
                                $q->whereNull('variant_id');
                            }
                        })
                        ->whereHas('flashSale', function ($query) use ($now) {
                            $query->where('is_active', true)
                                ->where('start_time', '<=', $now)
                                ->where('end_time', '>=', $now);
                        })
                        ->first();
                    if (!$flashSaleProduct) {
                        $flashSaleProduct = $item->product->active_flash_sale;
                    }
                    if ($flashSaleProduct) {
                        $flashSaleProduct->decrement('stock', $item->qty);
                        $flashSaleProduct->increment('sold', $item->qty);
                    }
                }
            }

            // Determine display payment method
            $paymentMethodLabel = 'Midtrans / Gateway';
            if ($paymentMethod === 'duitku') {
                $paymentMethodLabel = 'Duitku / Gateway';
            } elseif ($paymentMethod === 'tripay') {
                $paymentMethodLabel = 'Tripay / Gateway';
            } elseif ($paymentMethod === 'manual_bank') {
                $paymentMethodLabel = 'Transfer Bank Manual';
            } elseif ($paymentMethod === 'manual_qris') {
                $paymentMethodLabel = 'QRIS Manual';
            }

            if ($paymentType === 'dp') {
                $paymentMethodLabel .= ' (DP)';
            }

            // Create Payment record placeholder
            Payment::create([
                'order_id' => $order->id,
                'payment_method' => $paymentMethodLabel,
                'status' => 'pending'
            ]);

            // Create Shipment record placeholder
            $courierName = $hasPhysical ? ($shippingMethod === 'courier' ? $courier : $shippingMethod) : 'DIGITAL';
            $serviceName = $hasPhysical ? ($shippingMethod === 'courier' ? $service : 'NONE') : 'NONE';
            Shipment::create([
                'order_id' => $order->id,
                'courier' => strtoupper($courierName),
                'service' => strtoupper($serviceName),
                'status' => $hasPhysical ? 'pending' : 'delivered'
            ]);

            // Clear Cart
            if ($selectedItems) {
                if (str_starts_with($selectedItems, 'buy_now:')) {
                    // Direct checkout, do not clear database cart
                } else {
                    $selectedItemIds = explode(',', $selectedItems);
                    CartItem::whereIn('id', $selectedItemIds)->delete();
                }
            } else {
                $this->cartService->clearCart($userId);
            }
            return $order;
        });
    }

    public function updateStatus(Order $order, string $newStatus, ?string $trackingNumber = null, ?array $paymentDetails = null, bool $isRemaining = false): Order
    {
        return DB::transaction(function() use ($order, $newStatus, $trackingNumber, $paymentDetails, $isRemaining) {
            $oldStatus = $order->status;
            
            // Manage Down Payment (DP) Status
            if ($newStatus === 'paid' || $newStatus === 'processing') {
                if ($order->payment_type === 'dp') {
                    $order->dp_status = 'paid';
                }
            }

            if ($oldStatus === $newStatus) {
                // Save any DP status changes even if status remains the same
                $order->save();
                return $order;
            }

            $order->status = $newStatus;
            $order->save();

            // Create subscriptions if order becomes paid/processing/completed and not already created
            if (in_array($newStatus, ['paid', 'processing', 'completed']) && !in_array($oldStatus, ['paid', 'processing', 'completed'])) {
                foreach ($order->items as $item) {
                    if ($item->product && $item->product->type === 'subscription') {
                        $existingSub = \App\Models\Subscription::where('order_id', $order->id)
                            ->where('product_id', $item->product_id)
                            ->first();
                            
                        if (!$existingSub) {
                            $period = $item->product->subscription_period === 'year' ? 'year' : 'month';
                            $endsAt = $period === 'year' ? now()->addYear() : now()->addMonth();
                            
                            \App\Models\Subscription::create([
                                'user_id' => $order->user_id,
                                'order_id' => $order->id,
                                'product_id' => $item->product_id,
                                'status' => 'active',
                                'billing_cycle' => $period,
                                'starts_at' => now(),
                                'ends_at' => $endsAt,
                                'custom_form_data' => $item->custom_form_data
                            ]);
                        }
                    }
                }
            }

            // If cancelled, restore stock
            if ($newStatus === 'cancelled' && $oldStatus !== 'cancelled') {
                foreach ($order->items as $item) {
                    $this->productService->adjustStock(
                        $item->product_id,
                        $item->variant_id,
                        $item->qty,
                        'adjustment',
                        "Restore stock for cancelled order: {$order->invoice_number}"
                    );

                    // Restore flash sale stock if applicable
                    if ($item->is_flash_sale) {
                        $flashSaleProduct = \App\Models\FlashSaleProduct::where('product_id', $item->product_id)
                            ->where(function($q) use ($item) {
                                if ($item->variant_id) {
                                    $q->where('variant_id', $item->variant_id);
                                } else {
                                    $q->whereNull('variant_id');
                                }
                            })
                            ->whereHas('flashSale', function($query) use ($order) {
                                $query->where('start_time', '<=', $order->created_at)
                                      ->where('end_time', '>=', $order->created_at);
                            })
                            ->first();
                        if ($flashSaleProduct) {
                            $flashSaleProduct->increment('stock', $item->qty);
                            $flashSaleProduct->decrement('sold', $item->qty);
                        }
                    }
                }
                
                // Restore voucher stock if applied
                if ($order->voucher_id) {
                    $order->voucher->increment('stock');
                }
            }

            // Update associated tables
            if ($paymentDetails) {
                $payment = $order->payment()->firstOrCreate([]);
                $payment->update($paymentDetails);
            }

            if ($newStatus === 'shipped') {
                $shipment = $order->shipment()->firstOrCreate([]);
                $shipment->update([
                    'tracking_number' => $trackingNumber ?? $shipment->tracking_number,
                    'status' => 'shipped'
                ]);
            } elseif ($newStatus === 'delivered') {
                $shipment = $order->shipment()->firstOrCreate([]);
                $shipment->update([
                    'status' => 'delivered'
                ]);
            }

            // Create affiliate commission if referrer exists and order is paid/processing
            if (in_array($newStatus, ['paid', 'processing']) && !$order->affiliateCommissions()->exists()) {
                $buyer = $order->user;
                if ($buyer && $buyer->referred_by) {
                    $commissionPercent = (int)\App\Models\Setting::get('affiliate_commission_percent', 5);
                    $netTotal = max(0, $order->total - $order->shipping_cost);
                    $commissionAmount = round(($netTotal * $commissionPercent) / 100);
                    
                    if ($commissionAmount > 0) {
                        \App\Models\AffiliateCommission::create([
                            'affiliate_user_id' => $buyer->referred_by,
                            'buyer_id' => $buyer->id,
                            'order_id' => $order->id,
                            'commission_amount' => $commissionAmount,
                            'status' => 'pending'
                        ]);
                    }
                }
            }

            // Approve affiliate commission on order completion
            if ($newStatus === 'completed') {
                $order->affiliateCommissions()->update(['status' => 'approved']);
            }

            // Send WhatsApp Status Notification
            try {
                $user = $order->user()->first();
                if ($user && !empty($user->whatsapp)) {
                    $storeName = \App\Models\Setting::get('store_name', 'Toko LRV');
                    $amountPaid = $order->total;
                    if ($order->payment_type === 'dp') {
                        $amountPaid = $isRemaining ? $order->remaining_payment : $order->dp_amount;
                    }
                    $formattedAmount = number_format($amountPaid, 0, ',', '.');
                    $invoice = $order->invoice_number;
                    $name = $user->name;
                    $message = null;
                    
                    switch ($newStatus) {
                        case 'paid':
                            $paymentTypeLabel = $order->payment_type === 'dp' 
                                ? ($isRemaining ? "Pelunasan" : "Uang Muka (DP)")
                                : "Pembayaran";
                            $message = "Halo *{$name}*,\n\n"
                                     . "*{$paymentTypeLabel}* untuk pesanan *{$invoice}* sebesar *Rp {$formattedAmount}* telah kami terima dan terkonfirmasi.\n"
                                     . "Pesanan Anda akan segera diproses oleh toko kami. Terima kasih!";
                            break;
                            
                        case 'processing':
                            $message = "Halo *{$name}*,\n\n"
                                     . "Pesanan Anda dengan nomor Invoice *{$invoice}* sedang diproses dan dikemas oleh toko kami.";
                            break;
                            
                        case 'shipped':
                            $courierName = $order->shipment ? $order->shipment->courier : 'Ekspedisi';
                            $resi = $trackingNumber ?? ($order->shipment ? $order->shipment->tracking_number : '-');
                            $message = "Halo *{$name}*,\n\n"
                                     . "Pesanan Anda dengan nomor Invoice *{$invoice}* telah dikirim.\n"
                                     . "Kurir: *{$courierName}*\n"
                                     . "Nomor Resi: *{$resi}*\n\n"
                                     . "Anda dapat melacak status pengiriman Anda di halaman dashboard akun.";
                            break;
                            
                        case 'delivered':
                            $message = "Halo *{$name}*,\n\n"
                                     . "Pesanan Anda dengan nomor Invoice *{$invoice}* telah dinyatakan terkirim/diterima.\n"
                                     . "Terima kasih telah berbelanja di {$storeName}!";
                            break;
                            
                        case 'cancelled':
                            $message = "Halo *{$name}*,\n\n"
                                     . "Pesanan Anda dengan nomor Invoice *{$invoice}* telah dibatalkan.";
                            break;
                    }
                    
                    if ($message) {
                        \App\Services\WhatsAppService::sendMessage($user->whatsapp, $message);
                    }
                }
                
                // Admin notification for PAID orders
                if ($newStatus === 'paid') {
                    $storePhone = \App\Models\Setting::get('contact_phone');
                    if (!empty($storePhone)) {
                        $paymentMethodName = $order->payment ? $order->payment->payment_method : 'Gateway';
                        $customerName = $user ? $user->name : 'Pelanggan';
                        $customerWa = $user ? $user->whatsapp : '-';
                        $shippingAddress = $order->shipping_address;
                        
                        $paymentTypeLabel = $order->payment_type === 'dp' 
                            ? ($isRemaining ? "PELUNASAN SISA" : "UANG MUKA (DP)")
                            : "PENUH";
                        $amountPaid = $order->total;
                        if ($order->payment_type === 'dp') {
                            $amountPaid = $isRemaining ? $order->remaining_payment : $order->dp_amount;
                        }
                        $formattedAmount = number_format($amountPaid, 0, ',', '.');
                        
                        $adminMessage = "📢 *NOTIFIKASI PEMBAYARAN MASUK ({$paymentTypeLabel})* 📢\n\n"
                                       . "Invoice: *{$order->invoice_number}*\n"
                                       . "Pelanggan: *{$customerName}* ({$customerWa})\n"
                                       . "Jumlah Diterima: *Rp {$formattedAmount}*\n"
                                       . "Metode Pembayaran: *{$paymentMethodName}*\n\n"
                                       . "📍 *Alamat Pengiriman*:\n{$shippingAddress}\n\n"
                                       . "Silakan periksa dashboard admin untuk memproses pesanan ini.";
                                       
                        \App\Services\WhatsAppService::sendMessage($storePhone, $adminMessage);
                    }
                }
            } catch (\Exception $e) {
                \Illuminate\Support\Facades\Log::error("Failed to send WhatsApp status update alert: " . $e->getMessage());
            }

            return $order;
        });
    }
}
