<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\InventoryCategory;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;

class InventoryCategoryController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth:sanctum');
    }

    public function index(Request $request)
    {
        $query = InventoryCategory::with('restaurant');

        // Filter by restaurant
        $user = $request->user();
        
        // Default categories are visible to all users
        // User-specific categories are filtered by restaurant
        if (!$user->isAdmin() && $user->restaurant_id) {
            // Non-admin users (restaurant owners, inventory managers) see: default categories + their restaurant's categories
            $query->where(function($q) use ($user) {
                $q->where('is_default', true)
                  ->orWhere('restaurant_id', $user->restaurant_id);
            });
        } elseif ($request->has('restaurant_id') && $request->restaurant_id) {
            // Admin filtering by restaurant: show default + selected restaurant's categories
            $query->where(function($q) use ($request) {
                $q->where('is_default', true)
                  ->orWhere('restaurant_id', $request->restaurant_id);
            });
        } else {
            // Admin without filter: show all categories (default + all restaurant categories)
            // No additional filter needed
        }

        // Filter by branch manager - they see only their branch's restaurant categories
        if ($user->isBranchManager() && $user->branch_id) {
            $branch = \App\Models\Branch::find($user->branch_id);
            if ($branch && $branch->restaurant_id) {
                $query->where(function($q) use ($branch) {
                    $q->where('is_default', true)
                      ->orWhere('restaurant_id', $branch->restaurant_id);
                });
            }
        }

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

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

        $categories = $query->orderBy('is_default', 'desc')->orderBy('name')->paginate($request->get('per_page', 50));

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

    public function store(Request $request)
    {
        $user = $request->user();
        
        // Determine restaurant_id first
        $restaurantId = null;
        if ($user->isAdmin()) {
            // Admin must provide restaurant_id
            if (!$request->has('restaurant_id') || !$request->restaurant_id) {
                return response()->json([
                    'error' => 'Restaurant selection is required'
                ], 400);
            }
            $restaurantId = $request->restaurant_id;
        } elseif ($user->isInventoryManager() && $user->restaurant_id) {
            // Inventory manager: use their assigned restaurant_id
            $restaurantId = $user->restaurant_id;
        } elseif ($user->isBranchManager() && $user->branch_id) {
            // Branch manager: get restaurant_id from their branch
            $branch = \App\Models\Branch::find($user->branch_id);
            if ($branch && $branch->restaurant_id) {
                $restaurantId = $branch->restaurant_id;
            } else {
                return response()->json([
                    'error' => 'Your branch is not assigned to a restaurant'
                ], 400);
            }
        } else {
            // Restaurant owner and other users use their assigned restaurant_id
            if ($user->restaurant_id) {
                $restaurantId = $user->restaurant_id;
            } else {
                return response()->json([
                    'error' => 'Your account is not assigned to a restaurant'
                ], 400);
            }
        }

        // Validate with unique check per restaurant (excluding default categories)
        $validated = $request->validate([
            'name' => [
                'required',
                'max:255',
                Rule::unique('inventory_categories', 'name')
                    ->where('restaurant_id', $restaurantId)
                    ->where('is_default', false),
            ],
            'description' => 'nullable|string',
            'status' => 'required|in:active,inactive',
        ]);

        $validated['restaurant_id'] = $restaurantId;
        $validated['is_default'] = false; // User-created categories are never default
        $category = InventoryCategory::create($validated);
        $category->load('restaurant');

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

    public function show(InventoryCategory $inventoryCategory)
    {
        $inventoryCategory->load('restaurant');
        // Ensure restaurant_id is included even if null
        return response()->json($inventoryCategory);
    }

    public function update(Request $request, $id)
    {
        // Find the category directly to avoid route model binding issues
        $inventoryCategory = InventoryCategory::find($id);
        
        if (!$inventoryCategory) {
            return response()->json([
                'error' => 'Category not found'
            ], 404);
        }
        
        // Prevent updating default categories
        if ($inventoryCategory->is_default) {
            return response()->json([
                'error' => 'Default categories cannot be updated'
            ], 403);
        }

        $user = $request->user();
        
        // Verify user has permission to update this category
        if (!$user->isAdmin()) {
            $userRestaurantId = null;
            if ($user->isInventoryManager() && $user->restaurant_id) {
                // Inventory manager: use their assigned restaurant_id
                $userRestaurantId = $user->restaurant_id;
            } elseif ($user->isBranchManager() && $user->branch_id) {
                // Branch manager: get restaurant_id from their branch
                $branch = \App\Models\Branch::find($user->branch_id);
                $userRestaurantId = $branch ? $branch->restaurant_id : null;
            } else {
                $userRestaurantId = $user->restaurant_id;
            }
            
            // Non-admin users can only update categories from their restaurant
            // Ensure proper type casting for comparison
            $categoryRestaurantId = (int) $inventoryCategory->restaurant_id;
            $userRestaurantIdInt = (int) $userRestaurantId;
            if ($categoryRestaurantId !== $userRestaurantIdInt) {
                return response()->json([
                    'error' => 'Unauthorized to update this category. You can only update categories from your own restaurant.'
                ], 403);
            }
            
            // For branch managers, verify branch access if category has branch_id
            // PRIMARY CHECK: If branch_id matches, allow update (branch_id match is sufficient)
            if ($user->isBranchManager() && $user->branch_id) {
                $categoryBranchId = $inventoryCategory->branch_id ? (int) $inventoryCategory->branch_id : null;
                $userBranchId = (int) $user->branch_id;
                // If category has branch_id, it must match user's branch_id
                if ($categoryBranchId !== null && $categoryBranchId !== $userBranchId) {
                    return response()->json([
                        'error' => 'Unauthorized to update this category. You can only update categories from your own branch.'
                    ], 403);
                }
            }
        }
        
        // Always keep the existing restaurant_id - categories cannot change restaurants
        // This ensures the category always belongs to the restaurant it was created with
        $restaurantId = $inventoryCategory->restaurant_id;
        
        // If restaurant_id is null, try to get it from the request (for backward compatibility)
        if (!$restaurantId && $request->has('restaurant_id') && $request->restaurant_id) {
            $restaurantId = $request->restaurant_id;
        }

        // For custom categories, remove name validation completely - allow any name
        $validated = $request->validate([
            'name' => 'required|max:255',
            'description' => 'nullable|string',
            'status' => 'required|in:active,inactive',
        ]);

        // Always use the existing restaurant_id - never change it
        // Only set restaurant_id if it exists (for backward compatibility with legacy data)
        if ($restaurantId) {
            $validated['restaurant_id'] = $restaurantId;
        }
        
        // Update the category
        $inventoryCategory->update($validated);
        
        // Refresh the model to get updated data
        $inventoryCategory->refresh();
        $inventoryCategory->load('restaurant');

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

    public function destroy($id)
    {
        $user = request()->user();
        
        // Find the category directly (not using route model binding to avoid soft-delete issues)
        $inventoryCategory = InventoryCategory::find($id);
        
        if (!$inventoryCategory) {
            return response()->json([
                'error' => 'Category not found'
            ], 404);
        }
        
        // Store category details BEFORE any operations that might affect the model
        $categoryId = $inventoryCategory->id;
        $categoryName = $inventoryCategory->name;
        $categoryRestaurantId = $inventoryCategory->restaurant_id;
        $isDefault = $inventoryCategory->is_default;
        
        // Prevent deleting default categories
        if ($isDefault) {
            return response()->json([
                'error' => 'Default categories cannot be deleted'
            ], 403);
        }

        // Refresh to ensure latest data
        $inventoryCategory->refresh();
        
        // Verify user has permission to delete this category
        // Admin can delete any user-created category
        // Regular users can only delete their own restaurant's categories
        if (!$user->isAdmin()) {
            // For inventory managers, check restaurant_id
            if ($user->isInventoryManager() && $user->restaurant_id) {
                $categoryRestaurantIdInt = (int) $categoryRestaurantId;
                $userRestaurantIdInt = (int) $user->restaurant_id;
                if ($categoryRestaurantIdInt !== $userRestaurantIdInt) {
                    return response()->json([
                        'error' => 'Unauthorized to delete this category. You can only delete categories from your own restaurant.'
                    ], 403);
                }
            }
            // For branch managers, PRIMARY CHECK: If branch_id matches, allow deletion
            elseif ($user->isBranchManager() && $user->branch_id) {
                $categoryBranchId = $inventoryCategory->branch_id ? (int) $inventoryCategory->branch_id : null;
                $userBranchId = (int) $user->branch_id;
                // If category has branch_id, it must match user's branch_id
                if ($categoryBranchId !== null && $categoryBranchId === $userBranchId) {
                    // Branch IDs match - allow deletion, continue
                } else {
                    // If branch_id doesn't match or category has no branch_id, check restaurant_id
                    $branch = \App\Models\Branch::find($user->branch_id);
                    $userRestaurantId = $branch ? $branch->restaurant_id : null;
                    $categoryRestaurantIdInt = (int) $categoryRestaurantId;
                    $userRestaurantIdInt = $userRestaurantId ? (int) $userRestaurantId : null;
                    if ($categoryRestaurantIdInt !== $userRestaurantIdInt) {
                        return response()->json([
                            'error' => 'Unauthorized to delete this category. You can only delete categories from your own restaurant.'
                        ], 403);
                    }
                }
            } else {
                // Restaurant owner and other users
                $userRestaurantId = $user->restaurant_id;
                $categoryRestaurantIdInt = (int) $categoryRestaurantId;
                $userRestaurantIdInt = $userRestaurantId ? (int) $userRestaurantId : null;
                if ($categoryRestaurantIdInt !== $userRestaurantIdInt) {
                    return response()->json([
                        'error' => 'Unauthorized to delete this category. You can only delete categories from your own restaurant.'
                    ], 403);
                }
            }
        }

        // Check if category is being used - only check within the same restaurant
        // Use withTrashed to check even soft-deleted inventories/items
        $inventoriesCount = \App\Models\Inventory::withTrashed()
            ->where('category_id', $categoryId)
            ->where('restaurant_id', $categoryRestaurantId)
            ->count();
        $itemsCount = \App\Models\Item::withTrashed()
            ->where('category_id', $categoryId)
            ->where('restaurant_id', $categoryRestaurantId)
            ->count();
        
        if ($inventoriesCount > 0 || $itemsCount > 0) {
            return response()->json([
                'error' => 'Cannot delete category. It is being used by ' . ($inventoriesCount + $itemsCount) . ' item(s).'
            ], 400);
        }

        // Use forceDelete to permanently delete user-created categories (hard delete)
        // This completely removes the record from the database, bypassing soft deletes
        $deleted = $inventoryCategory->forceDelete();

        // Verify deletion by checking if record still exists (even with soft deletes)
        $stillExists = InventoryCategory::withTrashed()->find($categoryId);
        
        return response()->json([
            'message' => 'Category deleted successfully',
            'deleted' => !$stillExists,
            'category_id' => $categoryId,
            'category_name' => $categoryName
        ]);
    }
}

