// tests/i18n/locale-parity.test.ts — Plan 01-12 Wave 0 RED unit test.
//
// Enforces default_locale parity: every key in _locales/ru/messages.json
// must exist in _locales/en/messages.json (the default_locale fallback).
// Symmetric check for cleanliness; non-empty message strings throughout.
//
// Polarity at Wave 0 land: RED across the board (no _locales/ yet).
// Flips GREEN after Wave 3 Task 1 lands both locale files with parity.
//
// References:
//   - RESEARCH Pitfall 4 (missing default_locale key returns empty string,
//     not the key name — silent UI breakage if EN locale lacks a key the
//     RU locale defines).

import { describe, expect, it } from 'vitest';
import { existsSync, readFileSync } from 'node:fs';
import { resolve as resolvePath } from 'node:path';

const EN_LOCALE_PATH = resolvePath(process.cwd(), '_locales/en/messages.json');
const RU_LOCALE_PATH = resolvePath(process.cwd(), '_locales/ru/messages.json');

interface I18nEntry {
  message: string;
  description?: string;
}

type LocaleFile = Record<string, I18nEntry>;

function loadLocale(filePath: string): LocaleFile {
  if (!existsSync(filePath)) {
    throw new Error(`Missing locale file: ${filePath} (RED until Wave 3 Task 1)`);
  }
  return JSON.parse(readFileSync(filePath, 'utf8'));
}

describe('Plan 01-12: _locales/ key parity (default_locale fallback invariant)', () => {
  it('every key in _locales/ru/messages.json exists in _locales/en/messages.json', () => {
    const ru = loadLocale(RU_LOCALE_PATH);
    const en = loadLocale(EN_LOCALE_PATH);
    const ruKeys = Object.keys(ru);
    const missingInEn = ruKeys.filter((k) => !(k in en));
    expect(
      missingInEn,
      missingInEn.length === 0
        ? 'unreachable'
        : `Keys present in ru/ but missing in en/ (silent UI breakage risk):\n  - ${missingInEn.join('\n  - ')}`,
    ).toEqual([]);
  });

  it('every key in _locales/en/messages.json exists in _locales/ru/messages.json (symmetric)', () => {
    const ru = loadLocale(RU_LOCALE_PATH);
    const en = loadLocale(EN_LOCALE_PATH);
    const enKeys = Object.keys(en);
    const missingInRu = enKeys.filter((k) => !(k in ru));
    expect(
      missingInRu,
      missingInRu.length === 0
        ? 'unreachable'
        : `Keys present in en/ but missing in ru/ (cleanliness):\n  - ${missingInRu.join('\n  - ')}`,
    ).toEqual([]);
  });

  it('every key in _locales/en/messages.json has a non-empty .message string', () => {
    const en = loadLocale(EN_LOCALE_PATH);
    for (const k of Object.keys(en)) {
      expect(typeof en[k].message, `en:${k}.message must be a string`).toBe('string');
      expect(en[k].message.length, `en:${k}.message must be non-empty`).toBeGreaterThan(0);
    }
  });

  it('every key in _locales/ru/messages.json has a non-empty .message string', () => {
    const ru = loadLocale(RU_LOCALE_PATH);
    for (const k of Object.keys(ru)) {
      expect(typeof ru[k].message, `ru:${k}.message must be a string`).toBe('string');
      expect(ru[k].message.length, `ru:${k}.message must be non-empty`).toBeGreaterThan(0);
    }
  });
});
