<?php
namespace App\Services;

class DxccLookupService
{
    private array $dxccData = [];

    public function __construct(string $filePath)
    {
        $this->loadCTY($filePath);
    }

    private function loadCTY(string $path): void
    {
        $lines         = file($path, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
        $inPrefixBlock = false;
        $currentCountry= null;
        $prefixBuffer  = '';

        foreach ($lines as $line) {
            $line = trim($line);
            if ($line === '' || str_starts_with($line, ';')) continue;

            if (!$inPrefixBlock && substr_count($line, ':') >= 7) {
                if ($currentCountry !== null) {
                    $currentCountry['prefixes'] = $this->parsePrefixes($prefixBuffer);
                    $this->dxccData[] = $currentCountry;
                    $prefixBuffer = '';
                }
                $parts = explode(':', $line);
                $currentCountry = [
                    'country'   => trim($parts[0]),
                    'cq_zone'   => trim($parts[1] ?? ''),
                    'itu_zone'  => trim($parts[2] ?? ''),
                    'continent' => trim($parts[3] ?? ''),
                    'latitude'  => trim($parts[4] ?? ''),
                    'longitude' => trim($parts[5] ?? ''),
                    'gmt'       => trim($parts[6] ?? ''),
                    'principal' => trim($parts[7] ?? ''),
                    'prefixes'  => [],
                ];
                $inPrefixBlock = true;
            } elseif ($inPrefixBlock) {
                $prefixBuffer .= ' ' . $line;
                if (str_contains($line, ';')) {
                    $currentCountry['prefixes'] = $this->parsePrefixes($prefixBuffer);
                    $this->dxccData[] = $currentCountry;
                    $inPrefixBlock = false;
                    $prefixBuffer  = '';
                    $currentCountry = null;
                }
            }
        }

        foreach ($this->dxccData as &$entry) {
            usort($entry['prefixes'], fn($a,$b) => strlen($b) - strlen($a));
        }
    }

    private function parsePrefixes(string $buf): array
    {
        $buf = rtrim($buf, ',; ');
        return array_filter(array_map(function($p) {
            $p = preg_replace('/[\(\[].*$/', '', $p);
            return strtoupper(trim($p));
        }, explode(',', $buf)));
    }

    private function matchPrefix(string $callsign, string $prefix): bool
    {
        if (str_starts_with($prefix, '=')) {
            return strcasecmp(substr($prefix, 1), $callsign) === 0;
        }
        if (!str_contains($prefix, '*') && !str_contains($prefix, '/') && $callsign === $prefix) {
            return true;
        }
        if (str_contains($prefix, '*')) {
            return (bool)preg_match('/^'.str_replace('\*','.*',preg_quote($prefix,'/')).'$/i', $callsign);
        }
        if (str_contains($prefix, '/')) {
            return (bool)preg_match('/^'.str_replace('\*','.*',preg_quote($prefix,'/')).'$/i', $callsign);
        }
        return str_starts_with($callsign, $prefix) && strlen($prefix) >= 1;
    }

    public function lookup(string $callsign): ?array
    {
        $callsign = strtoupper(trim($callsign));

        // 1. Match exato (=)
        $best = null; $bestLen = 0;
        foreach ($this->dxccData as $entry) {
            foreach ($entry['prefixes'] as $prefix) {
                if (str_starts_with($prefix,'=') && $this->matchPrefix($callsign,$prefix)) {
                    $len = strlen($callsign);
                    if ($len > $bestLen) { $best = $entry + ['prefix'=>$prefix]; $bestLen = $len; }
                }
            }
        }
        if ($best) return $best;

        // 2. Match por prefixo mais longo
        $bestLen = 0;
        foreach ($this->dxccData as $entry) {
            foreach ($entry['prefixes'] as $prefix) {
                if (!str_starts_with($prefix,'=') && $this->matchPrefix($callsign,$prefix)) {
                    $len = strlen($prefix);
                    if ($len > $bestLen) { $best = $entry + ['prefix'=>$prefix]; $bestLen = $len; }
                }
            }
        }
        return $best;
    }
}
