<?php

namespace App\Http\Controllers;

use App\Models\Category;
use App\Models\MenuItem;
use App\Services\CacheService;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Validation\Rule;

class MenuController extends Controller
{
    // POS-specific methods (read-only for ordering)
    public function posCategories(Request $request): JsonResponse
    {
        $cacheKey = CacheService::key(
            'pos_categories',
            $request->user()->restaurant_id,
            $request->user()->branch_id
        );

        $categories = CacheService::remember($cacheKey, CacheService::MENU_CATEGORIES_TTL, function () use ($request) {
            return Category::where('restaurant_id', $request->user()->restaurant_id)
                ->active()
                ->ordered()
                ->withCount('activeMenuItems')
                ->get();
        });

        return response()->json($categories, 200, CacheService::getHttpHeaders('menu'));
    }

    public function posItems(Request $request): JsonResponse
    {
        $params = [
            'category_id' => $request->get('category_id'),
            'search' => $request->get('search')
        ];

        $cacheKey = CacheService::key(
            'pos_items',
            $request->user()->restaurant_id,
            $request->user()->branch_id,
            array_filter($params)
        );

        $items = CacheService::remember($cacheKey, CacheService::MENU_ITEMS_TTL, function () use ($request) {
            $query = MenuItem::with(['category'])
                ->where('restaurant_id', $request->user()->restaurant_id)
                ->where('is_available', true); // Only show available items for POS

            // Filter by category
            if ($request->has('category_id')) {
                $query->where('category_id', $request->category_id);
            }

            // Search
            if ($request->has('search')) {
                $search = $request->search;
                $query->where(function ($q) use ($search) {
                    $q->where('name', 'like', "%{$search}%")
                      ->orWhere('description', 'like', "%{$search}%");
                });
            }

            return $query->orderBy('name')->get();
        });

        $transformedItems = $items->map(function ($item) {
            return [
                'id' => $item->id,
                'name' => $item->name,
                'description' => $item->description,
                'price' => $item->price,
                'formatted_price' => $item->formatted_price,
                'image_url' => $item->image_url,
                'category' => $item->category,
                'is_available' => $item->is_available,
                'is_in_stock' => $item->isInStock(),
                'prep_time' => $item->prep_time,
                'prep_time_display' => $item->prep_time_display,
                'kitchen_stations' => $item->kitchen_stations,
                'kitchen_stations_display' => $item->kitchen_stations_display,
            ];
        });

        return response()->json($transformedItems, 200, CacheService::getHttpHeaders('menu'));
    }

    // Management methods (for menu management page)
    public function categories(Request $request): JsonResponse
    {
        $categories = Category::where('restaurant_id', $request->user()->restaurant_id)
            ->active()
            ->ordered()
            ->withCount('activeMenuItems')
            ->get();

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

    public function showCategory(Request $request, Category $category): JsonResponse
    {
        // Check permissions
        if ($category->restaurant_id !== $request->user()->restaurant_id) {
            return response()->json(['message' => 'Category not found'], 404);
        }

        $category->loadCount('activeMenuItems');

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

    public function items(Request $request): JsonResponse
    {
        $query = MenuItem::with(['category'])
            ->where('restaurant_id', $request->user()->restaurant_id);

        // Filter by category
        if ($request->has('category_id')) {
            $query->where('category_id', $request->category_id);
        }

        // Filter by availability
        if ($request->has('available')) {
            $query->where('is_available', $request->boolean('available'));
        }

        // Search
        if ($request->has('search')) {
            $search = $request->search;
            $query->where(function ($q) use ($search) {
                $q->where('name', 'like', "%{$search}%")
                  ->orWhere('description', 'like', "%{$search}%");
            });
        }

        $items = $query->orderBy('name')->get();

        return response()->json($items->map(function ($item) {
            return [
                'id' => $item->id,
                'name' => $item->name,
                'description' => $item->description,
                'price' => $item->price,
                'formatted_price' => $item->formatted_price,
                'image_url' => $item->image_url,
                'category' => $item->category,
                'is_available' => $item->is_available,
                'is_in_stock' => $item->isInStock(),
                'prep_time' => $item->prep_time,
                'prep_time_display' => $item->prep_time_display,
                'kitchen_stations' => $item->kitchen_stations,
                'kitchen_stations_display' => $item->kitchen_stations_display,
            ];
        }));
    }

    public function show(MenuItem $item): JsonResponse
    {
        $item->load(['category', 'ingredients']);
        
        return response()->json([
            'id' => $item->id,
            'name' => $item->name,
            'description' => $item->description,
            'price' => $item->price,
            'formatted_price' => $item->formatted_price,
            'image_url' => $item->image_url,
            'category' => $item->category,
            'is_available' => $item->is_available,
            'is_in_stock' => $item->isInStock(),
            'prep_time' => $item->prep_time,
            'kitchen_stations' => $item->kitchen_stations,
            'ingredients' => $item->ingredients,
            'unavailable_ingredients' => $item->checkIngredientAvailability(),
        ]);
    }

    public function storeCategory(Request $request): JsonResponse
    {
        $request->validate([
            'name' => 'required|string|max:255',
            'description' => 'nullable|string',
            'color' => 'required|string|regex:/^#[0-9A-Fa-f]{6}$/',
            'sort_order' => 'nullable|integer|min:0',
        ]);

        $category = Category::create([
            'restaurant_id' => $request->user()->restaurant_id,
            'name' => $request->name,
            'slug' => \Str::slug($request->name),
            'description' => $request->description,
            'color' => $request->color,
            'sort_order' => $request->sort_order ?? 0,
        ]);

        // Clear menu cache so POS shows new categories immediately
        CacheService::clearMenuCache($request->user()->restaurant_id, $request->user()->branch_id);

        return response()->json([
            'message' => 'Category created successfully',
            'category' => $category,
        ], 201);
    }

    public function updateCategory(Request $request, Category $category): JsonResponse
    {
        // Check permissions
        if ($category->restaurant_id !== $request->user()->restaurant_id) {
            return response()->json(['message' => 'Category not found'], 404);
        }

        $request->validate([
            'name' => 'required|string|max:255',
            'description' => 'nullable|string',
            'color' => 'required|string|regex:/^#[0-9A-Fa-f]{6}$/',
            'sort_order' => 'nullable|integer|min:0',
            'is_active' => 'boolean',
        ]);

        $category->update([
            'name' => $request->name,
            'slug' => \Str::slug($request->name),
            'description' => $request->description,
            'color' => $request->color,
            'sort_order' => $request->sort_order ?? $category->sort_order,
            'is_active' => $request->input('is_active', $category->is_active),
        ]);

        // Clear menu cache so POS shows updated categories immediately
        CacheService::clearMenuCache($request->user()->restaurant_id, $request->user()->branch_id);

        return response()->json([
            'message' => 'Category updated successfully',
            'category' => $category,
        ]);
    }

    public function destroyCategory(Request $request, Category $category): JsonResponse
    {
        // Check permissions - Only admin and manager can delete categories
        if (!in_array($request->user()->role, ['admin', 'manager'])) {
            return response()->json(['message' => 'Only administrators and managers can delete categories'], 403);
        }

        if ($category->restaurant_id !== $request->user()->restaurant_id) {
            return response()->json(['message' => 'Category not found'], 404);
        }

        try {
            // Check if category has any menu items
            $menuItemCount = $category->menuItems()->count();
            if ($menuItemCount > 0) {
                return response()->json([
                    'message' => "Cannot delete category. It has {$menuItemCount} associated menu items.",
                    'error' => 'Category has associated menu items'
                ], 422);
            }

            // Delete category image if exists
            if ($category->image && \Storage::disk('public')->exists($category->image)) {
                \Storage::disk('public')->delete($category->image);
            }

            $category->delete();

            // Clear menu cache so POS reflects deleted categories immediately
            CacheService::clearMenuCache($request->user()->restaurant_id, $request->user()->branch_id);

            return response()->json(['message' => 'Category deleted successfully']);

        } catch (\Exception $e) {
            return response()->json([
                'message' => 'Failed to delete category',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    public function storeItem(Request $request): JsonResponse
    {
        // Convert string boolean values from FormData to actual booleans
        $request->merge([
            'track_inventory' => $request->input('track_inventory') === '1' || $request->input('track_inventory') === true,
            'is_available' => $request->input('is_available', '1') === '1' || $request->input('is_available', true) === true,
        ]);

        // Check for duplicate menu item name in the same restaurant
        $existingItem = MenuItem::where('restaurant_id', $request->user()->restaurant_id)
            ->where('name', $request->name)
            ->first();

        if ($existingItem) {
            return response()->json([
                'message' => 'A menu item with this name already exists',
                'error' => 'Duplicate menu item name',
                'errors' => [
                    'name' => ['A menu item with this name already exists in your restaurant']
                ]
            ], 422);
        }

        $request->validate([
            'category_id' => [
                'required',
                Rule::exists('categories', 'id')->where('restaurant_id', $request->user()->restaurant_id),
            ],
            'name' => 'required|string|max:255',
            'description' => 'nullable|string',
            'price' => 'required|numeric|min:0',
            'image' => 'nullable|image|mimes:jpeg,png,jpg,gif|max:2048',
            'prep_time' => 'nullable|integer|min:1|max:180',
            'kitchen_stations' => 'nullable|array',
            'kitchen_stations.*' => 'string|in:main,grill,bar,salad,dessert',
            'track_inventory' => 'boolean',
            'stock_quantity' => 'nullable|integer|min:0',
            'low_stock_alert' => 'nullable|integer|min:0',
        ]);

        $imagePath = null;
        if ($request->hasFile('image')) {
            $imagePath = $request->file('image')->store('menu-items', 'public');
        }

        $item = MenuItem::create([
            'restaurant_id' => $request->user()->restaurant_id,
            'category_id' => $request->category_id,
            'name' => $request->name,
            'slug' => \Str::slug($request->name),
            'description' => $request->description,
            'price' => $request->price,
            'image' => $imagePath,
            'prep_time' => $request->prep_time,
            'kitchen_stations' => $request->kitchen_stations ?? ['main'],
            'track_inventory' => $request->track_inventory,
            'stock_quantity' => $request->stock_quantity,
            'low_stock_alert' => $request->low_stock_alert,
        ]);

        // Clear menu cache so POS shows new items immediately
        CacheService::clearMenuCache($request->user()->restaurant_id, $request->user()->branch_id);

        return response()->json([
            'message' => 'Menu item created successfully',
            'item' => $item->load('category'),
        ], 201);
    }

    public function updateItem(Request $request, MenuItem $item): JsonResponse
    {
        // Convert string boolean values from FormData to actual booleans
        $request->merge([
            'track_inventory' => $request->input('track_inventory') === '1' || $request->input('track_inventory') === true,
            'is_available' => $request->input('is_available', '1') === '1' || $request->input('is_available', true) === true,
        ]);

        // Check for duplicate menu item name in the same restaurant (excluding current item)
        $existingItem = MenuItem::where('restaurant_id', $request->user()->restaurant_id)
            ->where('name', $request->name)
            ->where('id', '!=', $item->id)
            ->first();

        if ($existingItem) {
            return response()->json([
                'message' => 'A menu item with this name already exists',
                'error' => 'Duplicate menu item name',
                'errors' => [
                    'name' => ['A menu item with this name already exists in your restaurant']
                ]
            ], 422);
        }

        $request->validate([
            'category_id' => [
                'required',
                Rule::exists('categories', 'id')->where('restaurant_id', $request->user()->restaurant_id),
            ],
            'name' => 'required|string|max:255',
            'description' => 'nullable|string',
            'price' => 'required|numeric|min:0',
            'image' => 'nullable|image|mimes:jpeg,png,jpg,gif|max:2048',
            'prep_time' => 'nullable|integer|min:1|max:180',
            'kitchen_stations' => 'nullable|array',
            'kitchen_stations.*' => 'string|in:main,grill,bar,salad,dessert',
            'is_available' => 'boolean',
            'track_inventory' => 'boolean',
            'stock_quantity' => 'nullable|integer|min:0',
            'low_stock_alert' => 'nullable|integer|min:0',
        ]);

        $updateData = [
            'category_id' => $request->category_id,
            'name' => $request->name,
            'slug' => \Str::slug($request->name),
            'description' => $request->description,
            'price' => $request->price,
            'prep_time' => $request->prep_time,
            'kitchen_stations' => $request->kitchen_stations ?? ['main'],
            'is_available' => $request->is_available,
            'track_inventory' => $request->track_inventory,
            'stock_quantity' => $request->stock_quantity,
            'low_stock_alert' => $request->low_stock_alert,
        ];

        // Handle image upload
        if ($request->hasFile('image')) {
            // Delete old image if exists
            if ($item->image && \Storage::disk('public')->exists($item->image)) {
                \Storage::disk('public')->delete($item->image);
            }
            $updateData['image'] = $request->file('image')->store('menu-items', 'public');
        }

        $item->update($updateData);

        // Clear menu cache so POS shows updated items immediately
        CacheService::clearMenuCache($request->user()->restaurant_id, $request->user()->branch_id);

        return response()->json([
            'message' => 'Menu item updated successfully',
            'item' => $item->load('category'),
        ]);
    }

    public function destroyItem(MenuItem $item): JsonResponse
    {
        // Check if item is used in any orders
        if ($item->orderItems()->count() > 0) {
            return response()->json([
                'error' => 'Cannot delete menu item that has been ordered'
            ], 400);
        }

        // Get restaurant and branch info before deletion
        $restaurantId = $item->restaurant_id;
        $branchId = null; // We don't have branch_id in MenuItem model, but cache clearing will work

        // Delete image if exists
        if ($item->image && \Storage::disk('public')->exists($item->image)) {
            \Storage::disk('public')->delete($item->image);
        }

        $item->delete();

        // Clear menu cache so POS reflects deleted items immediately
        CacheService::clearMenuCache($restaurantId, $branchId);

        return response()->json(['message' => 'Menu item deleted successfully']);
    }
}