<?php

namespace App\Rules\Invoicing;

use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Support\Str;

class PostalCode implements ValidationRule
{
    protected string $country;

    public function __construct(string $country)
    {
        $this->country = Str::upper(trim($country));
    }

    /**
     * Normaliza el valor de entrada:
     * - Recorta espacios
     * - Lleva a mayúsculas
     * - Elimina espacios internos
     */
    protected function normalize(?string $value): string
    {
        if (!is_string($value)) return '';
        $v = Str::of($value)->trim()->upper()->replaceMatches('/\s+/u', ' ')->toString();
        return $v;
    }

    /**
     * Devuelve el regex (PHP) y un ejemplo/título por país.
     * IMPORTANTE: todas las expresiones están ancladas ^$
     */
    protected function patterns(): array
    {
        return [
          // Norteamérica y Europa
            'MEX' => ['regex' => '/^\d{5}$/', 'title' => 'Código Postal de México (5 dígitos)'],
            'USA' => ['regex' => '/^\d{5}(-\d{4})?$/', 'title' => 'ZIP de EE. UU. (12345 o 12345-6789)'],
          // CAN: sin D,F,I,O,Q,U; espacio opcional.
            'CAN' => ['regex' => '/^[ABCEGHJ-NPRSTVXY]\d[ABCEGHJ-NPRSTV-Z]\s?\d[ABCEGHJ-NPRSTV-Z]\d$/', 'title' => 'Canadá (A1A 1A1, espacio opcional)'],
            'FRA' => ['regex' => '/^\d{5}$/', 'title' => 'Francia (5 chiffres)'],
            'ITA' => ['regex' => '/^\d{5}$/', 'title' => 'Italia (CAP 5 cifre)'],
            'ESP' => ['regex' => '/^\d{5}$/', 'title' => 'España (5 dígitos)'],

          // Centroamérica
            'GTM' => ['regex' => '/^\d{5}$/', 'title' => 'Guatemala (5 dígitos)'],
            'SLV' => ['regex' => '/^\d{4}$/', 'title' => 'El Salvador (4 dígitos)'],
            'HND' => ['regex' => '/^\d{5}$/', 'title' => 'Honduras (5 dígitos)'],
            'NIC' => ['regex' => '/^\d{5}$/', 'title' => 'Nicaragua (5 dígitos)'],
            'CRI' => ['regex' => '/^\d{5}$/', 'title' => 'Costa Rica (5 dígitos)'],
            'PAN' => ['regex' => '/^\d{4,6}$/', 'title' => 'Panamá (4-6 dígitos)'],
            'BLZ' => ['regex' => '/^(?:N\/A|NA|[A-Z0-9\- ]{3,10})$/', 'title' => 'Belice: N/A o identificador 3-10'], // Belice no tiene nacional; permitimos N/A o flexible

          // Caribe
            'CUB' => ['regex' => '/^\d{5}$/', 'title' => 'Cuba (5 dígitos)'],
            'JAM' => ['nullable', 'regex' => '/^(?:N\/A|NA|[A-Z0-9\- ]{3,10})$/', 'title' => 'Jamaica: N/A o formato 3-10'],
            'HTI' => ['regex' => '/^(?:HT)?\d{4}$/', 'title' => 'Haití (HTdddd o 4 dígitos)'],
            'DOM' => ['regex' => '/^\d{5}$/', 'title' => 'República Dominicana (5 dígitos)'],
            'BHS' => ['regex' => '/^[A-Z0-9\- ]{3,10}$/', 'title' => 'Bahamas (flexible 3-10)'],
            'KNA' => ['regex' => '/^[A-Z0-9\- ]{3,10}$/', 'title' => 'San Cristóbal y Nieves (3-10)'],
            'ATG' => ['regex' => '/^[A-Z0-9\- ]{3,10}$/', 'title' => 'Antigua y Barbuda (3-10)'],
            'DMA' => ['regex' => '/^[A-Z0-9\- ]{3,10}$/', 'title' => 'Dominica (3-10)'],
            'LCA' => ['regex' => '/^[A-Z0-9\- ]{3,10}$/', 'title' => 'Santa Lucía (3-10)'],
            'VCT' => ['regex' => '/^[A-Z0-9\- ]{3,10}$/', 'title' => 'San Vicente y las Granadinas (3-10)'],
            'BRB' => ['regex' => '/^(?:BB\d{5}|[A-Z0-9\- ]{3,10})$/', 'title' => 'Barbados (BB12345 o 3-10)'], // Barbados: BB12345 o flexible
            'TTO' => ['regex' => '/^\d{6}$/', 'title' => 'Trinidad y Tobago (6 dígitos)'],
            'GRD' => ['regex' => '/^[A-Z0-9\- ]{3,10}$/', 'title' => 'Granada (flexible 3-10)'],

          // Sudamérica
            'COL' => ['regex' => '/^\d{6}$/', 'title' => 'Colombia (6 dígitos)'],
            'VEN' => ['regex' => '/^\d{4}$/', 'title' => 'Venezuela (4 dígitos)'],
            'GUY' => ['regex' => '/^[A-Z0-9\- ]{3,10}$/', 'title' => 'Guyana (3-10)'],
            'SUR' => ['regex' => '/^[A-Z0-9\- ]{3,10}$/', 'title' => 'Surinam (3-10)'],
            'BRA' => ['regex' => '/^\d{5}-?\d{3}$/', 'title' => 'Brasil (CEP 12345-678 o 12345678)'], // Brasil: 12345-678 o 12345678
            'ECU' => ['regex' => '/^\d{6}$/', 'title' => 'Ecuador (6 dígitos)'],
            'PER' => ['regex' => '/^\d{5}$/', 'title' => 'Perú (5 dígitos)'],
            'BOL' => ['regex' => '/^\d{4}$/', 'title' => 'Bolivia (4 dígitos)'],
            'CHL' => ['regex' => '/^(?:\d{7}|\d{3}-\d{4})$/', 'title' => 'Chile (ddddddd o ddd-dddd)'], // Chile: 7 dígitos seguidos o 3-4 con guion
            'PRY' => ['regex' => '/^\d{4}$/', 'title' => 'Paraguay (4 dígitos)'],
            'URY' => ['regex' => '/^\d{5}$/', 'title' => 'Uruguay (5 dígitos)'],
            'ARG' => ['regex' => '/^(?:[A-Z]\d{4}[A-Z]{3}|\d{4})$/', 'title' => 'Argentina (CPA A1234AAA o 1234)'], // Argentina: CPA “A1234AAA” o antiguo “1234”
        ];
    }

    /**
     * Patrón genérico por si el país no está mapeado
     */
    protected function fallback(): array
    {
        return [
            'regex' => '/^[A-Z0-9\- ]{3,10}$/',
            'title' => 'Código postal (3-10 caracteres alfanuméricos)',
        ];
    }

    public function validate(string $attribute, mixed $value, Closure $fail): void
    {
        if (!is_string($value) || trim($value) === '') {
            $fail(__('validation.required', ['attribute' => $attribute]));
            return;
        }

        $value = $this->normalize($value);

        $patterns = $this->patterns();
        $rule = $patterns[$this->country] ?? $this->fallback();

        if (!preg_match($rule['regex'], $value)) {
            $fail(__('validation.custom.postal_code'));
            return;
        }
    }
}
