import assert from 'node:assert/strict';
import { test } from 'node:test';
import { selectIssueMatrixSeeds } from './issue-matrix-labels.seed';
import {
  PSWG_TRANSLATIONS,
  MINISTRY_TRANSLATIONS,
  CDC_TRANSLATIONS,
  CEFP_TRANSLATIONS,
  CDCGPSF_TRANSLATIONS,
  seedTranslationItems,
  type TranslationSeedModule,
  type TranslationSeedItem,
} from './index';
import {
  issueMatrixDefaults,
  issueMatrixTranslationKey,
  issueMatrixModuleFromPath,
  resolveIssueMatrixLabels,
  fetchIssueMatrixDictionary,
} from '../../../../frontend/features/pswg/issue-matrix/issue-matrix-translations';

const modules: Array<[TranslationSeedModule, TranslationSeedItem[]]> = [
  ['pswg', PSWG_TRANSLATIONS],
  ['ministry', MINISTRY_TRANSLATIONS],
  ['cdc', CDC_TRANSLATIONS],
  ['cefp', CEFP_TRANSLATIONS],
  ['cdcgpsf', CDCGPSF_TRANSLATIONS],
];
function flatten(value: object, prefix = ''): Record<string, string> {
  return Object.assign(
    {},
    ...Object.entries(value).map(([key, entry]) => {
      const path = prefix ? prefix + '.' + key : key;
      return typeof entry === 'string'
        ? { [path]: entry }
        : flatten(entry, path);
    }),
  );
}
test('all shared Issue Matrix UI labels have unique bilingual seeds in all five modules', () => {
  const en = flatten(issueMatrixDefaults('en')),
    kh = flatten(issueMatrixDefaults('kh'));
  assert.deepEqual(Object.keys(en).sort(), Object.keys(kh).sort());
  const keys = Object.keys(en).map(issueMatrixTranslationKey);
  assert.equal(new Set(keys).size, keys.length);
  for (const [module, all] of modules) {
    const items = all.filter((item) => item.page === 'issue_matrix');
    assert.equal(
      new Set(items.map((item) => item.translationKey)).size,
      items.length,
    );
    for (const key of keys) {
      const seed = items.find((item) => item.translationKey === key);
      assert.ok(seed, module + '/' + key);
      assert.equal(seed.module, module);
      assert.ok(seed.englishText.trim());
      assert.ok(seed.khmerText.trim());
      assert.equal(seed.isActive, true);
    }
  }
});
test('module is resolved from the route, never from the shared file location', () => {
  for (const [module] of modules) {
    const route = module === 'cdcgpsf' ? 'cdc-gpsf' : module;
    assert.equal(
      issueMatrixModuleFromPath('/' + route + '/issue-matrix/12'),
      module,
    );
  }
  assert.equal(issueMatrixModuleFromPath('/admin/issues-management/12'), null);
  assert.equal(issueMatrixModuleFromPath('/cdc-other/issue-matrix'), null);
});
test('sidebar cannot rename page heading; missing labels remain local defaults', () => {
  const before = JSON.stringify(issueMatrixDefaults('kh'));
  const text = resolveIssueMatrixLabels('kh', {
    title: 'Sidebar',
    page_title: 'Heading',
    no_data: ' ',
    unknown: 'Ignored',
  });
  assert.equal(text.title, 'Heading');
  assert.equal(text.noData, issueMatrixDefaults('kh').noData);
  assert.equal('unknown' in text, false);
  assert.equal(
    resolveIssueMatrixLabels('en', { title: 'Sidebar' }).title,
    'Issue Matrix',
  );
  assert.equal(JSON.stringify(issueMatrixDefaults('kh')), before);
});
test('Admin dictionary can override every label including shared detail, values, reports and dialog templates', () => {
  for (const lang of ['en', 'kh'] as const) {
    const dictionary = Object.fromEntries(
      Object.keys(flatten(issueMatrixDefaults(lang))).map((path) => [
        issueMatrixTranslationKey(path),
        'Admin:' + path,
      ]),
    );
    const resolved = flatten(resolveIssueMatrixLabels(lang, dictionary));
    for (const path of Object.keys(resolved))
      assert.equal(resolved[path], 'Admin:' + path);
    const dialog = resolveIssueMatrixLabels(lang, {
      'status_change_dialog.description': 'Change to {status}?',
    });
    assert.equal(
      dialog.statusChangeDialog.description.replace('{status}', 'Solved'),
      'Change to Solved?',
    );
  }
});
test('fetch isolates each module/language, forwards abort, and does not cache', async () => {
  const original = globalThis.fetch;
  try {
    for (const [module] of modules)
      for (const language of ['en', 'kh'] as const) {
        const signal = new AbortController().signal;
        globalThis.fetch = async (input, init) => {
          const url = new URL(String(input));
          assert.equal(url.searchParams.get('module'), module);
          assert.equal(url.searchParams.get('page'), 'issue_matrix');
          assert.equal(
            url.searchParams.get('language'),
            language === 'kh' ? 'km' : 'en',
          );
          assert.equal(init?.cache, 'no-store');
          assert.equal(init?.signal, signal);
          return Response.json({
            data: {
              data: {
                translations: {
                  page_title: module + language,
                  no_data: ' ',
                  invalid: 4,
                },
              },
            },
          });
        };
        const dictionary = await fetchIssueMatrixDictionary(
          module,
          language,
          signal,
        );
        assert.deepEqual(dictionary, { page_title: module + language });
        assert.equal(
          resolveIssueMatrixLabels(language, dictionary).title,
          module + language,
        );
      }
    globalThis.fetch = async () => new Response('', { status: 503 });
    await assert.rejects(fetchIssueMatrixDictionary('pswg', 'en'));
  } finally {
    globalThis.fetch = original;
  }
});
test('repeat seeds preserve existing Admin values and keep modules separate', async () => {
  const rows = new Map<string, { id: number; englishText: string }>();
  rows.set('pswg/title', { id: 1, englishText: 'Admin sidebar' });
  const database = {
    translation: {
      findUnique: async ({
        where,
      }: {
        where: {
          module_page_translationKey: {
            module: string;
            translationKey: string;
          };
        };
      }) => {
        const key = where.module_page_translationKey;
        return rows.get(key.module + '/' + key.translationKey) ?? null;
      },
      create: async ({
        data,
      }: {
        data: { module: string; translationKey: string; englishText: string };
      }) => {
        const row = { id: rows.size + 1, englishText: data.englishText };
        rows.set(data.module + '/' + data.translationKey, row);
        return row;
      },
    },
  };
  for (const [module, all] of modules) {
    const items = all.filter((item) => item.page === 'issue_matrix');
    await seedTranslationItems(database, module, selectIssueMatrixSeeds(all));
    const result = await seedTranslationItems(database, module, items);
    assert.equal(result.created, 0);
    assert.equal(result.kept, items.length);
  }
  assert.equal(rows.get('pswg/title')?.englishText, 'Admin sidebar');
});
