<?php

namespace App\Http\Controllers\Web;

use App\Http\Controllers\Controller;
use App\Models\Cart;
use App\Models\CartItem;
use App\Models\Product;
use App\Models\ProductVariant;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;

class CartController extends Controller
{
    protected function getOrCreateCart(): Cart
    {
        if (auth()->guard('web')->check()) {
            return Cart::firstOrCreate(
                ['user_id' => auth()->guard('web')->id()],
                ['expires_at' => now()->addDays(30)]
            );
        }

        return Cart::firstOrCreate(
            [
                'user_id' => null,
                'session_id' => session()->getId(),
            ],
            ['expires_at' => now()->addDays(7)]
        );
    }

    public function show(): View
    {
        $cart = $this->getOrCreateCart();
        $cart->load(['items.product.images', 'items.variant']);

        return view('store.cart.show', compact('cart'));
    }

    public function add(Request $request): RedirectResponse
    {
        $request->validate([
            'product_id' => ['required', 'exists:products,id'],
            'quantity' => ['required', 'integer', 'min:1', 'max:99'],
            'product_variant_id' => ['nullable', 'exists:product_variants,id'],
        ]);

        $cart = $this->getOrCreateCart();
        $product = Product::findOrFail($request->product_id);

        if (! $product->is_active) {
            return back()->with('error', 'Product is not available.');
        }

        if ($product->variants()->exists() && ! $request->product_variant_id) {
            return back()->with('error', 'Please select a variant.');
        }

        $variant = null;
        if ($request->product_variant_id) {
            $variant = ProductVariant::findOrFail($request->product_variant_id);
            if (! $variant->is_active || ! $variant->isInStock($request->quantity)) {
                return back()->with('error', 'Variant not available or insufficient stock.');
            }
            $price = $variant->price;
        } else {
            $price = $product->base_price;
        }

        $existing = $cart->items()
            ->where('product_id', $product->id)
            ->where('product_variant_id', $request->product_variant_id)
            ->first();

        if ($existing) {
            $newQty = $existing->quantity + $request->quantity;
            if ($variant && ! $variant->isInStock($newQty)) {
                return back()->with('error', 'Insufficient stock.');
            }
            $existing->update(['quantity' => $newQty]);
        } else {
            $cart->items()->create([
                'product_id' => $product->id,
                'product_variant_id' => $request->product_variant_id,
                'quantity' => $request->quantity,
                'price' => $price,
            ]);
        }

        return back()->with('success', 'Added to cart.');
    }

    public function update(Request $request, CartItem $cartItem): RedirectResponse
    {
        $cart = $this->getOrCreateCart();
        if ($cartItem->cart_id !== $cart->id) {
            abort(403);
        }

        $request->validate(['quantity' => ['required', 'integer', 'min:1', 'max:99']]);

        if ($cartItem->variant && ! $cartItem->variant->isInStock($request->quantity)) {
            return back()->with('error', 'Insufficient stock.');
        }

        $cartItem->update(['quantity' => $request->quantity]);

        return back()->with('success', 'Cart updated.');
    }

    public function remove(CartItem $cartItem): RedirectResponse
    {
        $cart = $this->getOrCreateCart();
        if ($cartItem->cart_id !== $cart->id) {
            abort(403);
        }
        $cartItem->delete();
        return back()->with('success', 'Item removed.');
    }

    public function clear(): RedirectResponse
    {
        $cart = $this->getOrCreateCart();
        $cart->clear();
        return redirect()->route('cart.show')->with('success', 'Cart cleared.');
    }
}
