<?php

namespace App\Services;

use App\Models\Cart;
use App\Models\CartItem;
use App\Models\Product;
use App\Models\ProductVariant;
use Illuminate\Support\Facades\DB;

class CartService
{
    public function getOrCreateCart(int $userId): Cart
    {
        return Cart::firstOrCreate(['user_id' => $userId]);
    }

    public function getCartDetails(int $userId)
    {
        $cart = $this->getOrCreateCart($userId);
        return Cart::where('id', $cart->id)
            ->with(['items.product.images', 'items.product.variants', 'items.variant'])
            ->first();
    }

    public function addItem(int $userId, int $productId, ?int $variantId, int $qty = 1, bool $isFlashSale = false): CartItem
    {
        return DB::transaction(function() use ($userId, $productId, $variantId, $qty, $isFlashSale) {
            $cart = $this->getOrCreateCart($userId);
            
            // Validate stock
            if ($isFlashSale) {
                $product = Product::findOrFail($productId);
                $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) {
                    $availableStock = $flashSaleProduct->stock - $flashSaleProduct->sold;
                    if ($availableStock <= 0) {
                        throw new \Exception("Flash sale stock is sold out.");
                    }
                } else {
                    $isFlashSale = false;
                }
            }

            if (!$isFlashSale) {
                if ($variantId) {
                    $variant = ProductVariant::findOrFail($variantId);
                    $availableStock = $variant->stock;
                } else {
                    $product = Product::findOrFail($productId);
                    $availableStock = $product->stock;
                }
            }

            $existingItem = CartItem::where('cart_id', $cart->id)
                ->where('product_id', $productId)
                ->where('variant_id', $variantId)
                ->where('is_flash_sale', $isFlashSale)
                ->first();

            $newQty = $qty;
            if ($isFlashSale) {
                $newQty = 1;
            } elseif ($existingItem) {
                $newQty += $existingItem->qty;
            }

            $product = Product::findOrFail($productId);
            $minPurchase = $product->min_purchase ?? 1;
            if (!$isFlashSale && $newQty < $minPurchase) {
                throw new \Exception("Minimum purchase for this product is {$minPurchase} items.");
            }

            if ($availableStock < $newQty) {
                throw new \Exception("Only {$availableStock} items available in stock.");
            }

            if ($existingItem) {
                $existingItem->qty = $newQty;
                $existingItem->save();
                return $existingItem;
            }

            return CartItem::create([
                'cart_id' => $cart->id,
                'product_id' => $productId,
                'variant_id' => $variantId,
                'qty' => $isFlashSale ? 1 : $qty,
                'is_flash_sale' => $isFlashSale
            ]);
        });
    }

    public function updateItemQty(int $userId, int $itemId, int $qty): CartItem
    {
        return DB::transaction(function() use ($userId, $itemId, $qty) {
            $cart = $this->getOrCreateCart($userId);
            $item = CartItem::where('cart_id', $cart->id)->findOrFail($itemId);

            if ($qty <= 0) {
                $item->delete();
                return $item;
            }

            $product = $item->product;
            $minPurchase = $product->min_purchase ?? 1;
            if ($qty < $minPurchase) {
                throw new \Exception("Minimum purchase for this product is {$minPurchase} items.");
            }

            // Validate stock
            $isFlashSale = $item->is_flash_sale;
            if ($isFlashSale) {
                $now = now();
                $flashSaleProduct = $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) {
                    $availableStock = $flashSaleProduct->stock - $flashSaleProduct->sold;
                } else {
                    $isFlashSale = false;
                }
            }

            if (!$isFlashSale) {
                if ($item->variant_id) {
                    $availableStock = $item->variant->stock;
                } else {
                    $availableStock = $item->product->stock;
                }
            }

            if ($availableStock < $qty) {
                throw new \Exception("Only {$availableStock} items available in stock.");
            }

            $item->qty = $qty;
            $item->is_flash_sale = $isFlashSale;
            $item->save();
            return $item;
        });
    }

    public function updateItemVariant(int $userId, int $itemId, ?int $variantId): CartItem
    {
        return DB::transaction(function() use ($userId, $itemId, $variantId) {
            $cart = $this->getOrCreateCart($userId);
            $item = CartItem::where('cart_id', $cart->id)->findOrFail($itemId);
            
            // Check if there is an active flash sale for the target variant
            $now = now();
            $flashSaleProduct = $item->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();

            $isFlashSale = $item->is_flash_sale;

            // Check if there's already an item with the target variant and flash sale status
            $existingItem = CartItem::where('cart_id', $cart->id)
                ->where('product_id', $item->product_id)
                ->where('variant_id', $variantId)
                ->where('is_flash_sale', $isFlashSale)
                ->where('id', '!=', $itemId)
                ->first();
                
            // Validate stock
            if ($isFlashSale) {
                $availableStock = $flashSaleProduct->stock - $flashSaleProduct->sold;
            } else {
                if ($variantId) {
                    $variant = ProductVariant::findOrFail($variantId);
                    $availableStock = $variant->stock;
                } else {
                    $availableStock = $item->product->stock;
                }
            }
            
            $targetQty = $item->qty + ($existingItem ? $existingItem->qty : 0);
            if ($availableStock < $targetQty) {
                throw new \Exception("Only {$availableStock} items available in stock.");
            }
            
            if ($existingItem) {
                // Merge quantities
                $existingItem->qty = $targetQty;
                $existingItem->save();
                $item->delete();
                return $existingItem;
            }
            
            $item->variant_id = $variantId;
            $item->is_flash_sale = $isFlashSale;
            $item->save();
            return $item;
        });
    }

    public function removeItem(int $userId, int $itemId): bool
    {
        $cart = $this->getOrCreateCart($userId);
        return CartItem::where('cart_id', $cart->id)->findOrFail($itemId)->delete();
    }

    public function clearCart(int $userId): bool
    {
        $cart = $this->getOrCreateCart($userId);
        return CartItem::where('cart_id', $cart->id)->delete() >= 0;
    }

    public function calculateTotals(int $userId): array
    {
        $cart = $this->getCartDetails($userId);
        $subtotal = 0.00;
        $totalWeight = 0; // in grams
        $itemCount = 0;

        foreach ($cart->items as $item) {
            $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;
        }

        return [
            'subtotal' => $subtotal,
            'total_weight' => $totalWeight,
            'item_count' => $itemCount
        ];
    }
}
