<?php

namespace App\Livewire\HR;

use App\Domain\HR\Enums\EmploymentType;
use App\Domain\HR\Enums\SalaryFrequency;
use App\Domain\HR\Services\EmployeeService;
use App\Domain\Identity\Models\Branch;
use App\Domain\Identity\Models\Person;
use App\Domain\Identity\Models\Role;
use App\Domain\Identity\Services\PersonService;
use App\Domain\Shared\Exceptions\DomainException;
use App\Models\User;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Component;

#[Layout('layouts.app')]
#[Title('إضافة موظف جديد')]
class CreateEmployeeWizard extends Component
{
    public int $currentStep = 1;
    public int $totalSteps = 6;
    public bool $completed = false;

    // Step 1: Person
    public ?int $personId = null;
    public string $personSearch = '';
    public bool $createNewPerson = false;
    public string $personNameAr = '';
    public string $personName = '';
    public string $personPhone = '';
    public string $personNationalId = '';
    public string $personDateOfBirth = '';
    public string $personGender = '';

    // Step 2: Employment
    public string $department = '';
    public string $position = '';
    public string $employmentType = '';
    public string $startDate = '';
    public string $endDate = '';

    // Step 3: Branch & Manager
    public ?int $branchId = null;
    public ?int $managerId = null;

    // Step 4: Salary
    public string $salaryAmount = '';
    public string $salaryFrequency = '';
    public string $workingHoursPerWeek = '';

    // Step 5: User Account
    public bool $createUserAccount = true;
    public string $userEmail = '';
    public string $userPassword = '';
    public string $userPasswordConfirmation = '';
    public ?int $userRoleId = null;

    public function mount(): void
    {
        $this->authorize('employees.create');
        $this->startDate = now()->toDateString();
    }

    public function getStepLabels(): array
    {
        return [
            1 => 'بيانات الشخص',
            2 => 'بيانات التوظيف',
            3 => 'الفرع والمسؤول',
            4 => 'الراتب',
            5 => 'حساب المستخدم',
            6 => 'مراجعة',
        ];
    }

    public function getPersonResultsProperty(): \Illuminate\Support\Collection
    {
        if (strlen($this->personSearch) < 2) {
            return collect();
        }

        return Person::where(function ($q) {
            $q->where('name_ar', 'ilike', "%{$this->personSearch}%")
              ->orWhere('name', 'ilike', "%{$this->personSearch}%")
              ->orWhere('phone', 'like', "%{$this->personSearch}%")
              ->orWhere('national_id', 'like', "%{$this->personSearch}%");
        })->limit(10)->get(['id', 'name', 'name_ar', 'phone', 'national_id']);
    }

    public function selectPerson(int $id): void
    {
        $person = Person::findOrFail($id);
        $this->personId = $person->id;
        $this->personNameAr = $person->name_ar ?? '';
        $this->personName = $person->name ?? '';
        $this->personPhone = $person->phone ?? '';
        $this->personNationalId = $person->national_id ?? '';
        $this->personDateOfBirth = $person->date_of_birth?->toDateString() ?? '';
        $this->personGender = $person->gender ?? '';
        $this->createNewPerson = false;
        $this->personSearch = '';
    }

    public function toggleCreateNew(): void
    {
        $this->createNewPerson = !$this->createNewPerson;
        if ($this->createNewPerson) {
            $this->personId = null;
        }
    }

    public function rulesForStep(int $step): array
    {
        return match ($step) {
            1 => $this->createNewPerson ? [
                'personNameAr' => 'required|string|max:255',
                'personPhone' => 'required|string|max:20',
                'personGender' => 'required|in:male,female',
            ] : [
                'personId' => 'required|exists:people,id',
            ],
            2 => [
                'department' => 'required|string|max:100',
                'position' => 'required|string|max:100',
                'employmentType' => 'required|in:' . implode(',', array_column(EmploymentType::cases(), 'value')),
                'startDate' => 'required|date',
                'endDate' => 'nullable|date|after:startDate',
            ],
            3 => [
                'branchId' => 'required|exists:branches,id',
            ],
            4 => [
                'salaryAmount' => 'required|numeric|min:0',
                'salaryFrequency' => 'required|in:' . implode(',', array_column(SalaryFrequency::cases(), 'value')),
                'workingHoursPerWeek' => 'nullable|numeric|min:1|max:168',
            ],
            5 => $this->createUserAccount ? [
                'userEmail' => 'required|email|max:255|unique:users,email',
                'userPassword' => 'required|string|min:8',
                'userPasswordConfirmation' => 'required|same:userPassword',
                'userRoleId' => 'required|exists:roles,id',
            ] : [],
            default => [],
        };
    }

    public function messagesForStep(int $step): array
    {
        return match ($step) {
            1 => [
                'personId.required' => 'يجب اختيار شخص من القائمة',
                'personId.exists' => 'الشخص المختار غير موجود',
                'personNameAr.required' => 'الاسم بالعربي مطلوب',
                'personPhone.required' => 'رقم الهاتف مطلوب',
                'personGender.required' => 'الجنس مطلوب',
                'personGender.in' => 'قيمة الجنس غير صالحة',
            ],
            2 => [
                'department.required' => 'القسم مطلوب',
                'position.required' => 'المسمى الوظيفي مطلوب',
                'employmentType.required' => 'نوع التوظيف مطلوب',
                'employmentType.in' => 'نوع التوظيف غير صالح',
                'startDate.required' => 'تاريخ البدء مطلوب',
                'startDate.date' => 'تاريخ البدء غير صالح',
                'endDate.after' => 'تاريخ الانتهاء يجب أن يكون بعد تاريخ البدء',
            ],
            3 => [
                'branchId.required' => 'يجب اختيار الفرع',
                'branchId.exists' => 'الفرع غير موجود',
            ],
            4 => [
                'salaryAmount.required' => 'مبلغ الراتب مطلوب',
                'salaryAmount.numeric' => 'مبلغ الراتب يجب أن يكون رقم',
                'salaryAmount.min' => 'مبلغ الراتب لا يمكن أن يكون سالب',
                'salaryFrequency.required' => 'دورية الراتب مطلوبة',
                'salaryFrequency.in' => 'دورية الراتب غير صالحة',
                'workingHoursPerWeek.numeric' => 'ساعات العمل يجب أن تكون رقم',
                'workingHoursPerWeek.min' => 'ساعات العمل يجب أن تكون أكثر من صفر',
                'workingHoursPerWeek.max' => 'ساعات العمل لا يمكن أن تتجاوز 168 ساعة',
            ],
            5 => [
                'userEmail.required' => 'البريد الإلكتروني مطلوب',
                'userEmail.email' => 'صيغة البريد الإلكتروني غير صحيحة',
                'userEmail.unique' => 'البريد الإلكتروني مستخدم بالفعل',
                'userPassword.required' => 'كلمة المرور مطلوبة',
                'userPassword.min' => 'كلمة المرور يجب أن تكون 8 أحرف على الأقل',
                'userPasswordConfirmation.required' => 'تأكيد كلمة المرور مطلوب',
                'userPasswordConfirmation.same' => 'تأكيد كلمة المرور غير متطابق',
                'userRoleId.required' => 'يجب اختيار الصلاحيات',
                'userRoleId.exists' => 'الصلاحيات المختارة غير موجودة',
            ],
            default => [],
        };
    }

    public function nextStep(): void
    {
        $this->validate(
            $this->rulesForStep($this->currentStep),
            $this->messagesForStep($this->currentStep)
        );

        if ($this->currentStep < $this->totalSteps) {
            $this->currentStep++;
        }
    }

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

    public function goToStep(int $step): void
    {
        if ($step < $this->currentStep) {
            $this->currentStep = $step;
        }
    }

    public function confirm(): void
    {
        try {
            DB::transaction(function () {
                $person = $this->resolveOrCreatePerson();

                $data = [
                    'academy_id' => app('current_academy')->id,
                    'person_id' => $person->id,
                    'department' => $this->department,
                    'position' => $this->position,
                    'employment_type' => $this->employmentType,
                    'start_date' => $this->startDate,
                    'end_date' => $this->endDate ?: null,
                    'branch_id' => $this->branchId,
                    'manager_id' => $this->managerId,
                    'salary_amount' => (int) round((float) $this->salaryAmount * 100),
                    'salary_frequency' => $this->salaryFrequency,
                    'working_hours_per_week' => $this->workingHoursPerWeek ?: null,
                ];

                app(EmployeeService::class)->create($data, auth()->user());

                if ($this->createUserAccount) {
                    $user = User::create([
                        'academy_id' => app('current_academy')->id,
                        'name' => $this->personName ?: $this->personNameAr,
                        'name_ar' => $this->personNameAr,
                        'email' => $this->userEmail,
                        'password' => Hash::make($this->userPassword),
                        'role_id' => $this->userRoleId,
                        'person_id' => $person->id,
                        'status' => 'active',
                    ]);

                    app(PersonService::class)->linkUser($person, $user);
                }
            });

            $this->completed = true;
            session()->flash('success', 'تم إضافة الموظف بنجاح');
        } catch (DomainException $e) {
            session()->flash('error', $e->getMessage());
        }
    }

    private function resolveOrCreatePerson(): Person
    {
        if ($this->personId) {
            return Person::findOrFail($this->personId);
        }

        return Person::create([
            'academy_id' => app('current_academy')->id,
            'name_ar' => $this->personNameAr,
            'name' => $this->personName ?: null,
            'phone' => $this->personPhone,
            'national_id' => $this->personNationalId ?: null,
            'date_of_birth' => $this->personDateOfBirth ?: null,
            'gender' => $this->personGender,
            'created_by' => auth()->id(),
        ]);
    }

    public function render()
    {
        $rolesQuery = Role::orderBy('level', 'desc');
        if (! auth()->user()->is_super_admin) {
            $currentUserLevel = auth()->user()->primaryRole?->level ?? 0;
            $rolesQuery->where('level', '<', $currentUserLevel);
        }

        return view('livewire.hr.create-employee-wizard', [
            'stepLabels' => $this->getStepLabels(),
            'branches' => Branch::where('is_active', true)->orderBy('name_ar')->get(['id', 'name_ar']),
            'employees' => $this->branchId
                ? \App\Domain\HR\Models\Employee::where('branch_id', $this->branchId)->with('person')->get()
                : collect(),
            'employmentTypes' => EmploymentType::cases(),
            'salaryFrequencies' => SalaryFrequency::cases(),
            'roles' => $rolesQuery->get(['id', 'name_ar', 'slug', 'level']),
        ]);
    }
}
