<?php

namespace App\Http\Controllers\Api\Customer;

use App\Http\Controllers\Controller;
use App\Models\Cart;
use App\Models\CartItem;
use App\Models\Product;
use App\Models\ProductVariant;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Storage;

class CartController extends Controller
{
    /**
     * GET /api/customer/cart
     * Returns cart grouped by vendor.
     */
    public function index(): JsonResponse
    {
        $cart = $this->currentCart();
        $cart->load(['items.product.images', 'items.variant', 'items.vendor']);

        $groups = $cart->items->groupBy('vendor_id')->map(function ($items, $vendorId) {
            $vendor = $items->first()->vendor;
            $subtotal = (float) $items->sum(fn($i) => $i->lineTotal());

            return [
                'vendor' => [
                    'id'         => $vendor->id,
                    'store_name' => $vendor->store_name,
                    'slug'       => $vendor->slug,
                    'min_order'  => (float) $vendor->min_order_value,
                ],
                'items' => $items->map(fn($i) => $this->itemPayload($i))->values(),
                'subtotal'           => $subtotal,
                'meets_minimum'      => $subtotal >= (float) $vendor->min_order_value,
            ];
        })->values();

        $itemsTotal = (float) $cart->items->sum(fn($i) => $i->lineTotal());

        // Delivery is distance-based, so it's only known once an address is
        // chosen at checkout. The cart shows items only + a "at checkout" note.
        return response()->json([
            'cart_id'             => $cart->id,
            'item_count'          => (int) $cart->items->sum('quantity'),
            'vendor_count'        => $groups->count(),
            'groups'              => $groups,
            'items_total'         => $itemsTotal,
            'delivery_total'      => null,
            'delivery_at_checkout'=> true,
            'grand_total'         => $itemsTotal,
            // COD OTP confirmation has been removed — ordering is one tap.
            'cod_otp_required'=> false,
        ]);
    }

    /**
     * POST /api/customer/cart/items
     */
    public function add(Request $request): JsonResponse
    {
        $request->validate([
            'product_id' => 'required|exists:products,id',
            'variant_id' => 'nullable|exists:product_variants,id',
            'quantity'   => 'required|integer|min:1|max:100',
        ]);

        $product = Product::with('vendor')->findOrFail($request->product_id);

        abort_unless($product->is_active, 422, 'This product is unavailable.');
        abort_unless($product->vendor->isActive(), 422, 'This vendor is currently offline.');

        if ($product->track_stock && $product->stock_quantity < $request->quantity) {
            return response()->json([
                'message' => "Only {$product->stock_quantity} in stock.",
            ], 422);
        }

        $variant = null;
        $unitPrice = $product->getEffectivePrice();

        if ($request->variant_id) {
            $variant = ProductVariant::where('product_id', $product->id)
                ->where('id', $request->variant_id)
                ->firstOrFail();
            $unitPrice = $variant->getEffectivePrice();
        }

        $cart = $this->currentCart();

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

        if ($existing) {
            $existing->update([
                'quantity'   => $existing->quantity + $request->quantity,
                'unit_price' => $unitPrice,
            ]);
            $item = $existing;
        } else {
            $item = $cart->items()->create([
                'product_id' => $product->id,
                'variant_id' => $variant?->id,
                'vendor_id'  => $product->vendor_id,
                'quantity'   => $request->quantity,
                'unit_price' => $unitPrice,
            ]);
        }

        return response()->json([
            'message' => 'Added to cart.',
            'item'    => $this->itemPayload($item->fresh(['product.images', 'variant', 'vendor'])),
        ], 201);
    }

    /**
     * PUT /api/customer/cart/items/{item}
     */
    public function update(Request $request, CartItem $item): JsonResponse
    {
        $this->authorizeOwn($item);

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

        if ($item->product->track_stock && $item->product->stock_quantity < $request->quantity) {
            return response()->json([
                'message' => "Only {$item->product->stock_quantity} in stock.",
            ], 422);
        }

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

        return response()->json([
            'message' => 'Cart updated.',
            'item'    => $this->itemPayload($item->fresh(['product.images', 'variant', 'vendor'])),
        ]);
    }

    /**
     * DELETE /api/customer/cart/items/{item}
     */
    public function remove(CartItem $item): JsonResponse
    {
        $this->authorizeOwn($item);
        $item->delete();

        return response()->json(['message' => 'Item removed.']);
    }

    /**
     * DELETE /api/customer/cart
     */
    public function clear(): JsonResponse
    {
        $this->currentCart()->items()->delete();
        return response()->json(['message' => 'Cart cleared.']);
    }

    /* ---------- helpers ---------- */

    private function currentCart(): Cart
    {
        $userId = Auth::guard('customer')->id();
        return Cart::firstOrCreate(['user_id' => $userId]);
    }

    private function authorizeOwn(CartItem $item): void
    {
        abort_unless(
            $item->cart->user_id === Auth::guard('customer')->id(),
            403,
            'You do not own this cart item.'
        );
    }

    private function itemPayload(CartItem $item): array
    {
        $img = $item->product->images->firstWhere('is_primary', true)
            ?? $item->product->images->first();

        return [
            'id'         => $item->id,
            'product_id' => $item->product_id,
            'variant_id' => $item->variant_id,
            'product'    => [
                'name'      => ['en' => $item->product->name_en, 'ur' => $item->product->name_ur],
                'thumbnail' => $img ? Storage::disk('public')->url($img->path_thumb ?? $img->path) : null,
                'in_stock'  => $item->product->isInStock(),
            ],
            'variant'    => $item->variant ? [
                'name' => ['en' => $item->variant->name_en, 'ur' => $item->variant->name_ur],
            ] : null,
            'quantity'   => $item->quantity,
            'unit_price' => (float) $item->unit_price,
            'line_total' => $item->lineTotal(),
        ];
    }
}
