<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\User;
use App\Models\PosSetting;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\Rule;
use App\Http\Controllers\Api\Helpers\RestaurantBranchFilterTrait;

class PosSettingsController extends Controller
{
    use RestaurantBranchFilterTrait;
    
    public function staff(Request $request)
    {
        $user = $request->user();
        $query = User::whereIn('role', ['pos_staff', 'branch_manager', 'branch_cashier']);

        // Apply restaurant and branch filtering (this handles all roles including branch managers)
        $this->applyRestaurantBranchFilter($query, $user, $request);
        
        // Backward compatibility: Also filter by warehouse_id (map to branch_id)
        $warehouseId = $request->input('warehouse_id');
        if ($warehouseId && !$request->has('branch_id')) {
            // Map warehouse_id to branch_id for backward compatibility
            $query->where('branch_id', $warehouseId);
        }

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

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

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

    public function createStaff(Request $request)
    {
        $user = $request->user();
        
        // Allow admin, restaurant_owner, and branch_manager to create staff
        if (!$user || !in_array($user->role, ['admin', 'restaurant_owner', 'branch_manager'])) {
            return response()->json(['message' => 'Unauthorized. Only admins, restaurant owners, and branch managers can create staff.'], 403);
        }
        
        $validated = $request->validate([
            'name' => 'required|string|max:255',
            'email' => 'required|email|unique:users,email',
            'password' => 'required|string|min:8',
            'role' => ['required', 'string', Rule::in(['pos_staff', 'branch_manager', 'branch_cashier'])],
            'sub_role' => ['nullable', 'string', Rule::in(['order_taker', 'waiter', 'cleaning_staff', 'floor_manager', 'senior_cook', 'junior_cook'])],
            'branch_id' => 'nullable|exists:branches,id',
        ]);
        
        // Validate sub_role is required when role is pos_staff
        if ($validated['role'] === 'pos_staff' && empty($validated['sub_role'])) {
            return response()->json(['message' => 'Sub role is required when role is pos_staff'], 422);
        }
        
        // Get restaurant and branch context
        $context = $this->getRestaurantBranchContext($user, $request);
        
        // Ensure branch_id is set for admin and restaurant owner
        if ($user->isAdmin() || $user->isRestaurantOwner()) {
        if (!isset($validated['branch_id']) || !$validated['branch_id']) {
                $validated['branch_id'] = $context['branch_id'] ?? null;
                if (!$validated['branch_id']) {
                    return response()->json(['message' => 'Branch is required. Please select a branch.'], 422);
                }
            }
        }
        
        // For branch manager, use their branch_id
        if ($user->isBranchManager() && !isset($validated['branch_id'])) {
            $validated['branch_id'] = $user->branch_id;
        }
        
        // Set restaurant_id if available
        if ($context['restaurant_id']) {
            $validated['restaurant_id'] = $context['restaurant_id'];
        }

        // Remove warehouse_id if present (column was removed from users table)
        unset($validated['warehouse_id']);

        DB::beginTransaction();
        try {
        $newUser = User::create([
            'name' => $validated['name'],
            'email' => $validated['email'],
            'password' => Hash::make($validated['password']),
            'role' => $validated['role'],
            'sub_role' => $validated['sub_role'] ?? null,
            'branch_id' => $validated['branch_id'],
            'restaurant_id' => $validated['restaurant_id'] ?? null,
        ]);

            // Create employee record
            $existingEmployee = \App\Models\Employee::where('user_id', $newUser->id)
                ->orWhere('email', $newUser->email)
                ->first();

            if (!$existingEmployee) {
                // Get restaurant_id from branch if not set
                $restaurantId = $validated['restaurant_id'] ?? null;
                if (!$restaurantId && $validated['branch_id']) {
                    $branch = \App\Models\Branch::find($validated['branch_id']);
                    if ($branch) {
                        $restaurantId = $branch->restaurant_id;
                    }
                }

                \App\Models\Employee::create([
                    'name' => $newUser->name,
                    'email' => $newUser->email,
                    'phone' => null,
                    'role' => $newUser->role,
                    'sub_role' => $newUser->sub_role ?? null,
                    'restaurant_id' => $restaurantId,
                    'branch_id' => $newUser->branch_id,
                    'is_active' => $newUser->is_active ?? true,
                    'enable_login' => true, // They have user account
                    'user_id' => $newUser->id,
                    'salary_type' => 'monthly',
                    'current_salary_amount' => 0,
                ]);
            }

            DB::commit();

        return response()->json([
            'id' => $newUser->id,
            'name' => $newUser->name,
            'email' => $newUser->email,
            'role' => $newUser->role,
            'sub_role' => $newUser->sub_role,
            'branch_id' => $newUser->branch_id,
            'restaurant_id' => $newUser->restaurant_id,
        ], 201);
        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json(['message' => 'Failed to create staff: ' . $e->getMessage()], 500);
        }
    }

    public function updateStaff(Request $request, User $user)
    {
        $currentUser = $request->user();
        
        // Allow admin, restaurant_owner, and branch_manager to update staff
        if (!$currentUser || !in_array($currentUser->role, ['admin', 'restaurant_owner', 'branch_manager'])) {
            return response()->json(['message' => 'Unauthorized. Only admins, restaurant owners, and branch managers can update staff.'], 403);
        }
        
        // Check access: branch manager can only update their branch's staff
        if ($currentUser->isBranchManager() && $user->branch_id !== $currentUser->branch_id) {
            return response()->json(['message' => 'Unauthorized. You can only update staff in your branch.'], 403);
        }
        
        // Check access: restaurant owner can only update their restaurant's staff
        if ($currentUser->isRestaurantOwner() && $user->restaurant_id !== $currentUser->restaurant_id) {
            return response()->json(['message' => 'Unauthorized. You can only update staff in your restaurant.'], 403);
        }
        
        $validated = $request->validate([
            'name' => 'sometimes|required|string|max:255',
            'email' => ['sometimes', 'required', 'email', Rule::unique('users')->ignore($user->id)],
            'password' => 'nullable|string|min:8',
            'role' => ['sometimes', 'required', 'string', Rule::in(['pos_staff', 'branch_manager', 'branch_cashier'])],
            'sub_role' => ['nullable', 'string', Rule::in(['order_taker', 'waiter', 'cleaning_staff', 'floor_manager', 'senior_cook', 'junior_cook'])],
            'branch_id' => 'sometimes|nullable|exists:branches,id',
        ]);
        
        // Validate sub_role is required when role is pos_staff
        if (isset($validated['role']) && $validated['role'] === 'pos_staff' && empty($validated['sub_role'])) {
            // If updating role to pos_staff, sub_role is required
            if ($user->role !== 'pos_staff' || !$user->sub_role) {
                return response()->json(['message' => 'Sub role is required when role is pos_staff'], 422);
            }
        }
        
        // Get restaurant and branch context
        $context = $this->getRestaurantBranchContext($currentUser, $request);
        
        // If branch_id not provided in update, keep existing
        if (!isset($validated['branch_id'])) {
            $validated['branch_id'] = $user->branch_id;
        }
        
        // Set restaurant_id if available
        if ($context['restaurant_id']) {
            $validated['restaurant_id'] = $context['restaurant_id'];
        }

        if (isset($validated['password'])) {
            $validated['password'] = Hash::make($validated['password']);
        } else {
            unset($validated['password']);
        }

        // Remove warehouse_id if present (column was removed from users table)
        unset($validated['warehouse_id']);

        $user->update($validated);

        return response()->json([
            'id' => $user->id,
            'name' => $user->name,
            'email' => $user->email,
            'role' => $user->role,
            'sub_role' => $user->sub_role,
            'branch_id' => $user->branch_id,
            'restaurant_id' => $user->restaurant_id,
        ]);
    }

    public function deleteStaff(User $user)
    {
        $currentUser = request()->user();
        
        // Allow admin, restaurant_owner, and branch_manager to delete staff
        if (!$currentUser || !in_array($currentUser->role, ['admin', 'restaurant_owner', 'branch_manager'])) {
            return response()->json(['message' => 'Unauthorized. Only admins, restaurant owners, and branch managers can delete staff.'], 403);
        }
        
        // Check access: branch manager can only delete their branch's staff
        if ($currentUser->isBranchManager() && $user->branch_id !== $currentUser->branch_id) {
            return response()->json(['message' => 'Unauthorized. You can only delete staff in your branch.'], 403);
        }
        
        // Check access: restaurant owner can only delete their restaurant's staff
        if ($currentUser->isRestaurantOwner() && $user->restaurant_id !== $currentUser->restaurant_id) {
            return response()->json(['message' => 'Unauthorized. You can only delete staff in your restaurant.'], 403);
        }
        
        $user->delete();
        return response()->json(['message' => 'Staff deleted successfully']);
    }

    /**
     * Get all POS settings with restaurant/branch filtering
     */
    public function index(Request $request)
    {
        $user = $request->user();
        
        // Allow admin, restaurant_owner, and branch_manager
        if (!$user || !in_array($user->role, ['admin', 'restaurant_owner', 'branch_manager'])) {
            return response()->json(['message' => 'Unauthorized'], 403);
        }

        $query = PosSetting::with(['restaurant', 'branch']);

        // Apply restaurant and branch filtering
        $context = $this->getRestaurantBranchContext($user, $request);
        
        if ($user->isAdmin()) {
            // Admin can filter by restaurant_id and branch_id
            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()) {
            // Restaurant owner can only see their restaurant's settings
            $query->where('restaurant_id', $user->restaurant_id);
            if ($request->has('branch_id') && $request->branch_id) {
                // Verify branch belongs to restaurant
                $branch = \App\Models\Branch::where('id', $request->branch_id)
                    ->where('restaurant_id', $user->restaurant_id)
                    ->first();
                if ($branch) {
                    $query->where('branch_id', $request->branch_id);
                }
            }
        } elseif ($user->isBranchManager()) {
            // Branch manager can only see their branch's settings
            $query->where('branch_id', $user->branch_id);
        }

        $settings = $query->orderBy('key')->get();

        // Transform to include typed values
        $settings = $settings->map(function ($setting) {
            return [
                'id' => $setting->id,
                'restaurant_id' => $setting->restaurant_id,
                'branch_id' => $setting->branch_id,
                'key' => $setting->key,
                'value' => $setting->getValue(),
                'type' => $setting->type,
                'description' => $setting->description,
                'created_at' => $setting->created_at,
                'updated_at' => $setting->updated_at,
            ];
        });

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

    /**
     * Get settings for current context (restaurant/branch)
     */
    public function getByContext(Request $request)
    {
        $user = $request->user();
        
        // Allow admin, restaurant_owner, and branch_manager
        if (!$user || !in_array($user->role, ['admin', 'restaurant_owner', 'branch_manager'])) {
            return response()->json(['message' => 'Unauthorized'], 403);
        }

        $context = $this->getRestaurantBranchContext($user, $request);
        $restaurantId = $context['restaurant_id'] ?? null;
        $branchId = $context['branch_id'] ?? null;

        // Get all settings for this context
        $settings = PosSetting::where(function ($query) use ($restaurantId, $branchId) {
            if ($branchId) {
                $query->where(function ($q) use ($branchId) {
                    $q->where('branch_id', $branchId);
                });
            }
            if ($restaurantId) {
                $query->orWhere(function ($q) use ($restaurantId) {
                    $q->where('restaurant_id', $restaurantId)
                      ->whereNull('branch_id');
                });
            }
        })->get();

        // Transform to key-value pairs with typed values
        $result = [];
        foreach ($settings as $setting) {
            $result[$setting->key] = $setting->getValue();
        }

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

    /**
     * Get a single POS setting
     */
    public function show(Request $request, $id)
    {
        $user = $request->user();
        
        // Allow admin, restaurant_owner, and branch_manager
        if (!$user || !in_array($user->role, ['admin', 'restaurant_owner', 'branch_manager'])) {
            return response()->json(['message' => 'Unauthorized'], 403);
        }

        $setting = PosSetting::with(['restaurant', 'branch'])->findOrFail($id);

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

        return response()->json([
            'id' => $setting->id,
            'restaurant_id' => $setting->restaurant_id,
            'branch_id' => $setting->branch_id,
            'key' => $setting->key,
            'value' => $setting->getValue(),
            'type' => $setting->type,
            'description' => $setting->description,
            'created_at' => $setting->created_at,
            'updated_at' => $setting->updated_at,
        ]);
    }

    /**
     * Create a new POS setting
     */
    public function store(Request $request)
    {
        $user = $request->user();
        
        // Allow admin, restaurant_owner, and branch_manager
        if (!$user || !in_array($user->role, ['admin', 'restaurant_owner', 'branch_manager'])) {
            return response()->json(['message' => 'Unauthorized'], 403);
        }

        $validated = $request->validate([
            'key' => 'required|string|max:255',
            'value' => 'nullable',
            'type' => 'required|in:string,boolean,number,json',
            'description' => 'nullable|string',
            'restaurant_id' => 'nullable|exists:restaurants,id',
            'branch_id' => 'nullable|exists:branches,id',
        ]);

        // Validate timezone format if key is 'timezone'
        if ($validated['key'] === 'timezone' && isset($validated['value'])) {
            $timezone = $validated['value'];
            // Validate timezone format (accept timezone strings like 'Asia/Karachi' or offsets like '+05:00', '-05:00')
            if (!preg_match('/^[+-]\d{2}:\d{2}$/', $timezone) && !in_array($timezone, timezone_identifiers_list())) {
                return response()->json([
                    'message' => 'Invalid timezone format. Use timezone string (e.g., Asia/Karachi) or offset (e.g., +05:00)'
                ], 422);
            }
        }

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

        // Set restaurant_id and branch_id based on user role
        if ($user->isAdmin()) {
            $restaurantId = $validated['restaurant_id'] ?? $context['restaurant_id'] ?? null;
            $branchId = $validated['branch_id'] ?? $context['branch_id'] ?? null;
        } elseif ($user->isRestaurantOwner()) {
            $restaurantId = $user->restaurant_id;
            $branchId = $validated['branch_id'] ?? $context['branch_id'] ?? null;
            
            // Verify branch belongs to restaurant if provided
            if ($branchId) {
                $branch = \App\Models\Branch::where('id', $branchId)
                    ->where('restaurant_id', $restaurantId)
                    ->first();
                if (!$branch) {
                    return response()->json(['message' => 'Branch does not belong to your restaurant'], 422);
                }
            }
        } elseif ($user->isBranchManager()) {
            $restaurantId = $user->branch->restaurant_id ?? null;
            $branchId = $user->branch_id;
        }

        // Check if setting already exists
        $existing = PosSetting::where('key', $validated['key'])
            ->where('restaurant_id', $restaurantId)
            ->where('branch_id', $branchId)
            ->first();

        if ($existing) {
            return response()->json(['message' => 'Setting already exists for this restaurant/branch'], 422);
        }

        $setting = PosSetting::create([
            'restaurant_id' => $restaurantId,
            'branch_id' => $branchId,
            'key' => $validated['key'],
            'type' => $validated['type'],
            'description' => $validated['description'] ?? null,
        ]);

        $setting->setValue($validated['value'] ?? null);
        $setting->save();

        return response()->json([
            'id' => $setting->id,
            'restaurant_id' => $setting->restaurant_id,
            'branch_id' => $setting->branch_id,
            'key' => $setting->key,
            'value' => $setting->getValue(),
            'type' => $setting->type,
            'description' => $setting->description,
            'created_at' => $setting->created_at,
            'updated_at' => $setting->updated_at,
        ], 201);
    }

    /**
     * Update a POS setting
     */
    public function update(Request $request, $id)
    {
        $user = $request->user();
        
        // Allow admin, restaurant_owner, and branch_manager
        if (!$user || !in_array($user->role, ['admin', 'restaurant_owner', 'branch_manager'])) {
            return response()->json(['message' => 'Unauthorized'], 403);
        }

        $setting = PosSetting::findOrFail($id);

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

        $validated = $request->validate([
            'value' => 'nullable',
            'type' => 'sometimes|in:string,boolean,number,json',
            'description' => 'nullable|string',
        ]);

        // Validate timezone format if key is 'timezone' and value is being updated
        if ($setting->key === 'timezone' && isset($validated['value'])) {
            $timezone = $validated['value'];
            // Validate timezone format (accept timezone strings like 'Asia/Karachi' or offsets like '+05:00', '-05:00')
            if (!preg_match('/^[+-]\d{2}:\d{2}$/', $timezone) && !in_array($timezone, timezone_identifiers_list())) {
                return response()->json([
                    'message' => 'Invalid timezone format. Use timezone string (e.g., Asia/Karachi) or offset (e.g., +05:00)'
                ], 422);
            }
        }

        if (isset($validated['type'])) {
            $setting->type = $validated['type'];
        }
        if (isset($validated['description'])) {
            $setting->description = $validated['description'];
        }

        if (isset($validated['value'])) {
            $setting->setValue($validated['value']);
        }

        $setting->save();

        return response()->json([
            'id' => $setting->id,
            'restaurant_id' => $setting->restaurant_id,
            'branch_id' => $setting->branch_id,
            'key' => $setting->key,
            'value' => $setting->getValue(),
            'type' => $setting->type,
            'description' => $setting->description,
            'created_at' => $setting->created_at,
            'updated_at' => $setting->updated_at,
        ]);
    }

    /**
     * Delete a POS setting
     */
    public function destroy(Request $request, $id)
    {
        $user = $request->user();
        
        // Allow admin, restaurant_owner, and branch_manager
        if (!$user || !in_array($user->role, ['admin', 'restaurant_owner', 'branch_manager'])) {
            return response()->json(['message' => 'Unauthorized'], 403);
        }

        $setting = PosSetting::findOrFail($id);

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

        $setting->delete();

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

