<?php
declare(strict_types=1);

namespace Celena\Plugin\Analytics\Support;

use Celena\Core\Database\Connection;

/**
 * ISO 3166-1 alpha-2 → русское название страны (+ резолв страны по IP из локальной
 * базы cl_geo_ip4). Без флагов-эмодзи.
 */
final class Geo
{
    /**
     * Определить страну по IPv4 через локальную базу диапазонов (DB-IP Lite).
     * Возвращает 2-буквенный код или null. IP нигде не сохраняется.
     */
    public static function lookup(Connection $conn, string $ip): ?string
    {
        if ($ip === '' || str_contains($ip, ':')) {
            return null; // только IPv4
        }
        $long = ip2long($ip);
        if ($long === false) {
            return null;
        }
        $u = (int) sprintf('%u', $long); // беззнаковое представление
        try {
            $T = $conn->table('geo_ip4');
            $row = $conn->run(
                "SELECT cc, end_int FROM $T WHERE start_int <= ? ORDER BY start_int DESC LIMIT 1",
                [$u]
            )->fetch();
        } catch (\Throwable) {
            return null;
        }
        if (!$row || (int) ($row['end_int'] ?? 0) < $u) {
            return null;
        }
        $cc = strtoupper(trim((string) ($row['cc'] ?? '')));
        return preg_match('/^[A-Z]{2}$/', $cc) && $cc !== 'ZZ' ? $cc : null;
    }

    /** Полный список ISO 3166-1 alpha-2 → русское название (чтобы на карте/в списках никогда не светились голые коды). */
    private const NAMES = [
        'AD' => 'Андорра', 'AE' => 'ОАЭ', 'AF' => 'Афганистан', 'AG' => 'Антигуа и Барбуда',
        'AI' => 'Ангилья', 'AL' => 'Албания', 'AM' => 'Армения', 'AO' => 'Ангола',
        'AQ' => 'Антарктида', 'AR' => 'Аргентина', 'AS' => 'Американское Самоа', 'AT' => 'Австрия',
        'AU' => 'Австралия', 'AW' => 'Аруба', 'AX' => 'Аландские острова', 'AZ' => 'Азербайджан',
        'BA' => 'Босния и Герцеговина', 'BB' => 'Барбадос', 'BD' => 'Бангладеш', 'BE' => 'Бельгия',
        'BF' => 'Буркина-Фасо', 'BG' => 'Болгария', 'BH' => 'Бахрейн', 'BI' => 'Бурунди',
        'BJ' => 'Бенин', 'BL' => 'Сен-Бартелеми', 'BM' => 'Бермуды', 'BN' => 'Бруней',
        'BO' => 'Боливия', 'BQ' => 'Бонайре, Синт-Эстатиус и Саба', 'BR' => 'Бразилия', 'BS' => 'Багамы',
        'BT' => 'Бутан', 'BV' => 'Остров Буве', 'BW' => 'Ботсвана', 'BY' => 'Беларусь',
        'BZ' => 'Белиз', 'CA' => 'Канада', 'CC' => 'Кокосовые острова', 'CD' => 'ДР Конго',
        'CF' => 'ЦАР', 'CG' => 'Конго', 'CH' => 'Швейцария', 'CI' => 'Кот-д’Ивуар',
        'CK' => 'Острова Кука', 'CL' => 'Чили', 'CM' => 'Камерун', 'CN' => 'Китай',
        'CO' => 'Колумбия', 'CR' => 'Коста-Рика', 'CU' => 'Куба', 'CV' => 'Кабо-Верде',
        'CW' => 'Кюрасао', 'CX' => 'Остров Рождества', 'CY' => 'Кипр', 'CZ' => 'Чехия',
        'DE' => 'Германия', 'DJ' => 'Джибути', 'DK' => 'Дания', 'DM' => 'Доминика',
        'DO' => 'Доминиканская Республика', 'DZ' => 'Алжир', 'EC' => 'Эквадор', 'EE' => 'Эстония',
        'EG' => 'Египет', 'EH' => 'Западная Сахара', 'ER' => 'Эритрея', 'ES' => 'Испания',
        'ET' => 'Эфиопия', 'FI' => 'Финляндия', 'FJ' => 'Фиджи', 'FK' => 'Фолклендские острова',
        'FM' => 'Микронезия', 'FO' => 'Фарерские острова', 'FR' => 'Франция', 'GA' => 'Габон',
        'GB' => 'Великобритания', 'GD' => 'Гренада', 'GE' => 'Грузия', 'GF' => 'Французская Гвиана',
        'GG' => 'Гернси', 'GH' => 'Гана', 'GI' => 'Гибралтар', 'GL' => 'Гренландия',
        'GM' => 'Гамбия', 'GN' => 'Гвинея', 'GP' => 'Гваделупа', 'GQ' => 'Экваториальная Гвинея',
        'GR' => 'Греция', 'GT' => 'Гватемала', 'GU' => 'Гуам', 'GW' => 'Гвинея-Бисау',
        'GY' => 'Гайана', 'HK' => 'Гонконг', 'HN' => 'Гондурас', 'HR' => 'Хорватия',
        'HT' => 'Гаити', 'HU' => 'Венгрия', 'ID' => 'Индонезия', 'IE' => 'Ирландия',
        'IL' => 'Израиль', 'IM' => 'Остров Мэн', 'IN' => 'Индия', 'IO' => 'Британская территория в Индийском океане',
        'IQ' => 'Ирак', 'IR' => 'Иран', 'IS' => 'Исландия', 'IT' => 'Италия',
        'JE' => 'Джерси', 'JM' => 'Ямайка', 'JO' => 'Иордания', 'JP' => 'Япония',
        'KE' => 'Кения', 'KG' => 'Киргизия', 'KH' => 'Камбоджа', 'KI' => 'Кирибати',
        'KM' => 'Коморы', 'KN' => 'Сент-Китс и Невис', 'KP' => 'КНДР', 'KR' => 'Южная Корея',
        'KW' => 'Кувейт', 'KY' => 'Каймановы острова', 'KZ' => 'Казахстан', 'LA' => 'Лаос',
        'LB' => 'Ливан', 'LC' => 'Сент-Люсия', 'LI' => 'Лихтенштейн', 'LK' => 'Шри-Ланка',
        'LR' => 'Либерия', 'LS' => 'Лесото', 'LT' => 'Литва', 'LU' => 'Люксембург',
        'LV' => 'Латвия', 'LY' => 'Ливия', 'MA' => 'Марокко', 'MC' => 'Монако',
        'MD' => 'Молдова', 'ME' => 'Черногория', 'MF' => 'Сен-Мартен', 'MG' => 'Мадагаскар',
        'MH' => 'Маршалловы Острова', 'MK' => 'Северная Македония', 'ML' => 'Мали', 'MM' => 'Мьянма',
        'MN' => 'Монголия', 'MO' => 'Макао', 'MP' => 'Северные Марианские острова', 'MQ' => 'Мартиника',
        'MR' => 'Мавритания', 'MS' => 'Монтсеррат', 'MT' => 'Мальта', 'MU' => 'Маврикий',
        'MV' => 'Мальдивы', 'MW' => 'Малави', 'MX' => 'Мексика', 'MY' => 'Малайзия',
        'MZ' => 'Мозамбик', 'NA' => 'Намибия', 'NC' => 'Новая Каледония', 'NE' => 'Нигер',
        'NF' => 'Остров Норфолк', 'NG' => 'Нигерия', 'NI' => 'Никарагуа', 'NL' => 'Нидерланды',
        'NO' => 'Норвегия', 'NP' => 'Непал', 'NR' => 'Науру', 'NU' => 'Ниуэ',
        'NZ' => 'Новая Зеландия', 'OM' => 'Оман', 'PA' => 'Панама', 'PE' => 'Перу',
        'PF' => 'Французская Полинезия', 'PG' => 'Папуа — Новая Гвинея', 'PH' => 'Филиппины', 'PK' => 'Пакистан',
        'PL' => 'Польша', 'PM' => 'Сен-Пьер и Микелон', 'PN' => 'Острова Питкэрн', 'PR' => 'Пуэрто-Рико',
        'PS' => 'Палестина', 'PT' => 'Португалия', 'PW' => 'Палау', 'PY' => 'Парагвай',
        'QA' => 'Катар', 'RE' => 'Реюньон', 'RO' => 'Румыния', 'RS' => 'Сербия',
        'RU' => 'Россия', 'RW' => 'Руанда', 'SA' => 'Саудовская Аравия', 'SB' => 'Соломоновы Острова',
        'SC' => 'Сейшелы', 'SD' => 'Судан', 'SE' => 'Швеция', 'SG' => 'Сингапур',
        'SH' => 'Остров Святой Елены', 'SI' => 'Словения', 'SJ' => 'Шпицберген и Ян-Майен', 'SK' => 'Словакия',
        'SL' => 'Сьерра-Леоне', 'SM' => 'Сан-Марино', 'SN' => 'Сенегал', 'SO' => 'Сомали',
        'SR' => 'Суринам', 'SS' => 'Южный Судан', 'ST' => 'Сан-Томе и Принсипи', 'SV' => 'Сальвадор',
        'SX' => 'Синт-Мартен', 'SY' => 'Сирия', 'SZ' => 'Эсватини', 'TC' => 'Острова Теркс и Кайкос',
        'TD' => 'Чад', 'TF' => 'Французские Южные территории', 'TG' => 'Того', 'TH' => 'Таиланд',
        'TJ' => 'Таджикистан', 'TK' => 'Токелау', 'TL' => 'Восточный Тимор', 'TM' => 'Туркмения',
        'TN' => 'Тунис', 'TO' => 'Тонга', 'TR' => 'Турция', 'TT' => 'Тринидад и Тобаго',
        'TV' => 'Тувалу', 'TW' => 'Тайвань', 'TZ' => 'Танзания', 'UA' => 'Украина',
        'UG' => 'Уганда', 'UM' => 'Внешние малые острова США', 'US' => 'США', 'UY' => 'Уругвай',
        'UZ' => 'Узбекистан', 'VA' => 'Ватикан', 'VC' => 'Сент-Винсент и Гренадины', 'VE' => 'Венесуэла',
        'VG' => 'Британские Виргинские острова', 'VI' => 'Американские Виргинские острова', 'VN' => 'Вьетнам', 'VU' => 'Вануату',
        'WF' => 'Уоллис и Футуна', 'WS' => 'Самоа', 'YE' => 'Йемен', 'YT' => 'Майотта',
        'ZA' => 'ЮАР', 'ZM' => 'Замбия', 'ZW' => 'Зимбабве',
    ];

    public static function name(string $code): string
    {
        $code = strtoupper(trim($code));
        return self::NAMES[$code] ?? ($code !== '' ? $code : '—');
    }

    /** Полный словарь cc_low => русское название — для тултипов карты по ВСЕМ странам, не только с трафиком. */
    public static function allNames(): array
    {
        $out = [];
        foreach (self::NAMES as $cc => $name) {
            $out[strtolower($cc)] = $name;
        }
        return $out;
    }

    /** URL локального SVG-флага страны (flag-icons, без внешних запросов). '' если код невалиден. */
    public static function flag(string $code): string
    {
        $c = strtolower(trim($code));
        return preg_match('/^[a-z]{2}$/', $c) ? '/public/assets/analytics/flags/' . $c . '.svg' : '';
    }
}
