<?php

namespace App\Rules\Invoicing;

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

class MoralTaxIdentifier implements ValidationRule
{
    /**
     * ISO 3166-1 alpha-3 (e.g. MEX, USA, CAN)
     */
    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
     * - Conserva guiones SOLO en países que los requieren (EIN USA, RIF VEN, RUT CHL)
     */
    protected function normalize(string $value): string
    {
        $v = trim($value);

        // Quita espacios y convierte a mayúsculas
        $v = Str::of($v)->upper()->replace(' ', '')->toString();

        // Para la mayoría, quitamos guiones. Los reinsertamos si el patrón lo requiere.
        $keepHyphen = in_array($this->country, ['USA', 'VEN', 'CHL'], true);
        if (!$keepHyphen) {
            $v = str_replace('-', '', $v);
        }

        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 [
            // México (RFC)
            'MEX' => [
                'regex' => '/^([A-ZÑ&]{3,4})(\d{2})(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])[A-Z0-9]{3}$/u',
                'title' => 'RFC válido (3 o 4 letras, fecha AAMMDD, 3 alfanuméricos)',
            ],
            // Estados Unidos (EIN)
            'USA' => [
                'regex' => '/^\d{2}\-\d{7}$/',
                'title' => 'EIN válido (formato 12-3456789)',
            ],
            // Canadá (BN)
            'CAN' => [
                'regex' => '/^\d{9}$/',
                'title' => 'Business Number canadiense (9 dígitos)',
            ],
            // Francia (SIREN / SIRET)
            'FRA' => [
                'regex' => '/^(\d{9}|\d{14})$/',
                'title' => 'SIREN (9) o SIRET (14) francés',
            ],
            // Italia (Codice Fiscale)
            'ITA' => [
                'regex' => '/^[A-Z]{6}[0-9]{2}[A-Z][0-9]{2}[A-Z][0-9]{3}[A-Z]$/',
                'title' => 'Codice Fiscale (16 caracteres)',
            ],
            // España (NIF/CIF genérico)
            'ESP' => [
                'regex' => '/^[A-Z0-9]{8,9}$/',
                'title' => 'NIF/CIF válido (8-9 alfanuméricos)',
            ],

            // América Central y Caribe (según tus reglas)
            'GTM' => ['regex' => '/^[A-Z0-9]{8,15}$/', 'title' => 'NIT Guatemala (8-15)'],
            'BLZ' => ['regex' => '/^[A-Z0-9\-]{6,15}$/', 'title' => 'Belice (6-15, puede llevar guión)'],
            'SLV' => ['regex' => '/^\d{14}$/', 'title' => 'NIT El Salvador (14)'],
            'HND' => ['regex' => '/^\d{14}$/', 'title' => 'RTN Honduras (14)'],
            'NIC' => ['regex' => '/^\d{14}$/', 'title' => 'RUC Nicaragua (14)'],
            'CRI' => ['regex' => '/^\d{9,12}$/', 'title' => 'Cédula Costa Rica (9-12)'],
            'PAN' => ['regex' => '/^[A-Z0-9\-]{8,20}$/', 'title' => 'RUC Panamá (8-20, guiones permitidos)'],

            'BHS' => ['regex' => '/^[A-Z0-9]{6,15}$/', 'title' => 'Bahamas (6-15)'],
            'CUB' => ['regex' => '/^\d{11}$/', 'title' => 'Cuba (11)'],
            'JAM' => ['regex' => '/^\d{9}$/', 'title' => 'TRN Jamaica (9)'],
            'HTI' => ['regex' => '/^\d{10}$/', 'title' => 'Haití (10)'],
            'DOM' => ['regex' => '/^\d{9}$/', 'title' => 'RNC Dominicana (9)'],
            'KNA' => ['regex' => '/^[A-Z0-9]{6,15}$/', 'title' => 'Saint Kitts and Nevis (6-15)'],
            'ATG' => ['regex' => '/^[A-Z0-9]{6,15}$/', 'title' => 'Antigua y Barbuda (6-15)'],
            'DMA' => ['regex' => '/^[A-Z0-9]{6,15}$/', 'title' => 'Dominica (6-15)'],
            'LCA' => ['regex' => '/^[A-Z0-9]{6,15}$/', 'title' => 'Santa Lucía (6-15)'],
            'VCT' => ['regex' => '/^[A-Z0-9]{6,15}$/', 'title' => 'San Vicente y las Granadinas (6-15)'],
            'BRB' => ['regex' => '/^[A-Z0-9]{6,15}$/', 'title' => 'Barbados (6-15)'],
            'TTO' => ['regex' => '/^[A-Z0-9]{6,15}$/', 'title' => 'Trinidad y Tobago (6-15)'],
            'GRD' => ['regex' => '/^[A-Z0-9]{6,15}$/', 'title' => 'Granada (6-15)'],

            // Sudamérica
            'COL' => ['regex' => '/^\d{9,10}$/', 'title' => 'NIT Colombia (9-10)'],
            'VEN' => ['regex' => '/^[VEJGP]\-\d{8}\-\d$/', 'title' => 'RIF Venezuela (V/E/J/G/P-XXXXXXXX-X)'],
            'GUY' => ['regex' => '/^[A-Z0-9]{6,15}$/', 'title' => 'Guyana (6-15)'],
            'SUR' => ['regex' => '/^[A-Z0-9]{6,15}$/', 'title' => 'Surinam (6-15)'],
            'BRA' => ['regex' => '/^(\d{11}|\d{14})$/', 'title' => 'CPF (11) o CNPJ (14) Brasil'],
            'ECU' => ['regex' => '/^\d{13}$/', 'title' => 'RUC Ecuador (13)'],
            'PER' => ['regex' => '/^\d{11}$/', 'title' => 'RUC Perú (11)'],
            'BOL' => ['regex' => '/^\d{7,12}$/', 'title' => 'NIT Bolivia (7-12)'],
            'CHL' => ['regex' => '/^\d{7,8}\-[0-9K]$/i', 'title' => 'RUT Chile (7-8 + DV)'],
            'PRY' => ['regex' => '/^\d{6,8}$/', 'title' => 'RUC Paraguay (6-8)'],
            'URY' => ['regex' => '/^\d{12}$/', 'title' => 'RUT Uruguay (12)'],
            'ARG' => ['regex' => '/^\d{11}$/', 'title' => 'CUIT Argentina (11)'],
        ];
    }

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

    public function validate(string $attribute, mixed $value, Closure $fail): void
    {
        if (!is_string($value) || $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.tax_identifier'));
            return;
        }

        // Validación extra para RUT (CHL): dígito verificador
        if ($this->country === 'CHL') {
            if (!$this->validChileanRut($value)) {
                $fail(__('validation.custom.tax_identifier_chl'));
            }
        }
    }

    /**
     * Valida DV del RUT chileno.
     */
    protected function validChileanRut(string $rut): bool
    {
        // Formato: ########-X (X puede ser K)
        [$num, $dv] = explode('-', $rut);
        $num = strrev($num);
        $suma = 0;
        $multiplo = 2;

        for ($i = 0; $i < strlen($num); $i++) {
            $suma += intval($num[$i]) * $multiplo;
            $multiplo = ($multiplo === 7) ? 2 : $multiplo + 1;
        }

        $resto = $suma % 11;
        $digito = 11 - $resto;
        $dvCalc = match ($digito) {
            10 => 'K',
            11 => '0',
            default => (string)$digito
        };

        return strtoupper($dv) === $dvCalc;
    }
}
