<?php

namespace App\Livewire\HR;

use App\Domain\HR\Enums\EmployeeStatus;
use App\Domain\HR\Enums\EmploymentType;
use App\Domain\HR\Enums\SalaryFrequency;
use App\Domain\HR\Models\Employee;
use App\Domain\HR\Services\EmployeeService;
use App\Domain\Identity\Models\Branch;
use App\Domain\Identity\Models\Person;
use App\Domain\Shared\Exceptions\DomainException;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Component;

#[Layout('layouts.app')]
#[Title('بيانات الموظف')]
class EmployeeForm extends Component
{
    public ?Employee $employee = null;
    public bool $editing = false;

    // Person selection
    public string $personSearch = '';
    public ?int $personId = null;
    public string $selectedPersonName = '';

    // Form fields
    public string $department = '';
    public string $position = '';
    public string $employmentType = 'full_time';
    public string $startDate = '';
    public ?string $endDate = null;
    public ?string $salaryAmount = null;
    public string $salaryFrequency = '';
    public ?string $workingHoursPerWeek = null;
    public string $branchId = '';
    public string $managerId = '';
    public string $notes = '';

    public function mount(?Employee $employee = null): void
    {
        if ($employee && $employee->exists) {
            $this->authorize('employees.update');
            $this->employee = $employee;
            $this->editing = true;

            $this->personId = $employee->person_id;
            $this->selectedPersonName = $employee->person->name_ar ?? '';
            $this->department = $employee->department ?? '';
            $this->position = $employee->position ?? '';
            $this->employmentType = $employee->employment_type->value;
            $this->startDate = $employee->start_date->format('Y-m-d');
            $this->endDate = $employee->end_date?->format('Y-m-d');
            $this->salaryAmount = $employee->salary_amount ? (string) ($employee->salary_amount / 100) : null;
            $this->salaryFrequency = $employee->salary_frequency?->value ?? '';
            $this->workingHoursPerWeek = $employee->working_hours_per_week ? (string) $employee->working_hours_per_week : null;
            $this->branchId = (string) ($employee->branch_id ?? '');
            $this->managerId = (string) ($employee->manager_id ?? '');
            $this->notes = $employee->notes ?? '';
        } else {
            $this->authorize('employees.create');
            $this->startDate = now()->format('Y-m-d');
        }
    }

    public function rules(): array
    {
        return [
            'personId' => 'required|exists:people,id',
            'department' => 'nullable|string|max:30',
            'position' => 'nullable|string|max:50',
            'employmentType' => 'required|in:' . implode(',', array_column(EmploymentType::cases(), 'value')),
            'startDate' => 'required|date',
            'endDate' => 'nullable|date|after_or_equal:startDate',
            'salaryAmount' => 'nullable|numeric|min:0',
            'salaryFrequency' => 'nullable|in:' . implode(',', array_column(SalaryFrequency::cases(), 'value')),
            'workingHoursPerWeek' => 'nullable|numeric|min:0|max:168',
            'branchId' => 'nullable|exists:branches,id',
            'managerId' => 'nullable|exists:employees,id',
            'notes' => 'nullable|string|max:2000',
        ];
    }

    public function messages(): array
    {
        return [
            'personId.required' => 'يجب اختيار شخص',
            'personId.exists' => 'الشخص المختار غير موجود',
            'employmentType.required' => 'نوع التوظيف مطلوب',
            'employmentType.in' => 'نوع التوظيف غير صالح',
            'startDate.required' => 'تاريخ البداية مطلوب',
            'startDate.date' => 'تاريخ البداية غير صالح',
            'endDate.after_or_equal' => 'تاريخ الانتهاء يجب أن يكون بعد تاريخ البداية',
            'salaryAmount.numeric' => 'الراتب يجب أن يكون رقماً',
            'salaryFrequency.in' => 'دورة الراتب غير صالحة',
            'workingHoursPerWeek.numeric' => 'ساعات العمل يجب أن تكون رقماً',
        ];
    }

    public function save(EmployeeService $service): void
    {
        $this->validate();

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

        try {
            if ($this->editing) {
                $service->update($this->employee, $data, auth()->user());
                session()->flash('success', __('تم تحديث بيانات الموظف بنجاح'));
            } else {
                $data['academy_id'] = app('current_academy')->id;
                $service->create($data, auth()->user());
                session()->flash('success', __('تم إضافة الموظف بنجاح'));
            }

            $this->redirect(route('employees.list'), navigate: true);
        } catch (DomainException $e) {
            session()->flash('error', $e->getMessage());
        }
    }

    public function selectPerson(int $id): void
    {
        $person = Person::find($id);
        if ($person) {
            $this->personId = $person->id;
            $this->selectedPersonName = $person->name_ar;
            $this->personSearch = '';
        }
    }

    public function render()
    {
        $searchResults = [];
        if (strlen($this->personSearch) >= 2) {
            $searchResults = Person::where(function ($q) {
                $q->where('name_ar', 'ilike', "%{$this->personSearch}%")
                    ->orWhere('name', 'ilike', "%{$this->personSearch}%")
                    ->orWhere('phone', 'ilike', "%{$this->personSearch}%")
                    ->orWhere('national_id', 'ilike', "%{$this->personSearch}%");
            })->limit(10)->get();
        }

        return view('livewire.hr.employee-form', [
            'searchResults' => $searchResults,
            'employmentTypes' => EmploymentType::cases(),
            'salaryFrequencies' => SalaryFrequency::cases(),
            'branches' => Branch::orderBy('name_ar')->get(),
            'managers' => Employee::with('person')->active()->get(),
        ]);
    }
}
