import {
  readFileSync,
  readdirSync,
  statSync
} from 'node:fs';
import { join } from 'node:path';
import {
  describe,
  expect,
  it
} from 'vitest';

import {
  extractTranslationKeysFromSource,
  findMissingCatalogKeys,
  flattenCatalogKeys
} from './app-i18n-catalog.rules';

const APP_ROOT = join(import.meta.dirname, '../../..');
const EN_CATALOG_PATH = join(APP_ROOT, '../public/i18n/en.json');

function listSourceFiles(directory: string): string[] {
  const entries = readdirSync(directory);
  const files: string[] = [];

  for (const entry of entries) {
    const fullPath = join(directory, entry);
    const stats = statSync(fullPath);

    if (stats.isDirectory()) {
      files.push(...listSourceFiles(fullPath));
      continue;
    }

    if (fullPath.endsWith('.html') || (fullPath.endsWith('.ts') && !fullPath.endsWith('.spec.ts'))) {
      files.push(fullPath);
    }
  }

  return files;
}

describe('app-i18n-catalog.rules', () => {
  it('defines every translation key referenced in app templates and instant() calls', () => {
    const catalog = JSON.parse(readFileSync(EN_CATALOG_PATH, 'utf8')) as Record<string, unknown>;
    const definedKeys = flattenCatalogKeys(catalog);
    const usedKeys = new Set<string>();

    for (const filePath of listSourceFiles(join(APP_ROOT, 'app'))) {
      const source = readFileSync(filePath, 'utf8');

      for (const key of extractTranslationKeysFromSource(source)) {
        usedKeys.add(key);
      }
    }

    const missingKeys = findMissingCatalogKeys(definedKeys, usedKeys);

    expect(missingKeys, `Missing i18n keys: ${missingKeys.join(', ')}`).toEqual([]);
  });

  it('nests extracted theme registry labels under theme.registry', () => {
    const catalog = JSON.parse(readFileSync(EN_CATALOG_PATH, 'utf8')) as Record<string, unknown>;
    const theme = catalog['theme'] as Record<string, unknown> | undefined;
    const registry = theme?.['registry'] as Record<string, { label?: string }> | undefined;

    expect(theme?.['registry']).toBeDefined();
    expect(catalog['theme.registry']).toBeUndefined();
    expect(registry?.['appRoot']?.label).toBe('App Root');
    expect(Object.keys(registry ?? {}).length).toBeGreaterThanOrEqual(60);
  });
});
