<?php

namespace MintyPHP\Tests\I18n;

use PHPUnit\Framework\TestCase;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;

class TranslationKeysTest extends TestCase
{
    public function testAllTranslationKeysExistInDefaultLocales(): void
    {
        $root = realpath(__DIR__ . '/../..');
        $this->assertNotFalse($root, 'Project root not found.');

        $paths = [
            $root . '/pages',
            $root . '/templates',
            $root . '/lib',
            $root . '/web/js',
        ];
        $extensions = ['php', 'phtml', 'js'];

        $usedKeys = [];
        foreach ($paths as $path) {
            if (!is_dir($path)) {
                continue;
            }
            $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path));
            foreach ($iterator as $file) {
                if (!$file->isFile()) {
                    continue;
                }
                $ext = strtolower((string) $file->getExtension());
                if (!in_array($ext, $extensions, true)) {
                    continue;
                }
                $content = file_get_contents($file->getPathname());
                if ($content === false || $content === '') {
                    continue;
                }
                foreach ($this->extractTranslationKeys($content) as $key) {
                    $usedKeys[$key] = true;
                }
            }
        }

        $usedKeys = array_keys($usedKeys);
        sort($usedKeys);

        $locales = [
            'default_de.json' => $root . '/i18n/default_de.json',
            'default_en.json' => $root . '/i18n/default_en.json',
        ];
        $translations = [];
        foreach ($locales as $name => $path) {
            $this->assertFileExists($path, 'Missing locale file: ' . $name);
            $raw = file_get_contents($path);
            $this->assertNotFalse($raw, 'Failed to read locale file: ' . $name);
            $json = json_decode($raw, true);
            $this->assertIsArray($json, 'Invalid JSON in locale file: ' . $name);
            $translations[$name] = $json;
        }

        $missing = [];
        foreach ($usedKeys as $key) {
            foreach ($translations as $name => $map) {
                if (!array_key_exists($key, $map)) {
                    $missing[$name][] = $key;
                }
            }
        }

        $messages = [];
        foreach ($missing as $name => $keys) {
            $messages[] = $name . ' missing: ' . implode(', ', $keys);
        }

        $this->assertSame([], $missing, implode(' | ', $messages));
    }

    private function extractTranslationKeys(string $content): array
    {
        $keys = [];
        // Match t('...') with escaped quotes inside, and the same for t("...").
        $patterns = [
            "/\\bt\\s*\\(\\s*'((?:\\\\\\\\.|[^'\\\\\\\\])*)'\\s*\\)/",
            '/\\bt\\s*\\(\\s*"((?:\\\\\\\\.|[^"\\\\\\\\])*)"\\s*\\)/',
        ];

        foreach ($patterns as $pattern) {
            if (!preg_match_all($pattern, $content, $matches)) {
                continue;
            }
            foreach ($matches[1] as $match) {
                $keys[] = stripcslashes($match);
            }
        }

        return $keys;
    }
}
