<?php

namespace App\Http\Controllers;

use App\Models\Article;
use App\Models\Order;
use App\Models\Product;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Illuminate\View\View;

class StorefrontController extends Controller
{
    public function home(Request $request): View
    {
        $featuredProducts = Product::query()
            ->where('is_featured', true)
            ->orderBy('sort_order')
            ->get();

        $heroProduct = $featuredProducts->first();

        $articles = Article::query()
            ->orderBy('sort_order')
            ->get();

        return view('storefront.home', [
            'heroProduct' => $heroProduct,
            'featuredProducts' => $featuredProducts,
            'articles' => $articles,
            'cartCount' => $this->cartCount($request),
        ]);
    }

    public function cart(Request $request): View
    {
        $summary = $this->cartSummary($request);

        return view('storefront.cart', [
            'items' => $summary['items'],
            'subtotal' => $summary['subtotal'],
            'shipping' => $summary['shipping'],
            'tax' => $summary['tax'],
            'total' => $summary['total'],
            'cartCount' => $this->cartCount($request),
        ]);
    }

    public function checkout(Request $request): View|RedirectResponse
    {
        $summary = $this->cartSummary($request);

        if ($summary['items']->isEmpty()) {
            return redirect()
                ->route('cart.index')
                ->with('status', 'Add an item before continuing to checkout.');
        }

        return view('storefront.checkout', [
            'items' => $summary['items'],
            'subtotal' => $summary['subtotal'],
            'shipping' => $summary['shipping'],
            'tax' => $summary['tax'],
            'total' => $summary['total'],
            'cartCount' => $this->cartCount($request),
        ]);
    }

    public function placeOrder(Request $request): RedirectResponse
    {
        $summary = $this->cartSummary($request);

        if ($summary['items']->isEmpty()) {
            return redirect()
                ->route('cart.index')
                ->with('status', 'Your cart is empty.');
        }

        $validated = $request->validate([
            'customer_name' => ['required', 'string', 'max:255'],
            'email' => ['required', 'email', 'max:255'],
            'phone' => ['required', 'string', 'max:40'],
            'shipping_address' => ['required', 'string', 'max:255'],
            'city' => ['required', 'string', 'max:120'],
            'postal_code' => ['required', 'string', 'max:32'],
            'notes' => ['nullable', 'string', 'max:1000'],
        ]);

        $order = DB::transaction(function () use ($validated, $summary) {
            $order = Order::query()->create([
                'order_number' => 'CAM-' . now()->format('Ymd') . '-' . Str::upper(Str::random(6)),
                'customer_name' => $validated['customer_name'],
                'email' => $validated['email'],
                'phone' => $validated['phone'],
                'shipping_address' => $validated['shipping_address'],
                'city' => $validated['city'],
                'postal_code' => $validated['postal_code'],
                'notes' => $validated['notes'] ?? null,
                'subtotal' => $summary['subtotal'],
                'shipping_amount' => $summary['shipping'],
                'tax_amount' => $summary['tax'],
                'total_amount' => $summary['total'],
                'status' => 'pending',
            ]);

            foreach ($summary['items'] as $item) {
                $order->items()->create([
                    'product_id' => $item['product']->id,
                    'product_name' => $item['product']->name,
                    'unit_price' => $item['product']->price,
                    'quantity' => $item['quantity'],
                    'subtotal' => $item['subtotal'],
                ]);
            }

            return $order;
        });

        $request->session()->forget('cart');
        $request->session()->put('last_order_id', $order->id);

        return redirect()
            ->route('checkout.success')
            ->with('status', 'Order placed successfully.');
    }

    public function checkoutSuccess(Request $request): View|RedirectResponse
    {
        $orderId = $request->session()->get('last_order_id');

        if (! $orderId) {
            return redirect()->route('home');
        }

        $order = Order::query()
            ->with('items')
            ->findOrFail($orderId);

        return view('storefront.success', [
            'order' => $order,
            'cartCount' => $this->cartCount($request),
        ]);
    }

    public function addToCart(Request $request): RedirectResponse
    {
        $validated = $request->validate([
            'product_id' => ['required', 'exists:products,id'],
        ]);

        $productId = (int) $validated['product_id'];
        $cart = $request->session()->get('cart', []);

        if (isset($cart[$productId])) {
            $cart[$productId]['quantity']++;
        } else {
            $cart[$productId] = [
                'product_id' => $productId,
                'quantity' => 1,
            ];
        }

        $request->session()->put('cart', $cart);

        return redirect()
            ->back()
            ->with('status', 'Item added to cart.');
    }

    public function updateCart(Request $request, Product $product): RedirectResponse
    {
        $validated = $request->validate([
            'quantity' => ['required', 'integer', 'min:0', 'max:20'],
        ]);

        $cart = $request->session()->get('cart', []);
        $quantity = (int) $validated['quantity'];

        if ($quantity === 0) {
            unset($cart[$product->id]);
        } else {
            $cart[$product->id] = [
                'product_id' => $product->id,
                'quantity' => $quantity,
            ];
        }

        $request->session()->put('cart', $cart);

        return redirect()
            ->route('cart.index')
            ->with('status', 'Cart updated.');
    }

    public function removeFromCart(Request $request, Product $product): RedirectResponse
    {
        $cart = $request->session()->get('cart', []);
        unset($cart[$product->id]);
        $request->session()->put('cart', $cart);

        return redirect()
            ->route('cart.index')
            ->with('status', 'Item removed from cart.');
    }

    protected function cartCount(Request $request): int
    {
        return collect($request->session()->get('cart', []))
            ->sum('quantity');
    }

    protected function cartSummary(Request $request): array
    {
        $cart = collect($request->session()->get('cart', []));

        $productIds = $cart->pluck('product_id');

        $products = Product::query()
            ->whereIn('id', $productIds)
            ->get()
            ->keyBy('id');

        $items = $cart->map(function (array $item) use ($products) {
            $product = $products->get($item['product_id']);

            if (! $product) {
                return null;
            }

            $quantity = max(1, (int) $item['quantity']);
            $unitPrice = (float) $product->price;

            return [
                'product' => $product,
                'quantity' => $quantity,
                'subtotal' => $quantity * $unitPrice,
            ];
        })->filter()->values();

        $subtotal = $items->sum('subtotal');
        $shipping = $items->isNotEmpty() ? 18.00 : 0.00;
        $tax = $subtotal * 0.06;

        return [
            'items' => $items,
            'subtotal' => $subtotal,
            'shipping' => $shipping,
            'tax' => $tax,
            'total' => $subtotal + $shipping + $tax,
        ];
    }
}
