<?php

namespace App\Livewire\Users;

use Livewire\Component;
use App\Models\User;
use App\Models\Role;
use App\Models\Permission;
use App\Models\Branch;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Mail;
use Illuminate\Validation\Rules\Password;
use Illuminate\Support\Str;

class Create extends Component
{
    // User basic information
    public $name = '';
    public $email = '';
    public $password = '';
    public $password_confirmation = '';
    public $employee_id = '';
    public $phone = '';
    public $department = '';
    public $position = '';
    public $branch_code = '';
    public $hire_date = '';
    public $salary = '';
    public $status = 'active';
    public $emergency_contact_name = '';
    public $emergency_contact_phone = '';
    public $address = '';
    public $date_of_birth = '';
    public $national_id = '';

    // Role and permission management
    public $selectedRoles = [];
    public $selectedPermissions = [];
    public $sendWelcomeEmail = true;
    public $sendCredentials = false;
    
    // UI State
    public $showPasswordGenerator = false;
    public $generatedPassword = '';
    public $currentStep = 1;
    public $totalSteps = 4;
    public $saving = false;
    
    // Advanced options
    public $requirePasswordChange = true;
    public $temporaryPassword = false;
    public $accountExpiry = '';
    public $notes = '';

    protected function rules()
    {
        return [
            'name' => 'required|string|max:255|min:2',
            'email' => 'required|email|unique:users,email|max:255',
            'password' => ['required', 'confirmed', Password::min(8)->letters()->mixedCase()->numbers()->symbols()],
            'employee_id' => 'nullable|string|max:50|unique:users,employee_id|regex:/^[A-Z0-9-]+$/',
            'phone' => 'nullable|string|max:20|regex:/^[\+]?[0-9\s\-\(\)]+$/',
            'department' => 'nullable|string|max:100',
            'position' => 'nullable|string|max:100',
            'branch_code' => 'required|string|max:10|exists:branches,code',
            'hire_date' => 'nullable|date|before_or_equal:today',
            'salary' => 'nullable|numeric|min:0|max:999999.99',
            'status' => 'required|in:active,inactive,suspended',
            'emergency_contact_name' => 'nullable|string|max:255',
            'emergency_contact_phone' => 'nullable|string|max:20|regex:/^[\+]?[0-9\s\-\(\)]+$/',
            'address' => 'nullable|string|max:500',
            'date_of_birth' => 'nullable|date|before:-18 years',
            'national_id' => 'nullable|string|max:50|unique:users,national_id',
            'selectedRoles' => 'array|min:1',
            'selectedRoles.*' => 'exists:roles,id',
            'selectedPermissions' => 'array',
            'selectedPermissions.*' => 'exists:permissions,id',
            'accountExpiry' => 'nullable|date|after:today',
            'notes' => 'nullable|string|max:1000',
        ];
    }

    protected $messages = [
        'name.min' => 'Name must be at least 2 characters long.',
        'branch_code.required' => 'Branch code is required.',
        'branch_code.exists' => 'Selected branch code does not exist.',
        'email.unique' => 'This email address is already registered.',
        'employee_id.unique' => 'This employee ID is already in use.',
        'employee_id.regex' => 'Employee ID can only contain letters, numbers, and hyphens.',
        'phone.regex' => 'Please enter a valid phone number.',
        'emergency_contact_phone.regex' => 'Please enter a valid emergency contact phone number.',
        'date_of_birth.before' => 'Employee must be at least 18 years old.',
        'hire_date.before_or_equal' => 'Hire date cannot be in the future.',
        'national_id.unique' => 'This national ID is already registered.',
        'selectedRoles.min' => 'Please assign at least one role to the user.',
        'salary.max' => 'Salary cannot exceed 999,999.99.',
        'accountExpiry.after' => 'Account expiry must be in the future.',
        'notes.max' => 'Notes cannot exceed 1000 characters.',
    ];

    public function mount()
    {
        $this->hire_date = now()->format('Y-m-d');
        $this->branch_code = auth()->user()->branch_code ?? '';
        
        // Auto-generate employee ID if needed
        $this->generateEmployeeId();
    }

    public function render()
    {
        $roles = Role::where('is_active', true)
                    ->orderBy('display_name')
                    ->get();
        
        $permissions = Permission::where('is_active', true)
                                ->orderBy('module')
                                ->orderBy('name')
                                ->get()
                                ->groupBy('module');
        
        $departments = User::select('department')
                          ->distinct()
                          ->whereNotNull('department')
                          ->where('department', '!=', '')
                          ->orderBy('department')
                          ->pluck('department');
        
        $branches = Branch::where('is_active', true)
                          ->orderBy('name')
                          ->get(['code', 'name']);

        $positions = $this->getPositionsForDepartment($this->department);

        return view('livewire.users.create', [
            'roles' => $roles,
            'permissions' => $permissions,
            'departments' => $departments,
            'branches' => $branches,
            'positions' => $positions,
        ]);
    }

    public function generateEmployeeId()
    {
        if (empty($this->employee_id) && !empty($this->branch_code)) {
            $lastEmployee = User::where('branch_code', $this->branch_code)
                                ->where('employee_id', 'like', $this->branch_code . '%')
                                ->orderByDesc('employee_id')
                                ->first();
            
            if ($lastEmployee) {
                $number = (int) substr($lastEmployee->employee_id, strlen($this->branch_code)) + 1;
            } else {
                $number = 1;
            }
            
            $this->employee_id = $this->branch_code . str_pad($number, 4, '0', STR_PAD_LEFT);
        }
    }

    public function updatedBranchCode()
    {
        $this->generateEmployeeId();
    }

    public function generatePassword()
    {
        $this->generatedPassword = Str::random(12);
        $this->password = $this->generatedPassword;
        $this->password_confirmation = $this->generatedPassword;
        $this->showPasswordGenerator = false;
        $this->temporaryPassword = true;
        $this->requirePasswordChange = true;
    }

    public function applyRolePreset($preset)
    {
        $this->selectedRoles = [];
        $this->selectedPermissions = [];
        
        switch ($preset) {
            case 'manager':
                $roles = Role::whereIn('name', ['manager', 'service_supervisor'])->get();
                break;
            case 'technician':
                $roles = Role::whereIn('name', ['technician'])->get();
                break;
            case 'receptionist':
                $roles = Role::whereIn('name', ['receptionist', 'customer_service'])->get();
                break;
            case 'service_coordinator':
                $roles = Role::whereIn('name', ['service_coordinator'])->get();
                break;
            default:
                $roles = collect();
        }
        
        $this->selectedRoles = $roles->pluck('id')->toArray();
    }

    public function nextStep()
    {
        $this->validateCurrentStep();
        if ($this->currentStep < $this->totalSteps) {
            $this->currentStep++;
        }
    }

    public function previousStep()
    {
        if ($this->currentStep > 1) {
            $this->currentStep--;
        }
    }

    public function validateCurrentStep()
    {
        $rules = $this->rules();
        
        switch ($this->currentStep) {
            case 1: // Basic Information
                $stepRules = [
                    'name' => $rules['name'],
                    'email' => $rules['email'],
                    'employee_id' => $rules['employee_id'],
                    'branch_code' => $rules['branch_code'],
                ];
                break;
            case 2: // Employment Details
                $stepRules = [
                    'department' => $rules['department'],
                    'position' => $rules['position'],
                    'hire_date' => $rules['hire_date'],
                    'salary' => $rules['salary'],
                ];
                break;
            case 3: // Security & Access
                $stepRules = [
                    'password' => $rules['password'],
                    'selectedRoles' => $rules['selectedRoles'],
                    'selectedRoles.*' => $rules['selectedRoles.*'],
                ];
                break;
            case 4: // Additional Information
                $stepRules = [
                    'phone' => $rules['phone'],
                    'address' => $rules['address'],
                    'emergency_contact_name' => $rules['emergency_contact_name'],
                    'emergency_contact_phone' => $rules['emergency_contact_phone'],
                ];
                break;
            default:
                $stepRules = [];
        }
        
        $this->validate($stepRules);
    }

    public function getPositionsForDepartment($department)
    {
        if (empty($department)) return [];
        
        // Get positions from existing users in the same department
        $existingPositions = User::select('position')
                                ->where('department', $department)
                                ->distinct()
                                ->whereNotNull('position')
                                ->where('position', '!=', '')
                                ->orderBy('position')
                                ->pluck('position')
                                ->toArray();
        
        // Common positions by department
        $commonPositions = [
            'Service' => ['Service Advisor', 'Service Manager', 'Service Coordinator', 'Service Writer'],
            'Technical' => ['Lead Technician', 'Senior Technician', 'Junior Technician', 'Apprentice Technician'],
            'Parts' => ['Parts Manager', 'Parts Associate', 'Inventory Specialist', 'Parts Counter Person'],
            'Administration' => ['Administrator', 'Office Manager', 'Receptionist', 'Data Entry Clerk'],
            'Management' => ['General Manager', 'Assistant Manager', 'Supervisor', 'Team Lead'],
            'Sales' => ['Sales Manager', 'Sales Associate', 'Sales Coordinator'],
            'Finance' => ['Finance Manager', 'Accountant', 'Cashier', 'Billing Specialist'],
        ];
        
        $predefinedPositions = $commonPositions[$department] ?? [];
        
        // Merge and deduplicate
        $allPositions = array_unique(array_merge($existingPositions, $predefinedPositions));
        sort($allPositions);
        
        return $allPositions;
    }

    public function save()
    {
        $this->saving = true;
        $this->validate();

        DB::beginTransaction();
        try {
            // Create the user
            $user = User::create([
                'name' => trim($this->name),
                'email' => strtolower(trim($this->email)),
                'password' => Hash::make($this->password),
                'employee_id' => $this->employee_id ? strtoupper(trim($this->employee_id)) : null,
                'phone' => $this->phone ? preg_replace('/[^0-9+\-\s\(\)]/', '', $this->phone) : null,
                'department' => $this->department ?: null,
                'position' => $this->position ?: null,
                'branch_code' => $this->branch_code,
                'hire_date' => $this->hire_date ?: null,
                'salary' => $this->salary ?: null,
                'status' => $this->status,
                'emergency_contact_name' => trim($this->emergency_contact_name) ?: null,
                'emergency_contact_phone' => $this->emergency_contact_phone ? preg_replace('/[^0-9+\-\s\(\)]/', '', $this->emergency_contact_phone) : null,
                'address' => trim($this->address) ?: null,
                'date_of_birth' => $this->date_of_birth ?: null,
                'national_id' => $this->national_id ? trim($this->national_id) : null,
                'email_verified_at' => now(),
                'created_by' => auth()->id(),
            ]);

            // Assign roles
            if (!empty($this->selectedRoles)) {
                foreach ($this->selectedRoles as $roleId) {
                    $role = Role::find($roleId);
                    if ($role) {
                        $user->assignRole($role, $this->branch_code);
                    }
                }
            }

            // Assign direct permissions
            if (!empty($this->selectedPermissions)) {
                foreach ($this->selectedPermissions as $permissionId) {
                    $permission = Permission::find($permissionId);
                    if ($permission) {
                        $user->givePermission($permission, $this->branch_code);
                    }
                }
            }

            // Log the creation
            activity()
                ->performedOn($user)
                ->causedBy(auth()->user())
                ->withProperties([
                    'user_data' => [
                        'name' => $user->name,
                        'email' => $user->email,
                        'employee_id' => $user->employee_id,
                        'department' => $user->department,
                        'branch_code' => $user->branch_code,
                        'status' => $user->status,
                    ],
                    'roles_assigned' => $this->selectedRoles,
                    'permissions_assigned' => $this->selectedPermissions,
                ])
                ->log('User created');

            // Send welcome email if requested
            if ($this->sendWelcomeEmail) {
                try {
                    // TODO: Implement welcome email notification
                    // $user->notify(new WelcomeNotification($this->password));
                } catch (\Exception $e) {
                    // Log email failure but don't fail the user creation
                    \Log::warning('Failed to send welcome email to user: ' . $user->email, ['error' => $e->getMessage()]);
                }
            }

            DB::commit();

            session()->flash('success', "User '{$user->name}' created successfully!");
            $this->saving = false;
            
            return redirect()->route('users.show', $user);

        } catch (\Exception $e) {
            DB::rollBack();
            $this->saving = false;
            
            \Log::error('Failed to create user', [
                'error' => $e->getMessage(),
                'user_data' => [
                    'name' => $this->name,
                    'email' => $this->email,
                    'employee_id' => $this->employee_id,
                ]
            ]);
            
            session()->flash('error', 'Failed to create user: ' . $e->getMessage());
        }
    }

    public function cancel()
    {
        return redirect()->route('users.index');
    }

    public function updatedDepartment()
    {
        // Clear position when department changes
        $this->position = '';
    }

    public function validateStep1()
    {
        $this->validateOnly([
            'name',
            'email',
            'password',
            'password_confirmation',
            'employee_id',
            'phone',
        ]);
    }

    public function validateStep2()
    {
        $this->validateOnly([
            'department',
            'position',
            'branch_code',
            'hire_date',
            'salary',
            'status',
        ]);
    }

    public function copyPasswordToClipboard()
    {
        // This will be handled by Alpine.js on the frontend
        $this->dispatch('password-copied');
    }

    public function getRolePermissionCount($roleId)
    {
        $role = Role::find($roleId);
        return $role ? $role->permissions()->count() : 0;
    }

    public function getSelectedRolesPermissions()
    {
        if (empty($this->selectedRoles)) {
            return collect();
        }

        return Permission::whereHas('roles', function($query) {
            $query->whereIn('roles.id', $this->selectedRoles);
        })->get();
    }

    public function hasValidationErrors()
    {
        return $this->getErrorBag()->isNotEmpty();
    }

    public function getProgressPercentage()
    {
        return ($this->currentStep / $this->totalSteps) * 100;
    }
}
