<?php

namespace App\Livewire\Applicant;

use App\Enums\ApplicationStep;
use App\Enums\Gender;
use App\Livewire\Applicant\Concerns\WizardStep;
use App\Models\Application;
use Illuminate\Validation\Rule;
use Livewire\Component;

class PersonalInformationForm extends Component
{
    use WizardStep;

    public string $first_name = '';
    public string $middle_name = '';
    public string $last_name = '';
    public string $date_of_birth = '';
    public string $gender = '';
    public string $nationality = 'Ugandan';
    public string $identity_type = 'national_id';
    public string $national_id = '';
    public string $passport_number = '';
    public string $marital_status = '';
    public string $disability_status = 'none';
    public string $disability_details = '';

    protected function step(): ApplicationStep
    {
        return ApplicationStep::Personal;
    }

    public function mount(Application $application): void
    {
        $this->mountWizardStep($application);

        $applicant = $application->applicant;

        $this->first_name = $applicant->first_name ?? '';
        $this->middle_name = $applicant->middle_name ?? '';
        $this->last_name = $applicant->last_name ?? '';
        $this->date_of_birth = $applicant->date_of_birth?->toDateString() ?? '';
        $this->gender = $applicant->gender?->value ?? '';
        $this->nationality = $applicant->nationality ?: 'Ugandan';
        $this->national_id = $applicant->national_id ?? '';
        $this->passport_number = $applicant->passport_number ?? '';
        $this->marital_status = $applicant->marital_status ?? '';
        $this->disability_status = $applicant->disability_status ?: 'none';
        $this->disability_details = $applicant->disability_details ?? '';

        $this->identity_type = filled($applicant->passport_number) && blank($applicant->national_id)
            ? 'passport'
            : 'national_id';
    }

    protected function rules(): array
    {
        return [
            'first_name' => ['required', 'string', 'max:100'],
            'middle_name' => ['nullable', 'string', 'max:100'],
            'last_name' => ['required', 'string', 'max:100'],
            // An applicant must plausibly be old enough to hold a school-leaving certificate.
            'date_of_birth' => ['required', 'date', 'before:'.now()->subYears(14)->toDateString(), 'after:'.now()->subYears(90)->toDateString()],
            'gender' => ['required', Rule::enum(Gender::class)],
            'nationality' => ['required', 'string', 'max:100'],
            'identity_type' => ['required', 'in:national_id,passport'],
            'national_id' => ['nullable', 'required_if:identity_type,national_id', 'string', 'max:60'],
            'passport_number' => ['nullable', 'required_if:identity_type,passport', 'string', 'max:60'],
            'marital_status' => ['nullable', 'string', 'max:30'],
            'disability_status' => ['nullable', 'string', 'max:120'],
            'disability_details' => ['nullable', 'required_if:disability_status,yes', 'string', 'max:1000'],
        ];
    }

    protected function messages(): array
    {
        return [
            'date_of_birth.before' => 'Please enter a valid date of birth.',
            'date_of_birth.after' => 'Please enter a valid date of birth.',
            'national_id.required_if' => 'Enter your National ID number, or switch to passport.',
            'passport_number.required_if' => 'Enter your passport number, or switch to National ID.',
            'disability_details.required_if' => 'Please tell us what support you may need.',
        ];
    }

    /** Live validation as the applicant moves between fields (PRD 60, rule 3). */
    public function updated(string $field): void
    {
        $this->validateOnly($field);
    }

    public function save(): void
    {
        $data = $this->validate();

        $this->application->applicant->update([
            'first_name' => $data['first_name'],
            'middle_name' => $data['middle_name'] ?: null,
            'last_name' => $data['last_name'],
            'date_of_birth' => $data['date_of_birth'],
            'gender' => $data['gender'],
            'nationality' => $data['nationality'],
            'national_id' => $data['identity_type'] === 'national_id' ? $data['national_id'] : null,
            'passport_number' => $data['identity_type'] === 'passport' ? $data['passport_number'] : null,
            'marital_status' => $data['marital_status'] ?: null,
            'disability_status' => $data['disability_status'] ?: null,
            'disability_details' => $data['disability_status'] === 'yes' ? $data['disability_details'] : null,
        ]);

        // Keep the account name in step with the applicant record.
        $this->application->applicant->user->update([
            'name' => trim("{$data['first_name']} {$data['last_name']}"),
        ]);

        $this->completeStep();
    }

    public function render()
    {
        return view('livewire.applicant.personal-information-form', [
            'genders' => Gender::options(),
        ]);
    }
}
