<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Http\Controllers\Api\Helpers\RestaurantBranchFilterTrait;
use App\Models\RestaurantMenuCategory;
use App\Models\Branch;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;

class AdminMenuCategoryController extends Controller
{
    use RestaurantBranchFilterTrait;

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

    public function index(Request $request)
    {
        $user = $request->user();
        
        // Allow admin, restaurant owners, and branch managers
        if (!$user->isAdmin() && !$user->isRestaurantOwner() && !$user->isBranchManager()) {
            return response()->json(['error' => 'Unauthorized'], 403);
        }

        // Eager load relationships - Laravel handles null relationships automatically
        $query = RestaurantMenuCategory::with(['branch', 'restaurant']);

        // Apply role-based filtering
        if ($user->isAdmin()) {
            // Admin: filter by restaurant and branch if provided
            if ($request->has('restaurant_id') && $request->restaurant_id) {
                $query->where('restaurant_id', $request->restaurant_id);
            }
            if ($request->has('branch_id') && $request->branch_id) {
                $query->where('branch_id', $request->branch_id);
            }
        } elseif ($user->isRestaurantOwner() && $user->restaurant_id) {
            // Restaurant owner: filter by their restaurant
            $query->where('restaurant_id', $user->restaurant_id);
            // Filter by branch if selected
            if ($request->has('branch_id') && $request->branch_id) {
                // Verify branch belongs to restaurant
                $branch = Branch::find($request->branch_id);
                if ($branch && $branch->restaurant_id === $user->restaurant_id) {
                    $query->where('branch_id', $request->branch_id);
                }
            }
        } elseif ($user->isBranchManager() && $user->branch_id) {
            // Branch manager: filter by their branch OR categories without branch_id that belong to their restaurant
            // Store branch_id in a variable to use in closures
            $userBranchId = (int) $user->branch_id;
            
            // Load user's branch relationship if not already loaded
            $restaurantId = null;
            if (!$user->relationLoaded('branch')) {
                try {
                    $user->load('branch');
                    if ($user->branch && isset($user->branch->restaurant_id)) {
                        $restaurantId = (int) $user->branch->restaurant_id;
                    }
                } catch (\Exception $e) {
                    // If branch loading fails, log error and fallback to branch_id filter only
                    Log::error('Failed to load branch for branch manager: ' . $e->getMessage());
                }
            } else {
                // Branch relationship already loaded
                if ($user->branch && isset($user->branch->restaurant_id)) {
                    $restaurantId = (int) $user->branch->restaurant_id;
                }
            }
            
            if ($restaurantId) {
                // Show categories that:
                // 1. Belong to their branch (branch_id matches), OR
                // 2. Have no branch_id but belong to their restaurant (for backward compatibility)
                $query->where(function($q) use ($userBranchId, $restaurantId) {
                    $q->where('branch_id', $userBranchId)
                      ->orWhere(function($subQ) use ($restaurantId) {
                          $subQ->whereNull('branch_id')
                               ->where('restaurant_id', $restaurantId);
                      });
                });
            } else {
                // Fallback: only show categories with their branch_id
                $query->where('branch_id', $userBranchId);
            }
        }

        // Filter by status (convert string to boolean if needed)
        if ($request->has('status') && $request->status !== '') {
            $statusValue = $request->status;
            // If status is 'active' or 'inactive', convert to boolean
            if (in_array($statusValue, ['active', 'inactive'])) {
                $statusValue = $statusValue === 'active';
            }
            $query->where('status', $statusValue);
        }

        try {
            $categories = $query->orderBy('name')->get();
            return response()->json($categories);
        } catch (\Exception $e) {
            Log::error('Error loading menu categories: ' . $e->getMessage(), [
                'trace' => $e->getTraceAsString(),
                'user_id' => $user->id ?? null,
                'user_role' => $user->role ?? null,
            ]);
            return response()->json([
                'error' => 'Failed to load categories',
                'message' => config('app.debug') ? $e->getMessage() : 'An error occurred while loading categories'
            ], 500);
        }
    }

    public function store(Request $request)
    {
        $user = $request->user();
        
        // Allow admin, restaurant owners, and branch managers
        if (!$user->isAdmin() && !$user->isRestaurantOwner() && !$user->isBranchManager()) {
            return response()->json(['error' => 'Unauthorized'], 403);
        }

        $validated = $request->validate([
            'name' => 'required|string|max:255',
            'description' => 'nullable|string',
            'status' => 'required|in:active,inactive',
            'restaurant_id' => 'nullable|exists:restaurants,id',
            'branch_id' => 'nullable|exists:branches,id',
            'display_order' => 'nullable|integer',
        ]);

        // Get restaurant and branch context
        $context = $this->getRestaurantBranchContext($user, $request);

        // Determine restaurant_id and branch_id based on user role
        $restaurantId = null;
        $branchId = null;

        if ($user->isAdmin()) {
            // Admin must provide restaurant_id and branch_id
            $restaurantId = $validated['restaurant_id'] ?? $context['restaurant_id'] ?? null;
            $branchId = $validated['branch_id'] ?? $context['branch_id'] ?? null;
            
            if (!$restaurantId || !$branchId) {
                return response()->json([
                    'error' => 'Restaurant and branch selection is required'
                ], 422);
            }
        } elseif ($user->isRestaurantOwner()) {
            // Restaurant owner: restaurant_id from user, branch_id from selection
            $restaurantId = $user->restaurant_id;
            $branchId = $validated['branch_id'] ?? $context['branch_id'] ?? $request->input('branch_id');
            
            if (!$branchId) {
                return response()->json([
                    'error' => 'Branch selection is required. Please select a branch first.'
                ], 422);
            }
            
            // Verify branch belongs to restaurant
            $branch = Branch::find($branchId);
            if (!$branch || $branch->restaurant_id !== $restaurantId) {
                return response()->json([
                    'error' => 'Invalid branch. The selected branch does not belong to your restaurant.'
                ], 422);
            }
        } elseif ($user->isBranchManager()) {
            // Branch manager: get from user's branch
            $branchId = $user->branch_id;
            if ($user->branch && $user->branch->restaurant_id) {
                $restaurantId = $user->branch->restaurant_id;
            } else {
                return response()->json([
                    'error' => 'Your branch is not assigned to a restaurant'
                ], 422);
            }
        }

        // Set restaurant_id and branch_id in validated array
        $validated['restaurant_id'] = $restaurantId;
        $validated['branch_id'] = $branchId;

        // Convert status string to boolean (database expects boolean)
        $validated['status'] = $validated['status'] === 'active';

        $category = RestaurantMenuCategory::create($validated);
        $category->load(['branch', 'restaurant']);

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

    public function show(RestaurantMenuCategory $restaurantMenuCategory)
    {
        $user = request()->user();
        
        // Allow admin, restaurant owners, and branch managers
        if (!$user->isAdmin() && !$user->isRestaurantOwner() && !$user->isBranchManager()) {
            return response()->json(['error' => 'Unauthorized'], 403);
        }

        // Verify access
        if ($user->isRestaurantOwner() && $restaurantMenuCategory->restaurant_id !== $user->restaurant_id) {
            return response()->json(['error' => 'Unauthorized'], 403);
        }
        if ($user->isBranchManager() && $restaurantMenuCategory->branch_id !== $user->branch_id) {
            return response()->json(['error' => 'Unauthorized'], 403);
        }

        $restaurantMenuCategory->load(['branch', 'restaurant']);
        return response()->json($restaurantMenuCategory);
    }

    public function update(Request $request, RestaurantMenuCategory $restaurantMenuCategory)
    {
        $user = $request->user();
        
        // Load user's branch relationship if not already loaded
        if (!$user->relationLoaded('branch')) {
            $user->load('branch');
        }
        
        // Allow admin, restaurant owners, and branch managers
        if (!$user->isAdmin() && !$user->isRestaurantOwner() && !$user->isBranchManager()) {
            return response()->json(['error' => 'Unauthorized'], 403);
        }

        // Verify access - ensure proper type casting for comparison
        if ($user->isRestaurantOwner()) {
            $categoryRestaurantId = $restaurantMenuCategory->restaurant_id ? (int) $restaurantMenuCategory->restaurant_id : null;
            $userRestaurantId = $user->restaurant_id ? (int) $user->restaurant_id : null;
            if ($categoryRestaurantId !== $userRestaurantId) {
                return response()->json(['error' => 'Unauthorized. You can only update categories from your own restaurant.'], 403);
            }
        }
        if ($user->isBranchManager()) {
            // Ensure user has a branch_id
            if (!$user->branch_id) {
                return response()->json(['error' => 'Unauthorized. Your account is not assigned to a branch.'], 403);
            }
            
            // Refresh the category to ensure we have the latest data
            $restaurantMenuCategory->refresh();
            
            // Load user's branch relationship if not already loaded
            if (!$user->relationLoaded('branch')) {
                try {
                    $user->load('branch');
                } catch (\Exception $e) {
                    Log::error('Failed to load branch for branch manager in update: ' . $e->getMessage());
                }
            }
            
            // Get branch IDs with proper type casting
            $categoryBranchId = $restaurantMenuCategory->branch_id ? (int) $restaurantMenuCategory->branch_id : null;
            $userBranchId = (int) $user->branch_id;
            
            // Get restaurant IDs
            $categoryRestaurantId = $restaurantMenuCategory->restaurant_id ? (int) $restaurantMenuCategory->restaurant_id : null;
            $branchRestaurantId = null;
            if ($user->branch && isset($user->branch->restaurant_id)) {
                $branchRestaurantId = (int) $user->branch->restaurant_id;
            }
            
            // PRIMARY CHECK: If branch_id matches, allow update (sufficient proof)
            if ($categoryBranchId !== null && $categoryBranchId === $userBranchId) {
                // Branch IDs match - allow update, continue
            } 
            // SECONDARY CHECK: If category has no branch_id but belongs to same restaurant, allow update
            // This handles categories created before branch_id was required
            // Branch managers should be able to manage all categories from their branch's restaurant
            elseif ($categoryBranchId === null) {
                // If category has no branch_id, check if it belongs to the same restaurant as the branch
                if ($categoryRestaurantId !== null && $branchRestaurantId !== null && $categoryRestaurantId === $branchRestaurantId) {
                    // Category belongs to same restaurant as branch manager's branch - allow update
                } else {
                    // Category doesn't belong to the branch's restaurant
                    return response()->json([
                        'error' => 'Unauthorized. This category does not belong to your restaurant.',
                        'debug' => config('app.debug') ? [
                            'category_branch_id' => $categoryBranchId,
                            'user_branch_id' => $userBranchId,
                            'category_restaurant_id' => $categoryRestaurantId,
                            'branch_restaurant_id' => $branchRestaurantId,
                        ] : null
                    ], 403);
                }
            }
            // DENY: Branch IDs don't match
            else {
                return response()->json([
                    'error' => 'Unauthorized. You can only update categories from your own branch.',
                    'debug' => config('app.debug') ? [
                        'category_branch_id' => $categoryBranchId,
                        'user_branch_id' => $userBranchId,
                        'category_restaurant_id' => $categoryRestaurantId,
                        'branch_restaurant_id' => $branchRestaurantId,
                    ] : null
                ], 403);
            }
        }

        $validated = $request->validate([
            'name' => 'required|string|max:255',
            'description' => 'nullable|string',
            'status' => 'required|in:active,inactive',
            'restaurant_id' => 'nullable|exists:restaurants,id',
            'branch_id' => 'nullable|exists:branches,id',
            'display_order' => 'nullable|integer',
        ]);

        // Get restaurant and branch context
        $context = $this->getRestaurantBranchContext($user, $request);

        // Determine restaurant_id and branch_id based on user role
        if ($user->isAdmin()) {
            // Admin can update restaurant_id and branch_id if provided
            if (isset($validated['restaurant_id'])) {
                $validated['restaurant_id'] = $validated['restaurant_id'];
            } else {
                $validated['restaurant_id'] = $restaurantMenuCategory->restaurant_id; // Keep existing
            }
            if (isset($validated['branch_id'])) {
                $validated['branch_id'] = $validated['branch_id'];
            } else {
                $validated['branch_id'] = $restaurantMenuCategory->branch_id; // Keep existing
            }
        } elseif ($user->isRestaurantOwner()) {
            // Restaurant owner: cannot change restaurant_id, can change branch_id
            $validated['restaurant_id'] = $user->restaurant_id;
            
            $branchId = $validated['branch_id'] ?? $context['branch_id'] ?? $request->input('branch_id') ?? $restaurantMenuCategory->branch_id;
            
            // Verify branch belongs to restaurant
            $branch = Branch::find($branchId);
            if (!$branch || $branch->restaurant_id !== $user->restaurant_id) {
                return response()->json([
                    'error' => 'Invalid branch. The selected branch does not belong to your restaurant.'
                ], 422);
            }
            $validated['branch_id'] = $branchId;
        } elseif ($user->isBranchManager()) {
            // Branch manager: cannot change restaurant_id or branch_id
            // Prevent branch managers from changing branch_id
            if (isset($validated['branch_id']) && (int)$validated['branch_id'] !== (int)$user->branch_id) {
                return response()->json(['error' => 'Unauthorized. You cannot change the branch of a category.'], 403);
            }
            
            // Keep existing restaurant_id, or set to branch's restaurant_id if category has none
            if ($restaurantMenuCategory->restaurant_id) {
                $validated['restaurant_id'] = $restaurantMenuCategory->restaurant_id;
            } elseif ($user->branch && $user->branch->restaurant_id) {
                $validated['restaurant_id'] = $user->branch->restaurant_id;
            }
            
            // Set branch_id to user's branch_id (ensures category is assigned to their branch)
            $validated['branch_id'] = $user->branch_id;
        }

        // Convert status string to boolean (database expects boolean)
        $validated['status'] = $validated['status'] === 'active';

        $restaurantMenuCategory->update($validated);
        $restaurantMenuCategory->load(['branch', 'restaurant']);

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

    public function destroy(RestaurantMenuCategory $restaurantMenuCategory)
    {
        $user = request()->user();
        
        // Load user's branch relationship if not already loaded
        if (!$user->relationLoaded('branch')) {
            $user->load('branch');
        }
        
        // Allow admin, restaurant owners, and branch managers
        if (!$user->isAdmin() && !$user->isRestaurantOwner() && !$user->isBranchManager()) {
            return response()->json(['error' => 'Unauthorized'], 403);
        }

        // Refresh the category to ensure we have the latest data
        $restaurantMenuCategory->refresh();
        
        // Verify access - ensure proper type casting for comparison
        if ($user->isRestaurantOwner()) {
            $categoryRestaurantId = $restaurantMenuCategory->restaurant_id ? (int) $restaurantMenuCategory->restaurant_id : null;
            $userRestaurantId = $user->restaurant_id ? (int) $user->restaurant_id : null;
            
            if ($categoryRestaurantId !== $userRestaurantId) {
                return response()->json(['error' => 'Unauthorized. You can only delete categories from your own restaurant.'], 403);
            }
            
            // Verify the category's branch belongs to the restaurant owner's restaurant
            if ($restaurantMenuCategory->branch_id) {
                $categoryBranch = \App\Models\Branch::find($restaurantMenuCategory->branch_id);
                if (!$categoryBranch || (int)$categoryBranch->restaurant_id !== $userRestaurantId) {
                    return response()->json(['error' => 'Unauthorized. This category does not belong to your restaurant.'], 403);
                }
            }
        }
        
        if ($user->isBranchManager()) {
            // Ensure user has a branch_id
            if (!$user->branch_id) {
                return response()->json(['error' => 'Unauthorized. Your account is not assigned to a branch.'], 403);
            }
            
            // Load user's branch relationship if not already loaded
            if (!$user->relationLoaded('branch')) {
                try {
                    $user->load('branch');
                } catch (\Exception $e) {
                    Log::error('Failed to load branch for branch manager in destroy: ' . $e->getMessage());
                }
            }
            
            // Get branch IDs with proper type casting
            $categoryBranchId = $restaurantMenuCategory->branch_id ? (int) $restaurantMenuCategory->branch_id : null;
            $userBranchId = (int) $user->branch_id;
            
            // Branch managers can only delete categories from their own branch
            if ($categoryBranchId === null || $categoryBranchId !== $userBranchId) {
                return response()->json([
                    'error' => 'Unauthorized. You can only delete categories from your own branch.',
                    'debug' => config('app.debug') ? [
                        'category_branch_id' => $categoryBranchId,
                        'user_branch_id' => $userBranchId,
                    ] : null
                ], 403);
            }
        }

        // Check if category has menu items
        // For branch managers, only count menu items from their branch
        $menuItemsQuery = \App\Models\PosMenuItem::where('restaurant_category_id', $restaurantMenuCategory->id);
        
        if ($user->isBranchManager() && $user->branch_id) {
            $menuItemsQuery->where('branch_id', $user->branch_id);
        } elseif ($user->isRestaurantOwner() && $restaurantMenuCategory->branch_id) {
            // For restaurant owners, only count menu items from the same branch as the category
            $menuItemsQuery->where('branch_id', $restaurantMenuCategory->branch_id);
        }
        
        $menuItemsCount = $menuItemsQuery->count();
        
        if ($menuItemsCount > 0) {
            return response()->json([
                'error' => 'Cannot delete category. It is being used by ' . $menuItemsCount . ' menu item(s).'
            ], 400);
        }

        $restaurantMenuCategory->delete();

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


