<?php

namespace App\Services;

use App\Models\Cart;
use App\Models\CartItem;
use App\Models\Product;
use App\Models\ShippingMethod;
use App\Models\User;
use Illuminate\Support\Facades\DB;

class CartService
{
    public function __construct(
        protected CouponService $couponService
    ) {
    }

    public function getOrCreateCart(?User $user, ?string $cookieToken = null): Cart
    {
        if ($user) {
            $cart = Cart::firstOrCreate(
                ['user_id' => $user->id],
                ['totals' => $this->getDefaultTotals()]
            );
        } else {
            $cart = Cart::firstOrCreate(
                ['cookie_token' => $cookieToken],
                ['totals' => $this->getDefaultTotals()]
            );
        }

        return $cart->load('items.product', 'coupon');
    }

    public function addItem(Cart $cart, int $productId, int $qty = 1, ?int $productVariantId = null): bool
    {
        // Unified model: productId is the actual product (single or variant)
        // productVariantId parameter is kept for backward compatibility but ignored
        $product = Product::active()->find($productId);
        
        if (!$product) {
            return false;
        }

        // Unified logic: all products have stock and price directly
        if ($product->current_stock < $qty) {
            return false;
        }

        // Check for existing cart item (same product)
        $cartItem = CartItem::where('cart_id', $cart->id)
            ->where('product_id', $productId)
            ->first();

        if ($cartItem) {
            $newQty = $cartItem->qty + $qty;
            // Cap at 100 to respect validation limit
            if ($newQty > 100) {
                return false;
            }
            if ($product->current_stock < $newQty) {
                return false;
            }
            $cartItem->update(['qty' => $newQty]);
        } else {
            CartItem::create([
                'cart_id' => $cart->id,
                'product_id' => $productId,
                'qty' => $qty,
                'price_at_add' => $product->price,
            ]);
        }

        $this->recalculateTotals($cart);
        
        // Clear cart count cache if user is authenticated
        if ($cart->user_id) {
            \Illuminate\Support\Facades\Cache::forget("layout.cart_count." . $cart->user_id);
        } elseif ($cart->cookie_token) {
            // Clear guest cart count cache
            \Illuminate\Support\Facades\Cache::forget("layout.cart_count.guest." . $cart->cookie_token);
        }

        return true;
    }

    public function updateItem(Cart $cart, int $productId, int $qty): bool
    {
        if ($qty <= 0) {
            return $this->removeItem($cart, $productId);
        }

        $cartItem = CartItem::where('cart_id', $cart->id)
            ->where('product_id', $productId)
            ->first();

        if (!$cartItem) {
            return false;
        }

        $product = $cartItem->product;
        
        // Unified logic: check product stock directly
        if ($product->current_stock < $qty) {
            return false;
        }

        $cartItem->update(['qty' => $qty]);
        $this->recalculateTotals($cart);
        
        // Clear cart count cache if user is authenticated
        if ($cart->user_id) {
            \Illuminate\Support\Facades\Cache::forget("layout.cart_count." . $cart->user_id);
        } elseif ($cart->cookie_token) {
            // Clear guest cart count cache
            \Illuminate\Support\Facades\Cache::forget("layout.cart_count.guest." . $cart->cookie_token);
        }

        return true;
    }

    public function removeItem(Cart $cart, int $productId): bool
    {
        $deleted = CartItem::where('cart_id', $cart->id)
            ->where('product_id', $productId)
            ->delete();

        if ($deleted) {
            $this->recalculateTotals($cart);
            
            // Clear cart count cache if user is authenticated
            if ($cart->user_id) {
                \Illuminate\Support\Facades\Cache::forget("layout.cart_count." . $cart->user_id);
            } elseif ($cart->cookie_token) {
                // Clear guest cart count cache
                \Illuminate\Support\Facades\Cache::forget("layout.cart_count.guest." . $cart->cookie_token);
            }
            
            return true;
        }

        return false;
    }

    public function recalculateTotals(Cart $cart): void
    {
        $cart->load('items.product', 'coupon');

        $subtotal = $cart->items->sum(function ($item) {
            return $item->qty * $item->price_at_add;
        });

        // Calculate tax per item using tax-inclusive formula: (price * qty) * (tax_rate / (100 + tax_rate))
        // Since product prices are tax-inclusive, we extract the tax amount from the inclusive price
        $tax = $cart->items->sum(function ($item) {
            $itemTotal = $item->qty * $item->price_at_add;
            $taxRate = 0;
            
            // Get tax rate from product (unified model)
            if ($item->product && $item->product->tax_rate_snapshot) {
                $taxRate = (float) $item->product->tax_rate_snapshot;
            }
            
            // Tax-inclusive formula: tax = price × (rate / (100 + rate))
            if ($taxRate > 0) {
                return $itemTotal * ($taxRate / (100 + $taxRate));
            }
            
            return 0;
        });

        $discount = 0;
        if ($cart->coupon) {
            $validation = $this->couponService->validate(
                $cart->coupon->code,
                $cart->user,
                $subtotal
            );

            if ($validation['valid']) {
                $discount = $validation['discount'];
            } else {
                // Coupon no longer valid, remove it
                $cart->update(['coupon_id' => null]);
            }
        }

        $shipping = $this->calculateShipping($subtotal);
        // Since prices are tax-inclusive, subtotal already includes tax
        // Total = Subtotal - Discount + Shipping (tax already included in subtotal)
        $total = $subtotal - $discount + $shipping;

        $cart->update([
            'totals' => [
                'subtotal' => round($subtotal, 2),
                'tax' => round($tax, 2),
                'discount' => round($discount, 2),
                'shipping' => round($shipping, 2),
                'total' => round($total, 2),
            ],
        ]);
    }

    protected function calculateShipping(float $subtotal): float
    {
        try {
            $shippingMethod = ShippingMethod::where('code', 'standard')
                ->where('is_active', true)
                ->first();
            
            if ($shippingMethod) {
                return $shippingMethod->calculateCharge($subtotal);
            }
        } catch (\Exception $e) {
            // Shipping methods table doesn't exist or error occurred, use fallback
        }

        return 0;
    }

    protected function getDefaultTotals(): array
    {
        return [
            'subtotal' => 0,
            'discount' => 0,
            'shipping' => 0,
            'total' => 0,
        ];
    }

    public function clear(Cart $cart): void
    {
        $cart->items()->delete();
        $cart->update([
            'coupon_id' => null,
            'totals' => $this->getDefaultTotals(),
        ]);
        
        // Clear cart count cache if user is authenticated
        if ($cart->user_id) {
            \Illuminate\Support\Facades\Cache::forget("layout.cart_count." . $cart->user_id);
        } elseif ($cart->cookie_token) {
            // Clear guest cart count cache
            \Illuminate\Support\Facades\Cache::forget("layout.cart_count.guest." . $cart->cookie_token);
        }
    }

    /**
     * Merge guest cart (cookie-based) with user cart after login
     */
    public function mergeGuestCartWithUser(User $user, ?string $cookieToken = null): void
    {
        if (!$cookieToken) {
            return;
        }

        // Find guest cart by cookie token
        $guestCart = Cart::where('cookie_token', $cookieToken)
            ->whereNull('user_id')
            ->with('items.product')
            ->first();

        if (!$guestCart || $guestCart->items->isEmpty()) {
            return;
        }

        // Get or create user cart
        $userCart = Cart::firstOrCreate(
            ['user_id' => $user->id],
            ['totals' => $this->getDefaultTotals()]
        );

        // Merge items from guest cart to user cart
        DB::transaction(function () use ($guestCart, $userCart) {
            foreach ($guestCart->items as $guestItem) {
                $product = $guestItem->product;
                
                // Check if product is still available
                if (!$product || !$product->is_active) {
                    continue;
                }

                // Unified model: Check product stock directly
                // Note: Old guest carts might have product_variant_id, but we use product_id as the actual product
                // If product_variant_id was set, it means the product_id was the parent, but now variants are separate products
                // So we should use the product_id directly (which should be the actual sellable product)
                if ($product->current_stock < $guestItem->qty) {
                    continue;
                }

                // Check if item already exists in user cart (by product_id only)
                $existingItem = CartItem::where('cart_id', $userCart->id)
                    ->where('product_id', $guestItem->product_id)
                    ->first();

                if ($existingItem) {
                    // Merge quantities, but respect stock limits
                    $newQty = $existingItem->qty + $guestItem->qty;
                    $maxQty = min($newQty, $product->current_stock);
                    $existingItem->update(['qty' => $maxQty]);
                } else {
                    // Add new item to user cart
                    CartItem::create([
                        'cart_id' => $userCart->id,
                        'product_id' => $guestItem->product_id,
                        'qty' => min($guestItem->qty, $product->current_stock),
                        'price_at_add' => $guestItem->price_at_add,
                    ]);
                }
            }

            // Transfer coupon if user cart doesn't have one
            if ($guestCart->coupon_id && !$userCart->coupon_id) {
                $userCart->update(['coupon_id' => $guestCart->coupon_id]);
            }

            // Clear and delete guest cart
            $this->clear($guestCart);
            $guestCart->delete();
        });

        // Recalculate totals for user cart
        $this->recalculateTotals($userCart);
        
        // Clear cart count cache for the user after merge
        \Illuminate\Support\Facades\Cache::forget("layout.cart_count." . $user->id);
    }
}
