<?php

namespace App\Livewire\Users;

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

class Edit extends Component
{
    public User $user;

    // 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 $changePassword = false;
    public $showDeleteModal = false;
    
    // UI State
    public $currentTab = 'profile';
    public $saving = false;
    public $showPasswordGenerator = false;
    public $generatedPassword = '';
    public $originalData = [];

    protected function rules()
    {
        $rules = [
            'name' => 'required|string|max:255|min:2',
            'email' => 'required|email|unique:users,email,' . $this->user->id . '|max:255',
            'employee_id' => 'nullable|string|max:50|unique:users,employee_id,' . $this->user->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,' . $this->user->id,
            'selectedRoles' => 'array',
            'selectedRoles.*' => 'exists:roles,id',
            'selectedPermissions' => 'array',
            'selectedPermissions.*' => 'exists:permissions,id',
        ];

        if ($this->changePassword) {
            $rules['password'] = ['required', 'confirmed', Password::min(8)->letters()->mixedCase()->numbers()->symbols()];
        }

        return $rules;
    }

    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.',
        'salary.max' => 'Salary cannot exceed 999,999.99.',
    ];

    public function mount(User $user)
    {
        $this->user = $user;
        
        // Store original data for change tracking
        $this->originalData = [
            'name' => $user->name,
            'email' => $user->email,
            'employee_id' => $user->employee_id,
            'phone' => $user->phone,
            'department' => $user->department,
            'position' => $user->position,
            'branch_code' => $user->branch_code,
            'status' => $user->status,
        ];
        
        // Load user data
        $this->name = $user->name;
        $this->email = $user->email;
        $this->employee_id = $user->employee_id;
        $this->phone = $user->phone;
        $this->department = $user->department;
        $this->position = $user->position;
        $this->branch_code = $user->branch_code;
        $this->hire_date = $user->hire_date ? $user->hire_date->format('Y-m-d') : '';
        $this->salary = $user->salary;
        $this->status = $user->status;
        $this->emergency_contact_name = $user->emergency_contact_name;
        $this->emergency_contact_phone = $user->emergency_contact_phone;
        $this->address = $user->address;
        $this->date_of_birth = $user->date_of_birth ? $user->date_of_birth->format('Y-m-d') : '';
        $this->national_id = $user->national_id;

        // Load current roles
        $this->selectedRoles = $user->roles()
            ->where('user_roles.is_active', true)
            ->where(function ($q) {
                $q->whereNull('user_roles.expires_at')
                  ->orWhere('user_roles.expires_at', '>', now());
            })
            ->pluck('roles.id')
            ->toArray();

        // Load current direct permissions
        $this->selectedPermissions = $user->permissions()
            ->where('user_permissions.granted', true)
            ->where(function ($q) {
                $q->whereNull('user_permissions.expires_at')
                  ->orWhere('user_permissions.expires_at', '>', now());
            })
            ->pluck('permissions.id')
            ->toArray();
    }

    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 = \DB::table('branches')
                       ->where('is_active', true)
                       ->orderBy('name')
                       ->get(['code', 'name']);

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

        // Get user activity logs
        $causedByUser = \Spatie\Activitylog\Models\Activity::where('causer_id', $this->user->id)
            ->where('causer_type', \App\Models\User::class)
            ->latest()
            ->limit(5)
            ->get();
            
        $performedOnUser = \Spatie\Activitylog\Models\Activity::where('subject_id', $this->user->id)
            ->where('subject_type', \App\Models\User::class)
            ->latest()
            ->limit(5)
            ->get();
            
        $recentActivity = $causedByUser->merge($performedOnUser)
            ->sortByDesc('created_at')
            ->take(10);

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

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

        DB::beginTransaction();
        try {
            // Prepare update data
            $userData = [
                'name' => trim($this->name),
                'email' => strtolower(trim($this->email)),
                '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,
                'updated_by' => auth()->id(),
            ];

            // Update password if requested
            if ($this->changePassword && $this->password) {
                $userData['password'] = Hash::make($this->password);
                $userData['password_changed_at'] = now();
            }

            // Track changes for activity log
            $changes = $this->getChangedData($userData);

            $this->user->update($userData);

            // Sync roles with branch code
            $roleData = [];
            foreach ($this->selectedRoles as $roleId) {
                $roleData[$roleId] = [
                    'branch_code' => $this->branch_code,
                    'is_active' => true,
                    'assigned_at' => now(),
                    'expires_at' => null,
                ];
            }
            $this->user->roles()->sync($roleData);

            // Sync direct permissions
            $permissionData = [];
            foreach ($this->selectedPermissions as $permissionId) {
                $permissionData[$permissionId] = [
                    'granted' => true,
                    'branch_code' => $this->branch_code,
                    'assigned_at' => now(),
                    'expires_at' => null,
                ];
            }
            $this->user->permissions()->sync($permissionData);

            // Log the update with changes
            if (!empty($changes) || $this->changePassword) {
                $logProperties = ['changes' => $changes];
                if ($this->changePassword) {
                    $logProperties['password_changed'] = true;
                }

                activity()
                    ->performedOn($this->user)
                    ->causedBy(auth()->user())
                    ->withProperties($logProperties)
                    ->log('User updated');
            }

            DB::commit();

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

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

    public function cancel()
    {
        return redirect()->route('users.show', $this->user);
    }

    public function generatePassword()
    {
        $this->generatedPassword = $this->generateSecurePassword();
        $this->password = $this->generatedPassword;
        $this->password_confirmation = $this->generatedPassword;
        $this->changePassword = true;
        $this->showPasswordGenerator = true;
    }

    public function generateSecurePassword($length = 12)
    {
        // Generate a secure password with mixed case, numbers, and symbols
        $uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
        $lowercase = 'abcdefghijklmnopqrstuvwxyz';
        $numbers = '0123456789';
        $symbols = '!@#$%^&*()_+-=[]{}|;:,.<>?';
        
        $password = '';
        $password .= $uppercase[random_int(0, strlen($uppercase) - 1)];
        $password .= $lowercase[random_int(0, strlen($lowercase) - 1)];
        $password .= $numbers[random_int(0, strlen($numbers) - 1)];
        $password .= $symbols[random_int(0, strlen($symbols) - 1)];
        
        $allChars = $uppercase . $lowercase . $numbers . $symbols;
        for ($i = 4; $i < $length; $i++) {
            $password .= $allChars[random_int(0, strlen($allChars) - 1)];
        }
        
        return str_shuffle($password);
    }

    public function resetPassword()
    {
        
        try {
            $newPassword = \Str::random(12);
            $this->user->update([
                'password' => Hash::make($newPassword)
            ]);

            // TODO: Send password reset email
            // $this->user->notify(new PasswordResetNotification($newPassword));

            session()->flash('success', 'Password reset successfully. New password: ' . $newPassword);
        } catch (\Exception $e) {
            session()->flash('error', 'Failed to reset password: ' . $e->getMessage());
        }
    }

    public function impersonateUser()
    {
        
        if ($this->user->id === auth()->id()) {
            session()->flash('error', 'You cannot impersonate yourself.');
            return;
        }

        // Store original user ID for returning later
        session(['impersonate_original_user' => auth()->id()]);
        auth()->loginUsingId($this->user->id);

        session()->flash('success', 'Now impersonating ' . $this->user->name);
        return redirect()->route('dashboard');
    }

    public function getAvailableRolesProperty()
    {
        return Role::orderBy('name')->get();
    }

    public function confirmDelete()
    {
        $this->showDeleteModal = true;
    }

    public function deleteUser()
    {
        
        // Prevent self-deletion
        if ($this->user->id === auth()->id()) {
            session()->flash('error', 'You cannot delete your own account.');
            return;
        }
        
        try {
            $this->user->delete();
            session()->flash('success', 'User deleted successfully.');
            return redirect()->route('users.index');
        } catch (\Exception $e) {
            session()->flash('error', 'Failed to delete user: ' . $e->getMessage());
        }
        
        $this->showDeleteModal = false;
    }

    public function setActiveTab($tab)
    {
        $this->currentTab = $tab;
    }

    public function getChangedData($newData)
    {
        $changes = [];
        foreach ($newData as $key => $value) {
            if (isset($this->originalData[$key]) && $this->originalData[$key] != $value) {
                $changes[$key] = [
                    'old' => $this->originalData[$key],
                    'new' => $value
                ];
            }
        }
        return $changes;
    }

    public function getPositionsForDepartment($department)
    {
        $positions = [
            'Service' => ['Service Advisor', 'Service Manager', 'Service Coordinator', 'Service Writer'],
            'Technician' => ['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'],
        ];

        return $positions[$department] ?? [];
    }

    public function updatedDepartment()
    {
        // Clear position when department changes unless it's valid for new department
        $validPositions = $this->getPositionsForDepartment($this->department);
        if (!in_array($this->position, $validPositions)) {
            $this->position = '';
        }
    }

    public function hasUnsavedChanges()
    {
        $currentData = [
            'name' => $this->name,
            'email' => $this->email,
            'employee_id' => $this->employee_id,
            'phone' => $this->phone,
            'department' => $this->department,
            'position' => $this->position,
            'branch_code' => $this->branch_code,
            'status' => $this->status,
        ];

        return !empty($this->getChangedData($currentData)) || $this->changePassword;
    }

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

    public function togglePasswordVisibility()
    {
        $this->showPasswordGenerator = !$this->showPasswordGenerator;
    }
}
