<?php

declare(strict_types=1);

namespace App\Support;

class Countries
{
    public const DEFAULT = 'TM';

    /**
     * @return array<int, string>
     */
    public static function codes(): array
    {
        /** @var array{codes: array<int, string>} $config */
        $config = config('countries');

        return $config['codes'];
    }

    /**
     * @return array<string, string>
     */
    public static function options(?string $locale = null): array
    {
        $locale ??= app()->getLocale();
        $options = [];

        foreach (self::codes() as $code) {
            $name = self::name($code, $locale);

            if ($name !== null) {
                $options[$code] = $name;
            }
        }

        uasort($options, fn (string $a, string $b): int => strcasecmp($a, $b));

        return $options;
    }

    public static function name(?string $code, ?string $locale = null): ?string
    {
        if ($code === null || $code === '') {
            return null;
        }

        $code = strtoupper($code);
        $locale ??= app()->getLocale();

        $name = self::translation($code, $locale);

        if ($name === null && $locale !== 'en') {
            $name = self::translation($code, 'en');
        }

        return $name;
    }

    public static function isValid(?string $code): bool
    {
        if ($code === null || $code === '') {
            return false;
        }

        return in_array(strtoupper($code), self::codes(), true);
    }

    public static function resolve(?string $value, ?string $locale = null): ?string
    {
        if ($value === null || trim($value) === '') {
            return null;
        }

        $value = trim($value);
        $upper = strtoupper($value);

        if (self::isValid($upper)) {
            return $upper;
        }

        $locale ??= app()->getLocale();

        foreach (self::codes() as $code) {
            $name = self::name($code, $locale);

            if ($name !== null && strcasecmp($name, $value) === 0) {
                return $code;
            }
        }

        if ($locale !== 'en') {
            foreach (self::codes() as $code) {
                $name = self::name($code, 'en');

                if ($name !== null && strcasecmp($name, $value) === 0) {
                    return $code;
                }
            }
        }

        return null;
    }

    private static function translation(string $code, string $locale): ?string
    {
        $path = lang_path("{$locale}/countries.php");

        if (! is_file($path)) {
            return null;
        }

        /** @var array<string, string> $names */
        $names = require $path;

        return $names[$code] ?? null;
    }

    public static function default(): string
    {
        return self::DEFAULT;
    }
}
