<?php

namespace App\Components\Claim\Application;

use App\Models\Claim\Claim;
use App\Models\Claim\TerminalIllness as ClaimTerminalIllness;
use App\Services\HistoryService;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Livewire\Component;

class TerminalIllness extends Component {
    use AuthorizesRequests;
    public Claim $claim;

    public bool $terminal_illness = false;
    public ?string $terminal_illness_details = null;

    public ?bool $applied_advance_payment = null;
    public ?bool $permission_confirm_health = null;
    public ?bool $provide_ds1500 = null;

    public ?bool $agree_contact_healthcare = null;

    public ?bool $has_medical_ref = null;
    public ?string $medical_reference_number = null;

    public ?array $healthcare_professional = null;

    protected $messages = [

        'applied_advance_payment.required_if' =>
            'Please tell us whether an advance payment has been applied for.',

        'permission_confirm_health.required_if' =>
            'Please confirm whether we can contact healthcare professionals.',

        'provide_ds1500.required_if' =>
            'Please tell us whether a DS1500 has been provided.',

        'agree_contact_healthcare.required_if' =>
            'Please confirm whether we can contact a healthcare professional.',

        'has_medical_ref.required_if' =>
            'Please tell us whether you have a medical reference number.',

        'medical_reference_number.required_if' =>
            'Please enter the medical reference number.',

        'medical_reference_number.max' =>
            'The medical reference number must be no longer than 100 characters.',

        'healthcare_professional.type.required_if' =>
            'Please tell us the healthcare professional’s role.',

        'healthcare_professional.name.required_if' =>
            'Please enter the healthcare professional’s name.',

        'healthcare_professional.place.required_if' =>
            'Please enter where the healthcare professional works.',

        'healthcare_professional.email.required_if' =>
            'Please enter the healthcare professional’s email address.',

        'healthcare_professional.email.email' =>
            'Please enter a valid email address for the healthcare professional.',

        'healthcare_professional.phone.required_if' =>
            'Please enter the healthcare professional’s phone number.',

        'healthcare_professional.address_1.required_if' =>
            'Please enter the first line of the healthcare professional’s address.',

        'healthcare_professional.postcode.required_if' =>
            'Please enter the healthcare professional’s postcode.',
    ];


    public function mount(Claim $claim) {
        $this->claim = $claim;

        if ($existing = $claim->terminalIllness) {
            $this->fill([
                'terminal_illness' => true,
                'terminal_illness_details' => $existing->terminal_illness_details,

                'applied_advance_payment' => $existing->applied_advance_payment,
                'permission_confirm_health' => $existing->permission_confirm_health,
                'provide_ds1500' => $existing->provide_ds1500,

                'agree_contact_healthcare' => $existing->agree_contact_healthcare,
                'has_medical_ref' => $existing->has_medical_ref,
                'medical_reference_number' => $existing->medical_reference_number,
            ]);

            if ($existing->agree_contact_healthcare) {
                $this->healthcare_professional = [
                    'type' => $existing->healthcare_type,
                    'name' => $existing->healthcare_name,
                    'place' => $existing->healthcare_place_of_work,
                    'email' => $existing->healthcare_email,
                    'phone' => $existing->healthcare_phone,
                    'address_1' => $existing->healthcare_address_1,
                    'address_2' => $existing->healthcare_address_2,
                    'address_3' => $existing->healthcare_address_3,
                    'postcode' => $existing->healthcare_postcode,
                ];
            }
        }
    }

    public function updated($property) {
        $this->validateOnly($property);
    }


    public function updatedTerminalIllness(HistoryService $service, $value) {
        if (!$value && $this->claim->terminalIllness) {
            $this->authorize('claims.edit');
            $this->claim->terminalIllness->delete();

            $service->add(
                $this->claim->client,
                'Terminal illness details removed',
                ['claim_id' => $this->claim->id],
            );

            $this->reset([
                'terminal_illness_details',
                'applied_advance_payment',
                'permission_confirm_health',
                'provide_ds1500',
                'agree_contact_healthcare',
                'has_medical_ref',
                'medical_reference_number',
                'healthcare_professional',
            ]);
        }
    }


    public function updatedAppliedAdvancePayment() {
        $this->reset([
            'permission_confirm_health',
            'provide_ds1500',
        ]);
    }

    public function updatedAgreeContactHealthcare($value) {
        if (!$value) {
            $this->healthcare_professional = null;
            $this->has_medical_ref = null;
            $this->medical_reference_number = null;
        }
    }

    public function updatedHasMedicalRef($value) {
        if (!$value) {
            $this->medical_reference_number = null;
        }
    }


    public function save(HistoryService $service) {
        $this->authorize('claims.edit');
        $this->validate();

        $existing = $this->claim->terminalIllness;
        $before = $existing?->toArray() ?? null;

        $payload = [
            'terminal_illness' => $this->terminal_illness,
            'terminal_illness_details' => $this->terminal_illness_details,
            'applied_advance_payment' => $this->applied_advance_payment,
            'permission_confirm_health' => $this->permission_confirm_health,
            'provide_ds1500' => $this->provide_ds1500,
            'agree_contact_healthcare' => $this->agree_contact_healthcare,
            'has_medical_ref' => $this->has_medical_ref,
            'medical_reference_number' => $this->medical_reference_number,

            'healthcare_type' => data_get($this->healthcare_professional, 'type'),
            'healthcare_name' => data_get($this->healthcare_professional, 'name'),
            'healthcare_place_of_work' => data_get($this->healthcare_professional, 'place'),
            'healthcare_email' => data_get($this->healthcare_professional, 'email'),
            'healthcare_phone' => data_get($this->healthcare_professional, 'phone'),
            'healthcare_address_1' => data_get($this->healthcare_professional, 'address_1'),
            'healthcare_address_2' => data_get($this->healthcare_professional, 'address_2'),
            'healthcare_address_3' => data_get($this->healthcare_professional, 'address_3'),
            'healthcare_postcode' => data_get($this->healthcare_professional, 'postcode'),
        ];

        $model = ClaimTerminalIllness::updateOrCreate(
            ['claim_id' => $this->claim->id],
            $payload
        );


        if (!$existing) {
            $service->add(
                $this->claim->client,
                'Terminal illness details added',
                [
                    'claim_id' => $this->claim->id,
                    'added' => $this->snapshot(),
                ]
            );
        } else {
            $changes = [];

            foreach ($model->getChanges() as $field => $newValue) {
                if (in_array($field, ['updated_at', 'created_at'])) {
                    continue;
                }

                $changes[$field] = [
                    'from' => $before[$field] ?? null,
                    'to'   => $newValue,
                ];
            }

            if (!empty($changes)) {
                $service->add(
                    $this->claim->client,
                    'Terminal illness details updated',
                    [
                        'claim_id' => $this->claim->id,
                        'changed' => $changes,
                    ]
                );
            }
        }

        $this->dispatch('toast',
            title: 'Saved',
            message: 'Successfully saved data.',
            type: 'success'
        );
    }


    private function snapshot(): array {
        return [
            'terminal_illness' => $this->terminal_illness,
            'terminal_illness_details' => $this->terminal_illness_details,
            'applied_advance_payment' => $this->applied_advance_payment,
            'permission_confirm_health' => $this->permission_confirm_health,
            'provide_ds1500' => $this->provide_ds1500,
            'agree_contact_healthcare' => $this->agree_contact_healthcare,
            'has_medical_ref' => $this->has_medical_ref,
            'medical_reference_number' => $this->medical_reference_number,

            'healthcare' => $this->agree_contact_healthcare
                ? $this->healthcare_professional
                : null,
        ];
    }


    public function render() {
        return view('components.claim.application.terminal-illness');
    }

    protected function rules() {
        return [
            'applied_advance_payment' => 'required_if:terminal_illness,true|boolean',

            'permission_confirm_health' =>
                'exclude_if:applied_advance_payment,false|required_if:applied_advance_payment,true|boolean',

            'provide_ds1500' =>
                'required_if:applied_advance_payment,false|boolean',

            'agree_contact_healthcare' =>
                'exclude_if:provide_ds1500,true|required_if:provide_ds1500,false|boolean',

            'has_medical_ref' =>
                'exclude_if:provide_ds1500,false|required_if:agree_contact_healthcare,true|boolean',

            'medical_reference_number' =>
                'exclude_if:has_medical_ref,false|required_if:has_medical_ref,true|max:100',

            'healthcare_professional.type' =>
                'required_if:agree_contact_healthcare,1|string|max:255',

            'healthcare_professional.name' =>
                'required_if:agree_contact_healthcare,1|string|max:255',

            'healthcare_professional.place' =>
                'required_if:agree_contact_healthcare,1|string|max:255',

            'healthcare_professional.email' =>
                'required_if:agree_contact_healthcare,1|email',

            'healthcare_professional.phone' =>
                'required_if:agree_contact_healthcare,1|string|max:50',

            'healthcare_professional.address_1' =>
                'required_if:agree_contact_healthcare,1|string|max:255',

            'healthcare_professional.address_2' =>
                'nullable|string|max:255',

            'healthcare_professional.address_3' =>
                'nullable|string|max:255',

            'healthcare_professional.postcode' =>
                'required_if:agree_contact_healthcare,1|string|max:20',
        ];
    }

}
