<?php

namespace App\Http\Controllers;

use App\Models\Order;
use App\Models\OrderItem;
use App\Models\MenuItem;
use App\Models\KitchenTicket;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\DB;

class OrderController extends Controller
{
    public function index(Request $request): JsonResponse
    {
        $query = Order::with(['table', 'user', 'customer', 'items.menuItem', 'payments'])
            ->where('restaurant_id', $request->user()->restaurant_id);

        // Filter by branch if user is not admin
        if ($request->user()->branch_id) {
            $query->where('branch_id', $request->user()->branch_id);
        }

        // Role-based filtering: waiters only see their own orders
        if (!$request->user()->canViewAllOrders()) {
            $query->where('user_id', $request->user()->id);
        }

        // Filter by status
        if ($request->filled('status')) {
            $query->where('status', $request->status);
        }

        // Filter by type
        if ($request->filled('type')) {
            $query->where('type', $request->type);
        }

        // Filter by date
        if ($request->filled('date')) {
            $query->whereDate('created_at', $request->date);
        }

        // Filter by payment status
        if ($request->filled('payment_status')) {
            $query->where('payment_status', $request->payment_status);
        }

        // Filter by waiter (user_id) - only for users who can view all orders
        if ($request->filled('waiter_id') && $request->user()->canViewAllOrders()) {
            $query->where('user_id', $request->waiter_id);
        }

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

        return response()->json([
            'orders' => $orders->items(),
            'pagination' => [
                'current_page' => $orders->currentPage(),
                'last_page' => $orders->lastPage(),
                'per_page' => $orders->perPage(),
                'total' => $orders->total(),
            ],
        ]);
    }

    public function store(Request $request): JsonResponse
    {
        $request->validate([
            'table_id' => 'nullable|exists:tables,id',
            'customer_id' => 'nullable|exists:customers,id',
            'type' => 'required|in:dine_in,takeaway,delivery',
            'items' => 'required|array|min:1',
            'items.*.menu_item_id' => 'required|exists:menu_items,id',
            'items.*.quantity' => 'required|integer|min:1',
            'items.*.special_instructions' => 'nullable|string|max:500',
            'items.*.variants' => 'nullable|array',
            'items.*.addons' => 'nullable|array',
            'notes' => 'nullable|string|max:1000',
            'customer_notes' => 'nullable|string|max:500',
        ]);

        DB::beginTransaction();
        try {
            // Calculate totals (prices are VAT inclusive)
            $subtotal = 0;
            $orderItems = [];

            foreach ($request->items as $itemData) {
                $menuItem = MenuItem::find($itemData['menu_item_id']);
                
                if (!$menuItem->canBeOrdered()) {
                    throw new \Exception("Item '{$menuItem->name}' is not available");
                }

                $itemPrice = $menuItem->price;
                $quantity = $itemData['quantity'];
                $totalPrice = $itemPrice * $quantity;

                // Add addon prices
                if (isset($itemData['addons'])) {
                    foreach ($itemData['addons'] as $addon) {
                        $totalPrice += ($addon['price'] ?? 0) * $quantity;
                    }
                }

                $subtotal += $totalPrice;

                $orderItems[] = [
                    'menu_item_id' => $menuItem->id,
                    'item_name' => $menuItem->name,
                    'item_price' => $itemPrice,
                    'quantity' => $quantity,
                    'total_price' => $totalPrice,
                    'variants' => $itemData['variants'] ?? null,
                    'addons' => $itemData['addons'] ?? null,
                    'special_instructions' => $itemData['special_instructions'] ?? null,
                    'kitchen_station' => $menuItem->kitchen_stations[0] ?? 'main',
                ];
            }

            // No VAT calculation - prices are inclusive
            $taxAmount = 0;
            $totalAmount = $subtotal;

            // Create order
            $order = Order::create([
                'restaurant_id' => $request->user()->restaurant_id,
                'branch_id' => $request->user()->branch_id ?? 1, // Fallback to branch 1 if null
                'table_id' => $request->table_id,
                'user_id' => $request->user()->id,
                'customer_id' => $request->customer_id,
                'type' => $request->type,
                'status' => 'pending',
                'payment_status' => 'unpaid', // Default to unpaid, will be updated when payment is processed
                'subtotal' => $subtotal,
                'tax_amount' => $taxAmount,
                'discount_amount' => 0,
                'total_amount' => $totalAmount,
                'notes' => $request->notes,
                'customer_notes' => $request->customer_notes,
                'ordered_at' => now(),
            ]);

            // Create order items
            foreach ($orderItems as $itemData) {
                $order->items()->create($itemData);
            }

            // Mark table as occupied if dine-in
            if ($request->type === 'dine_in' && $request->table_id) {
                $order->table->occupy();
            }

            // Create kitchen tickets by station
            $this->createKitchenTickets($order);

            // Adjust inventory if tracking is enabled
            foreach ($order->items as $orderItem) {
                if ($orderItem->menuItem->track_inventory) {
                    $orderItem->menuItem->adjustStock(-$orderItem->quantity, $order->order_number);
                }
            }

            DB::commit();

            return response()->json([
                'message' => 'Order created successfully',
                'order' => $order->load(['table', 'user', 'customer', 'items.menuItem']),
            ], 201);

        } catch (\Exception $e) {
            DB::rollback();
            return response()->json(['error' => $e->getMessage()], 400);
        }
    }

    public function show(Order $order): JsonResponse
    {
        $order->load(['table', 'user', 'customer', 'items.menuItem', 'payments', 'kitchenTickets']);

        return response()->json([
            'order' => $order,
            'is_paid' => $order->isPaid(),
            'remaining_amount' => $order->getRemainingAmount(),
        ]);
    }

    public function update(Request $request, Order $order): JsonResponse
    {
        $request->validate([
            'notes' => 'nullable|string|max:1000',
            'customer_notes' => 'nullable|string|max:500',
        ]);

        $order->update($request->only(['notes', 'customer_notes']));

        return response()->json([
            'message' => 'Order updated successfully',
            'order' => $order->load(['table', 'user', 'customer', 'items.menuItem']),
        ]);
    }

    public function updateStatus(Request $request, Order $order): JsonResponse
    {
        $request->validate([
            'status' => 'required|in:pending,confirmed,completed,cancelled',
        ]);

        $updateData = ['status' => $request->status];

        // Update timestamps based on status
        switch ($request->status) {
            case 'confirmed':
                $updateData['confirmed_at'] = now();
                break;
            case 'completed':
                $updateData['completed_at'] = now();
                if ($order->table && $order->type === 'dine_in') {
                    $order->table->makeAvailable();
                }
                break;
            case 'cancelled':
                $updateData['cancelled_at'] = now();
                $updateData['was_cancelled'] = true;
                break;
        }

        $order->update($updateData);

        return response()->json([
            'message' => 'Order status updated successfully',
            'order' => $order->fresh(),
        ]);
    }

    public function updatePaymentStatus(Request $request, Order $order): JsonResponse
    {
        $request->validate([
            'payment_status' => 'required|in:unpaid,pending,partial,paid',
        ]);

        $order->update(['payment_status' => $request->payment_status]);

        return response()->json([
            'message' => 'Payment status updated successfully',
            'order' => $order->fresh(),
        ]);
    }

    public function cancel(Order $order): JsonResponse
    {
        if (!in_array($order->status, ['pending', 'confirmed'])) {
            return response()->json(['error' => 'Cannot cancel order in current status'], 400);
        }

        DB::beginTransaction();
        try {
            // Restore inventory
            foreach ($order->items as $orderItem) {
                if ($orderItem->menuItem->track_inventory) {
                    $orderItem->menuItem->adjustStock($orderItem->quantity, $order->order_number . '-CANCELLED');
                }
            }

            // Update order status
            $order->update([
                'status' => 'cancelled',
                'cancelled_at' => now(),
                'was_cancelled' => true
            ]);

            // Make table available
            if ($order->table && $order->type === 'dine_in') {
                $order->table->makeAvailable();
            }

            DB::commit();

            return response()->json(['message' => 'Order cancelled successfully']);

        } catch (\Exception $e) {
            DB::rollback();
            return response()->json(['error' => $e->getMessage()], 400);
        }
    }

    public function addItem(Request $request, Order $order): JsonResponse
    {
        if (!in_array($order->status, ['pending', 'confirmed'])) {
            return response()->json(['error' => 'Cannot add items to order in current status'], 400);
        }

        $request->validate([
            'menu_item_id' => 'required|exists:menu_items,id',
            'quantity' => 'required|integer|min:1',
            'special_instructions' => 'nullable|string|max:500',
            'variants' => 'nullable|array',
            'addons' => 'nullable|array',
        ]);

        DB::beginTransaction();
        try {
            $menuItem = MenuItem::find($request->menu_item_id);
            
            if (!$menuItem->canBeOrdered()) {
                throw new \Exception("Item '{$menuItem->name}' is not available");
            }

            $itemPrice = $menuItem->price;
            $quantity = $request->quantity;
            $totalPrice = $itemPrice * $quantity;

            // Add addon prices
            if ($request->addons) {
                foreach ($request->addons as $addon) {
                    $totalPrice += ($addon['price'] ?? 0) * $quantity;
                }
            }

            // Create order item
            $orderItem = $order->items()->create([
                'menu_item_id' => $menuItem->id,
                'item_name' => $menuItem->name,
                'item_price' => $itemPrice,
                'quantity' => $quantity,
                'total_price' => $totalPrice,
                'variants' => $request->variants,
                'addons' => $request->addons,
                'special_instructions' => $request->special_instructions,
                'kitchen_station' => $menuItem->kitchen_stations[0] ?? 'main',
            ]);

            // Update order totals
            $this->recalculateOrderTotals($order);

            // Adjust inventory
            if ($menuItem->track_inventory) {
                $menuItem->adjustStock(-$quantity, $order->order_number);
            }

            DB::commit();

            return response()->json([
                'message' => 'Item added to order successfully',
                'order_item' => $orderItem->load('menuItem'),
                'order' => $order->fresh(),
            ]);

        } catch (\Exception $e) {
            DB::rollback();
            return response()->json(['error' => $e->getMessage()], 400);
        }
    }

    public function updateItem(Request $request, Order $order, OrderItem $item): JsonResponse
    {
        if (!in_array($order->status, ['pending', 'confirmed'])) {
            return response()->json(['error' => 'Cannot update items in current status'], 400);
        }

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

        DB::beginTransaction();
        try {
            $oldQuantity = $item->quantity;
            $newQuantity = $request->quantity;
            $quantityDiff = $newQuantity - $oldQuantity;

            // Update item
            $item->update([
                'quantity' => $newQuantity,
                'total_price' => $item->item_price * $newQuantity,
                'special_instructions' => $request->special_instructions,
            ]);

            // Update order totals
            $this->recalculateOrderTotals($order);

            // Adjust inventory
            if ($item->menuItem->track_inventory && $quantityDiff != 0) {
                $item->menuItem->adjustStock(-$quantityDiff, $order->order_number);
            }

            DB::commit();

            return response()->json([
                'message' => 'Order item updated successfully',
                'order_item' => $item->fresh(),
                'order' => $order->fresh(),
            ]);

        } catch (\Exception $e) {
            DB::rollback();
            return response()->json(['error' => $e->getMessage()], 400);
        }
    }

    public function removeItem(Order $order, OrderItem $item): JsonResponse
    {
        if (!in_array($order->status, ['pending', 'confirmed'])) {
            return response()->json(['error' => 'Cannot remove items in current status'], 400);
        }

        DB::beginTransaction();
        try {
            // Restore inventory
            if ($item->menuItem->track_inventory) {
                $item->menuItem->adjustStock($item->quantity, $order->order_number . '-REMOVED');
            }

            $item->delete();

            // Update order totals
            $this->recalculateOrderTotals($order);

            DB::commit();

            return response()->json([
                'message' => 'Item removed from order successfully',
                'order' => $order->fresh(),
            ]);

        } catch (\Exception $e) {
            DB::rollback();
            return response()->json(['error' => $e->getMessage()], 400);
        }
    }

    private function createKitchenTickets(Order $order): void
    {
        $itemsByStation = $order->items->groupBy('kitchen_station');

        foreach ($itemsByStation as $station => $items) {
            $ticketItems = $items->map(function ($item) {
                return [
                    'order_item_id' => $item->id,
                    'name' => $item->item_name,
                    'quantity' => $item->quantity,
                    'variants' => $item->variants,
                    'special_instructions' => $item->special_instructions,
                ];
            })->toArray();

            KitchenTicket::create([
                'order_id' => $order->id,
                'branch_id' => $order->branch_id ?? 1, // Fallback to branch 1 if null
                'station' => $station,
                'priority' => 'normal',
                'status' => 'pending',
                'items' => $ticketItems,
                'special_instructions' => $order->customer_notes,
            ]);
        }
    }

    private function recalculateOrderTotals(Order $order): void
    {
        $subtotal = $order->items()->sum('total_price');
        // No VAT calculation - prices are inclusive
        $taxAmount = 0;
        $totalAmount = $subtotal - $order->discount_amount;

        $order->update([
            'subtotal' => $subtotal,
            'tax_amount' => $taxAmount,
            'total_amount' => $totalAmount,
        ]);
    }
}