<?php

declare(strict_types=1);

namespace SeoScope\i18n;

final class Translator
{
    /** @var array<string, string> */
    private array $fallback = [];

    /** @var array<string, string> */
    private array $primary = [];

    public function __construct(
        private string $localeCode,
        string $langDir
    ) {
        $enFile = $langDir . '/en/messages.php';
        if (is_readable($enFile)) {
            $data = require $enFile;
            $this->fallback = is_array($data) ? $data : [];
        }

        if ($this->localeCode !== 'en') {
            $locFile = $langDir . '/' . $this->localeCode . '/messages.php';
            if (is_readable($locFile)) {
                $data = require $locFile;
                $this->primary = is_array($data) ? $data : [];
            }
            // User-added translations in storage/lang/{code}.json overlay file-based locale.
            $customJson = $this->customJsonPath($this->localeCode);
            if ($customJson !== null && is_readable($customJson)) {
                $json = @file_get_contents($customJson);
                if (is_string($json) && $json !== '') {
                    $decoded = json_decode($json, true);
                    if (is_array($decoded)) {
                        $overlay = [];
                        foreach ($decoded as $k => $v) {
                            if (!is_string($k) || !is_string($v)) {
                                continue;
                            }
                            $overlay[$k] = $v;
                        }
                        if ($overlay !== []) {
                            $this->primary = array_merge($this->primary, $overlay);
                        }
                    }
                }
            }
        }
    }

    public function getLocale(): string
    {
        return $this->localeCode;
    }

    /**
     * @param array<string, string|int|float> $params Placeholders :key in the string
     */
    public function get(string $key, array $params = []): string
    {
        $raw = $this->primary[$key] ?? $this->fallback[$key] ?? null;
        if ($raw === null || $raw === '') {
            $this->logMissingKey($key);
            return $key;
        }
        foreach ($params as $name => $value) {
            $raw = str_replace(':' . $name, (string) $value, $raw);
        }
        return $raw;
    }

    private function logMissingKey(string $key): void
    {
        if (!defined('SEOSCOPE_ROOT')) {
            return;
        }
        $logDir = SEOSCOPE_ROOT . '/storage/logs';
        if (!is_dir($logDir) || !is_writable($logDir)) {
            return;
        }
        $line = date('c') . " i18n missing key: {$key}\n";
        @file_put_contents($logDir . '/i18n.log', $line, FILE_APPEND);
    }

    private function customJsonPath(string $localeCode): ?string
    {
        if (!defined('SEOSCOPE_ROOT')) {
            return null;
        }
        // Keep locale code canonical (Translator only gets SupportedLocales-normalized codes).
        return SEOSCOPE_ROOT . '/storage/lang/' . $localeCode . '.json';
    }
}
