<?php

namespace App\Http\Controllers\Api\Biller;

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

class OrderController extends Controller
{
    /**
     * Get running / active orders of the biller's active branch.
     */
    public function active(): JsonResponse
    {
        $branchId = auth()->user()->active_branch_id;

        $orders = Order::with(['items.item', 'items.variant', 'items.kotItems', 'table', 'waiter'])
            ->where('branch_id', $branchId)
            ->where('status', 'active')
            ->orderBy('updated_at', 'desc')
            ->get();

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

    /**
     * Create or update draft order, sync items in the cart, and update table status to occupied.
     */
    public function hold(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'order_id' => 'nullable|exists:orders,id',
            'order_type' => 'required|in:dine_in,takeaway,delivery',
            'table_id' => 'nullable|required_if:order_type,dine_in|exists:restaurant_tables,id',
            'waiter_id' => 'nullable|exists:users,id',
            'customer_name' => 'nullable|string|max:255',
            'customer_phone' => 'nullable|string|max:20',
            'delivery_address' => 'nullable|string',
            'cart' => 'required|array',
            'cart.*.id' => 'required', // Allow string IDs for deals
            'cart.*.deal_id' => 'nullable|exists:deals,id',
            'cart.*.variant_id' => 'nullable|exists:item_variants,id',
            'cart.*.qty' => 'required|integer|min:1',
            'cart.*.price' => 'required|numeric',
            'cart.*.name' => 'required|string',
            'cart.*.selections' => 'nullable|array',
            'subtotal' => 'required|numeric',
            'gst_amount' => 'required|numeric',
            'grand_total' => 'required|numeric',
        ]);

        return DB::transaction(function () use ($validated): JsonResponse {
            $branchId = auth()->user()->active_branch_id;

            $order = Order::updateOrCreate(
                ['id' => $validated['order_id'] ?? null],
                [
                    'branch_id' => $branchId,
                    'table_id' => $validated['table_id'] ?? null,
                    'waiter_id' => $validated['waiter_id'] ?? null,
                    'biller_id' => auth()->id(),
                    'order_type' => $validated['order_type'],
                    'customer_name' => $validated['customer_name'] ?? null,
                    'customer_phone' => $validated['customer_phone'] ?? null,
                    'delivery_address' => $validated['delivery_address'] ?? null,
                    'status' => 'active',
                    'subtotal' => $validated['subtotal'],
                    'gst_amount' => $validated['gst_amount'],
                    'grand_total' => $validated['grand_total'],
                ]
            );

            // Sync items (Don't delete if they have KOTs)
            $existingItemIds = [];
            foreach ($validated['cart'] as $cartItem) {
                $isDeal = isset($cartItem['deal_id']);
                $orderItem = $order->items()->updateOrCreate(
                    [
                        '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'],
                    ]
                );
                $existingItemIds[] = $orderItem->id;
            }

            // Only delete items that are NOT in the cart AND don't have KOTs (or handle logic accordingly)
            $order->items()
                ->whereNotIn('id', $existingItemIds)
                ->whereDoesntHave('kotItems')
                ->delete();

            // Update table status
            if (isset($validated['table_id']) && $validated['table_id']) {
                RestaurantTable::where('id', $validated['table_id'])->update(['status' => 'occupied']);
            }

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

    /**
     * Auto-hold the order and fire new KOT items to the kitchen.
     */
    public function kot(Request $request): JsonResponse
    {
        $response = $this->hold($request);
        $responseData = json_decode($response->getContent(), true);

        if (! isset($responseData['success']) || ! $responseData['success']) {
            return $response;
        }

        $orderId = $responseData['order_id'];
        $order = Order::with('items.kotItems')->find($orderId);

        return DB::transaction(function () use ($order, $request): JsonResponse {
            $itemsToSend = [];
            $cart = $request->input('cart', []);

            foreach ($order->items as $item) {
                $alreadySentQty = $item->kotItems->sum('quantity');
                $qtyToSend = $item->quantity - $alreadySentQty;

                if ($qtyToSend > 0) {
                    // Match with cart item to get selections if it's a deal
                    $cartItem = collect($cart)->first(function ($c) use ($item) {
                        if ($item->deal_id) {
                            return isset($c['deal_id']) && $c['deal_id'] == $item->deal_id;
                        }

                        return isset($c['id']) && $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,
                                'deal_id' => $item->deal_id,
                            ];
                        }
                    } else {
                        $itemsToSend[] = [
                            'order_item_id' => $item->id,
                            'quantity' => $qtyToSend,
                            'item_id' => $item->item_id,
                        ];
                    }
                }
            }

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

            $kot = Kot::create([
                'branch_id' => $order->branch_id,
                'order_id' => $order->id,
                'waiter_id' => $order->waiter_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'] ?? null,
                    'quantity' => $itemData['quantity'],
                    'notes' => $itemData['name_override'] ?? null,
                    'status' => 'pending',
                    'deal_id' => $itemData['deal_id'] ?? null,
                ]);
            }

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

    /**
     * Settle payment for order, finalize discount/pricing details, and set table to available.
     */
    public function settle(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'order_id' => 'required|exists:orders,id',
            'discount_type' => 'nullable|in:percentage,fixed',
            'discount_value' => 'nullable|numeric|min:0',
            'discount_amount' => 'required|numeric|min:0',
            'grand_total' => 'required|numeric',
            'payment_method' => 'required|in:cash,card,upi,split',
            'split_cash' => 'nullable|numeric|min:0',
            'split_card' => 'nullable|numeric|min:0',
            'split_upi' => 'nullable|numeric|min:0',
        ]);

        return DB::transaction(function () use ($validated): JsonResponse {
            $order = Order::findOrFail($validated['order_id']);

            $order->update([
                'status' => 'settled',
                'biller_id' => auth()->id(),
                'discount_type' => $validated['discount_type'] ?? null,
                'discount_value' => $validated['discount_value'] ?? null,
                'discount_amount' => $validated['discount_amount'],
                'grand_total' => $validated['grand_total'],
                'payment_method' => $validated['payment_method'],
                'split_cash' => $validated['split_cash'] ?? null,
                'split_card' => $validated['split_card'] ?? null,
                'split_upi' => $validated['split_upi'] ?? null,
            ]);

            // Free the table
            if ($order->table_id) {
                RestaurantTable::where('id', $order->table_id)->update(['status' => 'available']);
            }

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

    /**
     * Get transaction logs / order history for the authenticated biller.
     */
    public function index(Request $request): JsonResponse
    {
        $query = Order::with(['table', 'waiter'])
            ->where('biller_id', auth()->id());

        $filter = $request->get('date_filter', 'today');

        if ($filter === 'today') {
            $query->whereDate('created_at', now()->toDateString());
        } elseif ($filter === 'yesterday') {
            $query->whereDate('created_at', now()->subDay()->toDateString());
        } elseif ($filter === 'last_7_days') {
            $query->whereDate('created_at', '>=', now()->subDays(7)->toDateString());
        } elseif ($filter === 'custom' && $request->has(['start_date', 'end_date'])) {
            $query->whereBetween('created_at', [
                $request->start_date.' 00:00:00',
                $request->end_date.' 23:59:59',
            ]);
        }

        $orders = $query->orderBy('created_at', 'desc')->paginate(20);

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

    /**
     * Get detailed information for a specific order.
     */
    public function show(Order $order): JsonResponse
    {
        // Ensure biller owns the order (or has access)
        if ($order->biller_id !== auth()->id() && auth()->user()->role !== 'owner') {
            return response()->json(['message' => 'Unauthorized'], 403);
        }

        $order->load(['table', 'waiter', 'items.item', 'items.variant', 'branch']);

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