<?php

namespace App\Http\Controllers\Api\Waiter;

use App\Http\Controllers\Controller;
use App\Models\Category;
use App\Models\Deal;
use App\Models\Item;
use App\Models\Kot;
use App\Models\KotItem;
use App\Models\Order;
use App\Models\OrderItem;
use App\Models\RestaurantTable;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class DashboardController extends Controller
{
    /**
     * Ensure the authenticated user is a waiter and active.
     */
    protected function authorizeWaiter(): ?JsonResponse
    {
        $user = auth()->user();

        if ($user->role !== 'waiter') {
            return response()->json([
                'message' => 'Unauthorized. Only waiters can access this panel.',
            ], 403);
        }

        if (!$user->active) {
            return response()->json([
                'message' => 'Your account is inactive. Please contact support.',
            ], 403);
        }

        return null;
    }

    /**
     * Get tables in the waiter's active branch with active order statuses.
     */
    public function getTables(): JsonResponse
    {
        if ($authError = $this->authorizeWaiter()) {
            return $authError;
        }

        $branchId = auth()->user()->active_branch_id;
        $tables = RestaurantTable::forBranch($branchId)
            ->with(['activeOrder.items.kotItems'])
            ->get()
            ->map(function ($table) {
                $status = $table->status;
                $hasReadyItems = false;

                if ($table->activeOrder) {
                    foreach ($table->activeOrder->items as $item) {
                        if ($item->kotItems->where('status', 'ready')->count() > 0) {
                            $hasReadyItems = true;
                            break;
                        }
                    }
                }

                return [
                    'id' => $table->id,
                    'name' => $table->name,
                    'status' => $status,
                    'has_ready_items' => $hasReadyItems,
                    'order_id' => $table->activeOrder?->id,
                ];
            });

        return response()->json($tables);
    }

    /**
     * Get categories in the waiter's active branch.
     */
    public function getCategories(): JsonResponse
    {
        if ($authError = $this->authorizeWaiter()) {
            return $authError;
        }

        $branchId = auth()->user()->active_branch_id;
        $categories = Category::forBranch($branchId)
            ->where('is_active', true)
            ->get();

        return response()->json($categories);
    }

    /**
     * Get items in the waiter's active branch.
     */
    public function getItems(Request $request): JsonResponse
    {
        if ($authError = $this->authorizeWaiter()) {
            return $authError;
        }

        $branchId = auth()->user()->active_branch_id;
        $query = Item::forBranch($branchId)
            ->with('variants')
            ->where('is_active', true);

        if ($request->category_id) {
            $query->where('category_id', $request->category_id);
        }

        return response()->json($query->get());
    }

    /**
     * Get active deals in the waiter's active branch.
     */
    public function getDeals(): JsonResponse
    {
        if ($authError = $this->authorizeWaiter()) {
            return $authError;
        }

        $branchId = auth()->user()->active_branch_id;
        $currentDay = now()->format('l');

        $deals = Deal::where('branch_id', $branchId)
            ->where('is_active', true)
            ->where(function ($query) use ($currentDay) {
                $query->whereNull('available_days')
                    ->orWhereJsonContains('available_days', $currentDay);
            })
            ->with(['slots.items.item.variants', 'slots.items.variant'])
            ->get();

        return response()->json($deals);
    }

    /**
     * Get details of the active order for a given table.
     */
    public function getOrder(RestaurantTable $table): JsonResponse
    {
        if ($authError = $this->authorizeWaiter()) {
            return $authError;
        }

        if ($table->branch_id !== auth()->user()->active_branch_id) {
            return response()->json([
                'message' => 'Unauthorized branch table access.',
            ], 403);
        }

        $order = Order::with(['items.kotItems', 'items.item', 'items.variant'])
            ->where('table_id', $table->id)
            ->where('status', 'active')
            ->first();

        return response()->json($order);
    }

    /**
     * Create or update an active order, placing incremental KOT requests.
     */
    public function submitKot(Request $request): JsonResponse
    {
        if ($authError = $this->authorizeWaiter()) {
            return $authError;
        }

        $validated = $request->validate([
            'table_id' => ['required', 'exists:restaurant_tables,id'],
            'cart' => ['required', 'array', 'min:1'],
            'subtotal' => ['required', 'numeric'],
            'gst_amount' => ['required', 'numeric'],
            'grand_total' => ['required', 'numeric'],
        ]);

        $table = RestaurantTable::findOrFail($validated['table_id']);

        if ($table->branch_id !== auth()->user()->active_branch_id) {
            return response()->json([
                'message' => 'Unauthorized branch table access.',
            ], 403);
        }

        return DB::transaction(function () use ($validated, $table) {
            $order = Order::updateOrCreate(
                [
                    'table_id' => $validated['table_id'],
                    'status' => 'active',
                ],
                [
                    'branch_id' => auth()->user()->active_branch_id,
                    'waiter_id' => auth()->id(),
                    'order_type' => 'dine_in',
                    'subtotal' => $validated['subtotal'],
                    'gst_amount' => $validated['gst_amount'],
                    'grand_total' => $validated['grand_total'],
                ]
            );

            $existingItemIds = [];
            foreach ($validated['cart'] as $cartItem) {
                $isDeal = isset($cartItem['deal_id']);
                $orderItem = OrderItem::updateOrCreate(
                    [
                        'order_id' => $order->id,
                        'item_id' => $isDeal ? null : $cartItem['id'],
                        'variant_id' => $cartItem['variant_id'] ?? null,
                        'deal_id' => $cartItem['deal_id'] ?? null,
                    ],
                    [
                        'name' => $cartItem['name'],
                        'price' => $cartItem['price'],
                        'quantity' => $cartItem['qty'],
                        'subtotal' => $cartItem['price'] * $cartItem['qty'],
                        'notes' => $cartItem['notes'] ?? null,
                    ]
                );
                $existingItemIds[] = $orderItem->id;
            }

            // Sync: Remove items not in cart that don't have KOTs
            $order->items()->whereNotIn('id', $existingItemIds)
                ->whereDoesntHave('kotItems')
                ->delete();

            // Recalculate order totals based on ALL items currently in the order
            $orderSubtotal = $order->items()->sum('subtotal');
            $orderGstAmount = $orderSubtotal * 0.05; // 5% GST
            $orderGrandTotal = $orderSubtotal + $orderGstAmount;

            $order->update([
                'subtotal' => $orderSubtotal,
                'gst_amount' => $orderGstAmount,
                'grand_total' => $orderGrandTotal,
            ]);

            $table->update(['status' => 'occupied']);

            // Compute incremental KOT items
            $itemsToSend = [];
            $order->load('items.kotItems');
            foreach ($order->items as $item) {
                $alreadySentQty = $item->kotItems->sum('quantity');
                $qtyToSend = $item->quantity - $alreadySentQty;

                if ($qtyToSend > 0) {
                    $cartItem = collect($validated['cart'])->first(function ($c) use ($item) {
                        if ($item->deal_id) {
                            return isset($c['deal_id']) && $c['deal_id'] == $item->deal_id;
                        }

                        return $c['id'] == $item->item_id;
                    });

                    if ($item->deal_id && isset($cartItem['selections'])) {
                        foreach ($cartItem['selections'] as $selection) {
                            $itemsToSend[] = [
                                'order_item_id' => $item->id,
                                'item_id' => $selection['item_id'],
                                'name_override' => $selection['name'],
                                'quantity' => $qtyToSend,
                                'notes' => $item->notes,
                                'deal_id' => $item->deal_id,
                            ];
                        }
                    } else {
                        $itemsToSend[] = [
                            'order_item_id' => $item->id,
                            'quantity' => $qtyToSend,
                            'notes' => $item->notes,
                        ];
                    }
                }
            }

            if (empty($itemsToSend)) {
                return response()->json([
                    'success' => true,
                    'order_id' => $order->id,
                    'message' => 'Nothing new.',
                ]);
            }

            $kot = Kot::create([
                'branch_id' => $order->branch_id,
                'order_id' => $order->id,
                'waiter_id' => auth()->id(),
                'status' => 'pending',
            ]);

            foreach ($itemsToSend as $itemData) {
                KotItem::create([
                    'kot_id' => $kot->id,
                    'order_item_id' => $itemData['order_item_id'],
                    'item_id' => $itemData['item_id'] ?? $item->item_id,
                    'quantity' => $itemData['quantity'],
                    'notes' => trim(($itemData['name_override'] ?? '').' '.($itemData['notes'] ?? '')),
                    'status' => 'pending',
                    'deal_id' => $itemData['deal_id'] ?? null,
                ]);
            }

            return response()->json([
                'success' => true,
                'order_id' => $order->id,
                'kot_id' => $kot->id,
            ]);
        });
    }

    /**
     * Mark ready items as served.
     */
    public function serveItem(Request $request): JsonResponse
    {
        if ($authError = $this->authorizeWaiter()) {
            return $authError;
        }

        $validated = $request->validate([
            'order_item_id' => ['required', 'exists:order_items,id'],
        ]);

        $orderItem = OrderItem::with('order.table')->findOrFail($validated['order_item_id']);

        if ($orderItem->order->branch_id !== auth()->user()->active_branch_id) {
            return response()->json([
                'message' => 'Unauthorized branch order item access.',
            ], 403);
        }

        KotItem::where('order_item_id', $validated['order_item_id'])
            ->where('status', 'ready')
            ->update(['status' => 'served']);

        return response()->json([
            'success' => true,
        ]);
    }
}
