<?php
declare(strict_types=1);

namespace Celena\Plugin\Analytics\Support;

use Celena\Plugin\Analytics\Mmdb\Reader;

/**
 * Резолв город + координаты по IP из локальной mmdb-базы (DB-IP City Lite, CC-BY).
 * Файл базы — storage/analytics/dbip-city.mmdb (грузится импортёром, НЕ в дистрибутиве).
 * Нет файла → null (всё деградирует к стране). IP нигде не сохраняется.
 *
 * Поддерживает IPv4 и IPv6 (в отличие от cl_geo_ip4, который только IPv4).
 */
final class GeoCity
{
    private static ?Reader $reader = null;
    private static bool $tried = false;

    /** Путь к mmdb-базе (storage/analytics/ в корне сайта). */
    public static function dbPath(): string
    {
        return dirname(__DIR__, 4) . '/storage/analytics/dbip-city.mmdb';
    }

    public static function available(): bool
    {
        return is_file(self::dbPath());
    }

    private static function reader(): ?Reader
    {
        if (!self::$tried) {
            self::$tried = true;
            try {
                if (self::available()) {
                    self::$reader = new Reader(self::dbPath());
                }
            } catch (\Throwable) {
                self::$reader = null;
            }
        }
        return self::$reader;
    }

    /**
     * @return array{cc:?string,city:?string,lat:?float,lon:?float}|null
     */
    public static function lookup(string $ip): ?array
    {
        if ($ip === '') {
            return null;
        }
        $r = self::reader();
        if ($r === null) {
            return null;
        }
        try {
            $rec = $r->get($ip);
        } catch (\Throwable) {
            return null;
        }
        if (!is_array($rec)) {
            return null;
        }

        $cc = $rec['country']['iso_code'] ?? null;
        $cc = is_string($cc) && preg_match('/^[A-Za-z]{2}$/', $cc) ? strtoupper($cc) : null;

        $names = $rec['city']['names'] ?? [];
        $city = null;
        if (is_array($names) && $names !== []) {
            $city = $names['ru'] ?? $names['en'] ?? reset($names);
        }
        $city = is_string($city) && $city !== '' ? mb_substr(trim($city), 0, 120) : null;

        $lat = isset($rec['location']['latitude'])  ? (float) $rec['location']['latitude']  : null;
        $lon = isset($rec['location']['longitude']) ? (float) $rec['location']['longitude'] : null;
        if ($lat !== null && ($lat < -90 || $lat > 90)) $lat = null;
        if ($lon !== null && ($lon < -180 || $lon > 180)) $lon = null;

        return ['cc' => $cc, 'city' => $city, 'lat' => $lat, 'lon' => $lon];
    }
}
