<?php

namespace App\Http\Requests\CRM;

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

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

    /**
     * Convert "d.m.Y." => "Y-m-d" for nested "passport.*" fields.
     */
    protected function prepareForValidation()
    {
        $this->merge([
            'passport' => array_merge($this->input('passport') ?? [], [
                'date_of_birth' => $this->formatDate($this->input('passport.date_of_birth')),
                'issued_at'     => $this->formatDate($this->input('passport.issued_at')),
                'expires_at'    => $this->formatDate($this->input('passport.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
    {
        $individualId = optional($this->route('individual'))->id;

        return [
            'passport.jmbg'                  => [
                'nullable', // can be null for non-resident
                'string',
                'max:255',
                Rule::unique('passports', 'jmbg')
                    ->where('documentable_type', Individual::class)
                    ->whereNot('documentable_id', $individualId),
            ],
            'passport.issuer'                => 'nullable|string|max:255',
            'passport.reg_no'                => 'nullable|string|max:255',
            'passport.date_of_birth'         => 'nullable|date',
            'passport.issued_at'             => 'nullable|date',
            'passport.expires_at'            => 'nullable|date|after:passport.issued_at',
            'passport.place_of_birth_country_id' => 'nullable|exists:countries,id',
            'passport.country_code_country_id'   => 'nullable|exists:countries,id',
            'passport.nationality_country_id'    => 'nullable|exists:countries,id',
        ];
    }

    /**
     * Compare with active ID Card:
     * - If ID card->jmbg != null, passport jmbg must either match or be null (if you allow that).
     * - date_of_birth must match
     * - passport->place_of_birth_country_id must match city->country_id from ID card
     */
    protected function withValidator($validator)
    {
        $validator->after(function (Validator $validator) {
            $individual = $this->route('individual');
            if (!$individual) {
                return;
            }

            $passportData = $this->input('passport', []);
            $passportJmbg = $passportData['jmbg'] ?? null;
            $passportDob  = $passportData['date_of_birth'] ?? null;
            $passportCountryId = $passportData['place_of_birth_country_id'] ?? null;

            // Active ID card?
            $activeIdCard = $individual->idCards()
                ->active()
                ->latest()
                ->first();

            if ($activeIdCard) {
                // 1) JMBG check
                // If ID card->jmbg is non-null, we can either force an exact match
                // or allow passport jmbg to be null if your business logic allows it.
                if (!is_null($activeIdCard->jmbg)) {
                    if (!is_null($passportJmbg) && $passportJmbg !== $activeIdCard->jmbg) {
                        $validator->errors()->add(
                            'passport.jmbg',
                            'Passport JMBG must match the active ID card JMBG ('
                                . $activeIdCard->jmbg . ') or be null.'
                        );
                    }
                }

                // 2) date_of_birth check
                if ($activeIdCard->date_of_birth && $passportDob) {
                    $idCardDobStr = $activeIdCard->date_of_birth->format('Y-m-d');
                    if ($passportDob !== $idCardDobStr) {
                        $validator->errors()->add(
                            'passport.date_of_birth',
                            'Passport date_of_birth must match the active ID card date_of_birth ('
                                . $idCardDobStr . ').'
                        );
                    }
                }

                // 3) place_of_birth_country_id must match ID card city->country_id
                if ($passportCountryId && $activeIdCard->place_of_birth_city_id) {
                    $cityCountryId = optional($activeIdCard->placeOfBirthCity)->country_id;
                    if (
                        $cityCountryId
                        && (int) $cityCountryId !== (int) $passportCountryId
                    ) {
                        $validator->errors()->add(
                            'passport.place_of_birth_country_id',
                            'Passport country of birth must match the active ID card city->country.'
                        );
                    }
                }
            }
        });
    }
}
