<?php

namespace App\Services;

use Carbon\Carbon;
use Exception;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Http;
use Throwable;

class HaciendaPublicApiService
{
    private string $baseUrl = 'https://api.hacienda.go.cr/fe';

    public function consultarExoneracion(string $autorizacion, ?int $sucursalId = null, ?int $usuarioId = null): array
    {
        $autorizacion = strtoupper(trim($autorizacion));

        if (!preg_match('/^AL-[0-9]{8}-[0-9]{2}$/', $autorizacion)) {
            throw new Exception('El número de autorización EXONET no tiene el formato esperado AL-XXXXXXXX-XX.');
        }

        $response = Http::withOptions(['verify' => false])
            ->timeout(20)
            ->retry(2, 300)
            ->get($this->baseUrl . '/ex', [
                'autorizacion' => strtolower($autorizacion),
            ]);

        if ($response->status() === 404) {
            throw new Exception('La autorización EXONET no fue encontrada.');
        }

        if ($response->status() === 429) {
            throw new Exception('Hacienda limitó temporalmente las consultas. Intente nuevamente más tarde.');
        }

        if (!$response->successful()) {
            throw new Exception('No se pudo consultar la autorización EXONET.');
        }

        $raw = $response->json();
        if (!is_array($raw) || $raw === []) {
            throw new Exception('Hacienda no devolvió datos para la autorización EXONET.');
        }

        $normalizada = $this->normalizarExoneracion($raw);

        DB::table('fe_exoneraciones_consultas')->updateOrInsert(
            [
                'sucursal_id' => $sucursalId,
                'autorizacion' => $normalizada['autorizacion'],
            ],
            [
                'usuario_id' => $usuarioId,
                'numero_documento' => $normalizada['numero_documento'],
                'identificacion' => $normalizada['identificacion'],
                'tipo_autorizacion' => $normalizada['tipo_autorizacion'],
                'tipo_documento_ex' => $normalizada['tipo_documento_ex'],
                'tipo_documento_descripcion' => $normalizada['tipo_documento_descripcion'],
                'codigo_institucion' => $normalizada['codigo_institucion'],
                'nombre_institucion' => $normalizada['nombre_institucion'],
                'fecha_emision' => $normalizada['fecha_emision'],
                'fecha_vencimiento' => $normalizada['fecha_vencimiento'],
                'tarifa_exonerada' => $normalizada['tarifa_exonerada'],
                'porcentaje_exoneracion' => $normalizada['porcentaje_exoneracion'],
                'posee_cabys' => $normalizada['posee_cabys'] ? 1 : 0,
                'cabys_json' => json_encode($normalizada['cabys'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),
                'vigente' => $normalizada['vigente'] ? 1 : 0,
                'respuesta_json' => json_encode($raw, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),
                'consultado_en' => now(),
            ]
        );

        return $normalizada;
    }

    public function consultarAgropecuario(string $identificacion, ?int $sucursalId = null, ?int $usuarioId = null): array
    {
        $identificacion = preg_replace('/[^0-9A-Za-z]/', '', $identificacion) ?: '';

        if ($identificacion === '') {
            throw new Exception('Debe indicar una identificación válida.');
        }

        $response = Http::withOptions(['verify' => false])
            ->timeout(20)
            ->retry(2, 300)
            ->get($this->baseUrl . '/agropecuario', [
                'identificacion' => $identificacion,
            ]);

        if ($response->status() === 404) {
            $normalizada = [
                'identificacion' => $identificacion,
                'nombre' => null,
                'estado' => 'no_encontrado',
                'vigente' => false,
                'respuesta' => null,
            ];
        } elseif ($response->status() === 429) {
            throw new Exception('Hacienda limitó temporalmente las consultas. Intente nuevamente más tarde.');
        } elseif (!$response->successful()) {
            throw new Exception('No se pudo consultar la condición agropecuaria.');
        } else {
            $raw = $response->json();
            $normalizada = $this->normalizarAgropecuario(is_array($raw) ? $raw : [], $identificacion);
        }

        DB::table('fe_condiciones_agropecuarias')->updateOrInsert(
            [
                'sucursal_id' => $sucursalId,
                'identificacion' => $identificacion,
            ],
            [
                'usuario_id' => $usuarioId,
                'nombre' => $normalizada['nombre'],
                'estado' => $normalizada['estado'],
                'vigente' => $normalizada['vigente'] ? 1 : 0,
                'respuesta_json' => json_encode($normalizada['respuesta'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),
                'consultado_en' => now(),
            ]
        );

        return $normalizada;
    }

    private function normalizarExoneracion(array $raw): array
    {
        $fechaEmision = $raw['fechaEmision'] ?? null;
        $fechaVencimiento = $raw['fechaVencimiento'] ?? null;
        $vigente = $fechaVencimiento ? Carbon::parse($fechaVencimiento)->gte(Carbon::today('America/Costa_Rica')) : false;
        $tipoDocumento = is_array($raw['tipoDocumento'] ?? null) ? $raw['tipoDocumento'] : [];

        return [
            'autorizacion' => strtoupper((string) ($raw['numeroDocumento'] ?? '')),
            'numero_documento' => strtoupper((string) ($raw['numeroDocumento'] ?? '')),
            'identificacion' => (string) ($raw['identificacion'] ?? ''),
            'tipo_autorizacion' => (string) ($raw['tipoAutorizacion'] ?? ''),
            'tipo_documento_ex' => str_pad((string) ($tipoDocumento['codigo'] ?? '04'), 2, '0', STR_PAD_LEFT),
            'tipo_documento_descripcion' => $tipoDocumento['descripcion'] ?? null,
            'codigo_institucion' => (string) ($raw['CodigoInstitucion'] ?? ''),
            'nombre_institucion' => (string) ($raw['nombreInstitucion'] ?? ''),
            'fecha_emision' => $fechaEmision ? Carbon::parse($fechaEmision)->format('Y-m-d H:i:s') : null,
            'fecha_vencimiento' => $fechaVencimiento ? Carbon::parse($fechaVencimiento)->format('Y-m-d H:i:s') : null,
            'tarifa_exonerada' => (float) ($raw['porcentajeExoneracion'] ?? 0),
            'porcentaje_exoneracion' => (float) ($raw['porcentajeExoneracion'] ?? 0),
            'posee_cabys' => (bool) ($raw['poseeCabys'] ?? false),
            'cabys' => is_array($raw['cabys'] ?? null) ? $raw['cabys'] : [],
            'vigente' => $vigente,
            'respuesta' => $raw,
        ];
    }

    private function normalizarAgropecuario(array $raw, string $identificacion): array
    {
        $estado = strtolower((string) ($raw['estado'] ?? $raw['situacion'] ?? $raw['condition'] ?? ''));
        $vigente = in_array($estado, ['activo', 'vigente', 'inscrito', 'a'], true);

        return [
            'identificacion' => $identificacion,
            'nombre' => $raw['nombre'] ?? $raw['nombreProductor'] ?? $raw['razonSocial'] ?? null,
            'estado' => $estado !== '' ? $estado : 'consultado',
            'vigente' => $vigente || $raw !== [],
            'respuesta' => $raw,
        ];
    }
}
