<?php

namespace App\Http\Controllers;

use App\Models\User;
use App\Models\Branch;
use App\Models\Restaurant;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\ValidationException;
use Illuminate\Support\Facades\DB;

class UserController extends Controller
{
    /**
     * Get all users with filtering and pagination
     */
    public function index(Request $request): JsonResponse
    {
        $query = User::with(['restaurant', 'branch']);

        // Filter by role (support multiple roles separated by comma)
        if ($request->has('role') && $request->role !== 'all') {
            $roles = explode(',', $request->role);
            $query->whereIn('role', $roles);
        }

        // Filter by branch
        if ($request->has('branch_id') && $request->branch_id !== 'all') {
            $query->where('branch_id', $request->branch_id);
        }

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

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

        // Apply user's access restrictions
        $currentUser = $request->user();
        if ($currentUser->role !== 'admin') {
            // Non-admin users cannot access user management
            return response()->json(['message' => 'Unauthorized'], 403);
        }

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

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

    /**
     * Get waiters for filtering (accessible to users who can view orders)
     */
    public function getWaiters(Request $request): JsonResponse
    {
        $currentUser = $request->user();
        
        // Build query for users who can take orders (waiters, admins, managers)
        $query = User::select(['id', 'name', 'role'])
            ->where('restaurant_id', $currentUser->restaurant_id)
            ->whereIn('role', ['waiter', 'admin', 'manager'])
            ->where('is_active', true);

        // Filter by branch only for non-admin and non-manager users
        if ($currentUser->branch_id && !in_array($currentUser->role, ['admin', 'manager'])) {
            $query->where('branch_id', $currentUser->branch_id);
        }

        // For managers and admins, show all waiters
        // For other roles, only show users who have actually taken orders
        if (!in_array($currentUser->role, ['admin', 'manager'])) {
            $query->whereHas('orders', function($q) {
                $q->where('created_at', '>=', now()->subDays(30)); // Orders in last 30 days
            });
        }

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

        return response()->json([
            'users' => $waiters,
            'success' => true
        ]);
    }

    /**
     * Create a new user
     */
    public function store(Request $request): JsonResponse
    {
        $currentUser = $request->user();
        
        // Check permissions
        if (!$this->canManageUsers($currentUser)) {
            return response()->json(['message' => 'Unauthorized'], 403);
        }

        $request->validate([
            'name' => 'required|string|max:255',
            'email' => 'required|string|email|max:255|unique:users',
            'password' => 'required|string|min:8',
            'restaurant_id' => 'required|exists:restaurants,id',
            'branch_id' => 'nullable|exists:branches,id',
            'role' => 'required|in:admin,manager,cashier,waiter,kitchen,inventory_manager,accountant',
            'phone' => 'nullable|string|max:20',
            'permissions' => 'nullable|array',
        ]);

        // Validate role permissions
        if (!$this->canAssignRole($currentUser, $request->role)) {
            return response()->json(['message' => 'Cannot assign this role'], 403);
        }

        // Validate restaurant/branch access
        if (!$this->canAccessRestaurant($currentUser, $request->restaurant_id)) {
            return response()->json(['message' => 'Cannot assign user to this restaurant'], 403);
        }

        $userData = [
            'name' => $request->name,
            'email' => $request->email,
            'password' => Hash::make($request->password),
            'restaurant_id' => $request->restaurant_id,
            'branch_id' => $request->branch_id,
            'role' => $request->role,
            'phone' => $request->phone,
            'permissions' => $this->getDefaultPermissions($request->role),
            'is_active' => true,
        ];

        // Override with custom permissions if provided and not empty
        if ($request->has('permissions') && !empty($request->permissions)) {
            $userData['permissions'] = $request->permissions;
        }

        $user = User::create($userData);
        $user->load(['restaurant', 'branch']);

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

    /**
     * Get a specific user
     */
    public function show(Request $request, User $user): JsonResponse
    {
        $currentUser = $request->user();
        
        if (!$this->canViewUser($currentUser, $user)) {
            return response()->json(['message' => 'Unauthorized'], 403);
        }

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

    /**
     * Update a user
     */
    public function update(Request $request, User $user): JsonResponse
    {
        $currentUser = $request->user();
        
        if (!$this->canEditUser($currentUser, $user)) {
            return response()->json(['message' => 'Unauthorized'], 403);
        }

        $request->validate([
            'name' => 'sometimes|required|string|max:255',
            'email' => 'sometimes|required|string|email|max:255|unique:users,email,' . $user->id,
            'restaurant_id' => 'sometimes|required|exists:restaurants,id',
            'branch_id' => 'nullable|exists:branches,id',
            'role' => 'sometimes|required|in:admin,manager,cashier,waiter,kitchen,inventory_manager,accountant',
            'phone' => 'nullable|string|max:20',
            'permissions' => 'nullable|array',
            'is_active' => 'sometimes|boolean',
        ]);

        $updateData = $request->only(['name', 'email', 'phone', 'restaurant_id', 'branch_id', 'is_active']);

        // Handle role change
        if ($request->has('role') && $request->role !== $user->role) {
            if (!$this->canAssignRole($currentUser, $request->role)) {
                return response()->json(['message' => 'Cannot assign this role'], 403);
            }
            $updateData['role'] = $request->role;
            $updateData['permissions'] = $this->getDefaultPermissions($request->role);
        }

        // Handle custom permissions
        if ($request->has('permissions')) {
            $updateData['permissions'] = $request->permissions;
        }

        $user->update($updateData);
        $user->load(['restaurant', 'branch']);

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

    /**
     * Delete a user
     */
    public function destroy(Request $request, User $user): JsonResponse
    {
        $currentUser = $request->user();
        
        if (!$this->canDeleteUser($currentUser, $user)) {
            return response()->json(['message' => 'Unauthorized'], 403);
        }

        // Prevent deleting the last admin
        if ($user->role === 'admin' && User::where('role', 'admin')->count() <= 1) {
            return response()->json(['message' => 'Cannot delete the last admin user'], 400);
        }

        $user->delete();

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

    /**
     * Reset user password
     */
    public function resetPassword(Request $request, User $user): JsonResponse
    {
        $currentUser = $request->user();
        
        if (!$this->canEditUser($currentUser, $user)) {
            return response()->json(['message' => 'Unauthorized'], 403);
        }

        $request->validate([
            'password' => 'required|string|min:8',
        ]);

        $user->update([
            'password' => Hash::make($request->password),
        ]);

        return response()->json(['message' => 'Password reset successfully']);
    }

    /**
     * Get available roles and permissions
     */
    public function getRolesAndPermissions(): JsonResponse
    {
        return response()->json([
            'roles' => $this->getAllRoles(),
            'permissions' => $this->getAllPermissions(),
        ]);
    }

    /**
     * Generate or update PIN for a user
     */
    public function generatePin(Request $request, User $user): JsonResponse
    {
        $currentUser = $request->user();
        
        if (!$this->canEditUser($currentUser, $user)) {
            return response()->json(['message' => 'Unauthorized'], 403);
        }

        // Generate a 4-digit PIN
        $pin = str_pad(rand(1000, 9999), 4, '0', STR_PAD_LEFT);
        
        // Ensure PIN is unique
        while (User::where('pin', $pin)->where('id', '!=', $user->id)->exists()) {
            $pin = str_pad(rand(1000, 9999), 4, '0', STR_PAD_LEFT);
        }

        $user->update(['pin' => $pin]);

        return response()->json([
            'message' => 'PIN generated successfully',
            'pin' => $pin,
        ]);
    }

    /**
     * Remove PIN from a user
     */
    public function removePin(Request $request, User $user): JsonResponse
    {
        $currentUser = $request->user();
        
        if (!$this->canEditUser($currentUser, $user)) {
            return response()->json(['message' => 'Unauthorized'], 403);
        }

        $user->update(['pin' => null]);

        return response()->json(['message' => 'PIN removed successfully']);
    }

    /**
     * Get user statistics
     */
    public function getStats(Request $request): JsonResponse
    {
        $currentUser = $request->user();
        $query = User::query();

        // Apply access restrictions
        if ($currentUser->role !== 'admin') {
            if ($currentUser->role === 'manager') {
                $query->where('restaurant_id', $currentUser->restaurant_id);
            } else {
                $query->where('branch_id', $currentUser->branch_id);
            }
        }

        $stats = [
            'total_users' => $query->count(),
            'active_users' => $query->where('is_active', true)->count(),
            'inactive_users' => $query->where('is_active', false)->count(),
            'by_role' => $query->select('role', DB::raw('count(*) as count'))
                              ->groupBy('role')
                              ->pluck('count', 'role'),
            'recent_logins' => $query->whereNotNull('last_login_at')
                                   ->where('last_login_at', '>=', now()->subDays(7))
                                   ->count(),
        ];

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

    // Helper methods for permission checking

    private function canManageUsers(User $user): bool
    {
        return $user->role === 'admin' || $user->hasPermission('manage_users');
    }

    private function canViewUser(User $currentUser, User $targetUser): bool
    {
        if ($currentUser->id === $targetUser->id) return true;
        if ($currentUser->role === 'admin') return true;
        
        return false;
    }

    private function canEditUser(User $currentUser, User $targetUser): bool
    {
        if ($currentUser->role === 'admin') return true;
        
        return false;
    }

    private function canDeleteUser(User $currentUser, User $targetUser): bool
    {
        if ($currentUser->id === $targetUser->id) return false; // Cannot delete self
        return $this->canEditUser($currentUser, $targetUser);
    }

    private function canAssignRole(User $currentUser, string $role): bool
    {
        if ($currentUser->role === 'admin') return true;
        
        return false;
    }

    private function canAccessRestaurant(User $currentUser, int $restaurantId): bool
    {
        if ($currentUser->role === 'admin') return true;
        return $currentUser->restaurant_id === $restaurantId;
    }

    private function getAllRoles(): array
    {
        return [
            'admin' => [
                'name' => 'Administrator',
                'description' => 'Full system access and management',
                'level' => 1,
            ],
            'manager' => [
                'name' => 'Manager',
                'description' => 'Restaurant/branch management and oversight',
                'level' => 2,
            ],
            'cashier' => [
                'name' => 'Cashier',
                'description' => 'POS operations and payment processing',
                'level' => 3,
            ],
            'waiter' => [
                'name' => 'Waiter/Server',
                'description' => 'Order taking and table service',
                'level' => 4,
            ],
            'kitchen' => [
                'name' => 'Kitchen Staff',
                'description' => 'Kitchen operations and order preparation',
                'level' => 4,
            ],
            'inventory_manager' => [
                'name' => 'Inventory Manager',
                'description' => 'Inventory management and stock control',
                'level' => 3,
            ],
            'accountant' => [
                'name' => 'Accountant',
                'description' => 'Financial reports and accounting',
                'level' => 3,
            ],
        ];
    }

    private function getAllPermissions(): array
    {
        return [
            // POS Permissions
            'access_pos' => 'Access POS system',
            'process_payments' => 'Process payments and refunds',
            'manage_tables' => 'Manage table assignments',
            'view_orders' => 'View order history',
            'modify_orders' => 'Modify existing orders',
            'cancel_orders' => 'Cancel orders',
            
            // Kitchen Permissions
            'access_kitchen' => 'Access kitchen display',
            'update_order_status' => 'Update order preparation status',
            'view_kitchen_tickets' => 'View kitchen tickets',
            
            // Inventory Permissions
            'view_inventory' => 'View inventory levels',
            'manage_inventory' => 'Manage inventory and stock',
            'receive_stock' => 'Receive stock deliveries',
            'adjust_stock' => 'Make stock adjustments',
            
            // Menu Permissions
            'view_menu' => 'View menu items',
            'manage_menu' => 'Manage menu items and categories',
            'update_prices' => 'Update menu prices',
            
            // Reports Permissions
            'view_reports' => 'View basic reports',
            'view_financial_reports' => 'View financial reports',
            'export_reports' => 'Export reports',
            
            // Expense Permissions
            'view_expenses' => 'View expense records',
            'create_expenses' => 'Create new expenses',
            'manage_expenses' => 'Manage and edit expenses',
            'approve_expenses' => 'Approve expense requests',
            'manage_expense_categories' => 'Manage expense categories',
            
            // User Management Permissions
            'manage_users' => 'Manage user accounts',
            'view_user_activity' => 'View user activity logs',
            
            // Waiter Performance Permissions
            'view_own_sales' => 'View own sales performance',
            'view_waiter_reports' => 'View waiter performance reports',
            'track_waiter_performance' => 'Track individual waiter metrics',
            
            // Settings Permissions
            'manage_settings' => 'Manage system settings',
            'manage_branches' => 'Manage branch information',
            'manage_customers' => 'Manage customer information',
        ];
    }

    private function getDefaultPermissions(string $role): array
    {
        return match($role) {
            'admin' => array_keys($this->getAllPermissions()),
            'manager' => [
                'access_pos', 'process_payments', 'manage_tables', 'view_orders', 'modify_orders', 'cancel_orders',
                'access_kitchen', 'update_order_status', 'view_kitchen_tickets',
                'view_inventory', 'manage_inventory', 'receive_stock', 'adjust_stock',
                'view_menu', 'manage_menu', 'update_prices',
                'view_reports', 'view_financial_reports', 'export_reports',
                'manage_users', 'view_user_activity',
                'manage_customers', 'manage_settings', 'manage_branches',
                'view_expenses', 'create_expenses', 'manage_expenses', 'approve_expenses', 'manage_expense_categories', // Added expense permissions
            ],
            'cashier' => [
                'access_pos', 'process_payments', 'manage_tables', 'view_orders', 'modify_orders',
                'view_inventory', 'view_menu', 'manage_customers',
                'view_expenses', 'create_expenses', // Added expense permissions
            ],
            'waiter' => [
                'access_pos', 'process_payments', 'manage_tables', 'view_orders', 'modify_orders',
                'view_menu', 'manage_customers', 'view_own_sales', 'view_waiter_reports',
            ],
            'kitchen' => [
                'access_kitchen', 'update_order_status', 'view_kitchen_tickets',
                'view_menu', 'view_inventory',
            ],
            'inventory_manager' => [
                'view_inventory', 'manage_inventory', 'receive_stock', 'adjust_stock',
                'view_reports', 'export_reports', 'view_menu', 'manage_menu',
            ],
            'accountant' => [
                'view_orders', 'view_reports', 'view_financial_reports', 'export_reports',
                'view_inventory', 'view_menu',
                'view_expenses', 'manage_expenses', 'manage_expense_categories', // Added expense permissions
            ],
            default => [],
        };
    }
}