<?php

namespace App\Http\Requests\CRM;

use App\Models\CRM\Individual;
use App\Models\CRM\Passport;
use App\Models\CRM\City;
use Carbon\Carbon;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
use Illuminate\Contracts\Validation\Validator;

class StoreIdCardRequest extends FormRequest
{
    public function authorize(): bool
    {
        return true;
    }

    /**
     * Convert incoming "d.m.Y." dates to "Y-m-d" BEFORE validation.
     */
    protected function prepareForValidation()
    {
        $this->merge([
            'date_of_birth' => $this->formatDate($this->input('date_of_birth')),
            'issued_at'     => $this->formatDate($this->input('issued_at')),
            'expires_at'    => $this->formatDate($this->input('expires_at')),
        ]);
    }

    /**
     * Helper method to format dates if valid, otherwise return null.
     */
    private function formatDate($date)
    {
        if (!empty($date)) {
            try {
                return Carbon::createFromFormat('d.m.Y.', $date)->format('Y-m-d');
            } catch (\Exception $e) {
                // Return the original value if invalid or unformatted to allow normal validation to handle it
                return $date;
            }
        }
        return null; // Return null for empty values
    }

    public function rules(): array
    {
        // The Individual from the route param "individual"
        $individualId = optional($this->route('individual'))->id;

        return [
            'jmbg'                   => [
                'required',
                'string',
                'max:255',
                Rule::unique('id_cards', 'jmbg')
                    ->where('documentable_type', Individual::class)
                    ->whereNot('documentable_id', $individualId),
            ],
            'issuer'                 => 'nullable|string|max:255',
            'reg_no'                 => 'nullable|string|max:255',
            'date_of_birth'          => 'nullable|date',
            'issued_at'              => 'nullable|date',
            'expires_at'             => 'nullable|date|after:issued_at',
            'place_of_birth_city_id' => 'nullable|exists:cities,id',
        ];
    }

    /**
     * After normal validation, add extra rules comparing ID Card to any active Passport.
     */
    protected function withValidator($validator)
    {
        $validator->after(function (Validator $validator) {
            $individual = $this->route('individual');
            if (! $individual) {
                return;
            }

            // Extract final data in "Y-m-d" format
            $idCardJmbg   = $this->input('jmbg');
            $idCardDob    = $this->input('date_of_birth'); // e.g. "2025-09-01"
            $cityId       = $this->input('place_of_birth_city_id');

            // If there's an active Passport, compare fields:
            $activePassport = $individual->passports()
                ->active()
                ->latest()
                ->first();

            if ($activePassport) {
                // 1) If passport->jmbg is non-null, ID Card jmbg must match it
                if (! is_null($activePassport->jmbg)) {
                    if ($idCardJmbg !== $activePassport->jmbg) {
                        $validator->errors()->add(
                            'jmbg',
                            'ID Card JMBG must match the active Passport JMBG (' . $activePassport->jmbg . ').'
                        );
                    }
                }

                // 2) date_of_birth must match
                if ($activePassport->date_of_birth && $idCardDob) {
                    $passportDobStr = $activePassport->date_of_birth->format('Y-m-d');
                    if ($idCardDob !== $passportDobStr) {
                        $validator->errors()->add(
                            'date_of_birth',
                            'ID Card date_of_birth must match the active Passport date_of_birth (' .
                                $passportDobStr . ').'
                        );
                    }
                }

                // 3) place_of_birth: city->country_id must match passport->place_of_birth_country_id
                if ($activePassport->place_of_birth_country_id && $cityId) {
                    $cityCountryId = optional(City::find($cityId))->country_id;
                    if (
                        $cityCountryId
                        && (int) $cityCountryId !== (int) $activePassport->place_of_birth_country_id
                    ) {
                        $validator->errors()->add(
                            'place_of_birth_city_id',
                            'The city’s country must match the Passport’s place_of_birth_country_id.'
                        );
                    }
                }
            }
        });
    }
}
