import assert from 'node:assert/strict';
import { test } from 'node:test';
import {
  PSWG_TRANSLATIONS,
  MINISTRY_TRANSLATIONS,
  CDCGPSF_TRANSLATIONS,
  seedTranslationItems,
} from './index';
import {
  reportSeedPage,
  selectReportSeeds,
} from './progress-report-labels.seed';
import {
  reportDefaults,
  reportPage,
  reportTranslationKey,
  resolveReportLabels,
  fetchReportDictionary,
} from '../../../../frontend/features/pswg/progress-report/progress-report-translations';
import { buildPswgIssuesPrintModel } from '../../../../frontend/features/pswg/progress-report/components/progress-report-view-details/sections/pswg-issues-print-model';
import { progressReportText } from '../../../../frontend/features/cdc-gpsf/progress-report/progress-report-i18n';
import { cdcGpsfReportFunctionPlaceholder, resolveCdcGpsfProgressReportLabels } from '../../../../frontend/features/cdc-gpsf/progress-report/progress-report-labels';
const modules = [
  ['pswg', PSWG_TRANSLATIONS],
  ['ministry', MINISTRY_TRANSLATIONS],
  ['cdcgpsf', CDCGPSF_TRANSLATIONS],
] as const;
function flat(value: object, prefix = ''): Record<string, string> {
  return Object.assign(
    {},
    ...Object.entries(value).map(([key, v]) => {
      const path = prefix ? prefix + '.' + key : key;
      return typeof v === 'string' ? { [path]: v } : flat(v, path);
    }),
  );
}
test('all PSWG and imported shared UI labels have matching bilingual seeds per module', () => {
  const en = flat(reportDefaults('en')),
    kh = flat(reportDefaults('kh'));
  assert.deepEqual(Object.keys(en), Object.keys(kh));
  assert.equal(
    new Set(Object.keys(en).map(reportTranslationKey)).size,
    Object.keys(en).length,
  );
  for (const [owner, items] of modules) {
    assert.equal(reportPage(owner), reportSeedPage(owner));
    const page = items.filter((item) => item.page === reportPage(owner));
    assert.equal(
      new Set(page.map((item) => item.translationKey)).size,
      page.length,
    );
    for (const path of Object.keys(en)) {
      const row = page.find(
        (item) => item.translationKey === reportTranslationKey(path),
      );
      assert.ok(row, owner + '/' + path);
      assert.equal(row.englishText, en[path]);
      assert.equal(row.khmerText, kh[path]);
    }
  }
});
test('Admin overrides every nested label, sidebar stays independent and print uses API labels', () => {
  for (const lang of ['en', 'kh']) {
    const defaults = reportDefaults(lang);
    const dictionary = Object.fromEntries(
      Object.keys(flat(defaults)).map((path) => [
        reportTranslationKey(path),
        'Admin:' + path,
      ]),
    );
    const labels = resolveReportLabels(defaults, dictionary, '');
    for (const [path, value] of Object.entries(flat(labels)))
      assert.equal(value, 'Admin:' + path);
    assert.equal(
      resolveReportLabels(
        defaults,
        { title: 'Sidebar', page_title: 'Heading' },
        '',
      ).pswg.pageTitle,
      'Heading',
    );
    assert.equal(
      resolveReportLabels(defaults, { page_title: ' ' }, '').pswg.pageTitle,
      defaults.pswg.pageTitle,
    );
    const model = buildPswgIssuesPrintModel([], labels, lang);
    assert.equal(model.reportTitle, 'Admin:printModel.title');
    assert.equal(model.privateSectorName, 'Admin:printModel.privateSector');
  }
});
test('dictionary API uses correct owning module/page and Khmer language', async () => {
  const original = globalThis.fetch;
  try {
    for (const [owner] of modules) {
      globalThis.fetch = async (input, init) => {
        const url = new URL(String(input));
        assert.equal(url.searchParams.get('module'), owner);
        assert.equal(url.searchParams.get('page'), reportPage(owner));
        assert.equal(url.searchParams.get('language'), 'km');
        assert.equal(init?.cache, 'no-store');
        return Response.json({
          data: { translations: { page_title: owner, empty: ' ', invalid: 1 } },
        });
      };
      assert.deepEqual(await fetchReportDictionary(owner, 'kh'), {
        page_title: owner,
      });
    }
  } finally {
    globalThis.fetch = original;
  }
});

test('CDC-GPSF report UI labels are seeded and Admin overrides reach nested dialogs', () => {
  const rows = CDCGPSF_TRANSLATIONS.filter((item) => item.page === 'progress_reports');
  const byKey = new Map(rows.map((row) => [row.translationKey, row]));
  const en = flat(progressReportText.en);
  const kh = flat(progressReportText.kh);
  assert.deepEqual(Object.keys(en), Object.keys(kh));
  for (const [path, englishText] of Object.entries(en)) {
    const key = reportTranslationKey('table.' + path);
    const row = byKey.get(key);
    assert.ok(row, key);
    assert.equal(row.englishText, englishText, key);
    assert.equal(row.khmerText, kh[path], key);
  }
  for (const [path, placeholder] of Object.entries(cdcGpsfReportFunctionPlaceholder)) {
    const row = byKey.get(reportTranslationKey('table.' + path));
    assert.ok(row, path);
    assert.ok(row.englishText.includes(`{${placeholder}}`));
    assert.ok(row.khmerText.includes(`{${placeholder}}`));
  }
  const labels = resolveCdcGpsfProgressReportLabels(progressReportText.kh, {
    'table.create_dialog.title': 'Admin dialog',
    'table.detail.page_title': 'Admin detail heading',
    'table.actions_menu.view_detail': 'Admin view detail',
    'table.detail.columns.name': 'Admin name',
    'table.draft_dashboard.title': 'Admin {semester}',
  });
  assert.equal(labels.detail.columns.name, 'Admin name');
  assert.equal(labels.createDialog.title, 'Admin dialog');
  assert.equal(labels.detail.pageTitle, 'Admin detail heading');
  assert.equal(labels.actionsMenu.viewDetail, 'Admin view detail');
  assert.equal(typeof labels.detail.statusChangeActions.issueSuccess, 'function');
  assert.equal(labels.draftDashboard.title('S1'), 'Admin S1');
});
test('seed remains create-only and resolves parents before child labels', async () => {
  const rows = new Map<string, { id: number; englishText: string }>();
  const db = {
    translation: {
      async findUnique(args: any) {
        return (
          rows.get(JSON.stringify(args.where.module_page_translationKey)) ??
          null
        );
      },
      async create(args: any) {
        if (args.data.parentId !== null)
          assert.ok(
            [...rows.values()].some((r) => r.id === args.data.parentId),
          );
        const { module, page, translationKey } = args.data;
        const row = { id: rows.size + 1, englishText: args.data.englishText };
        rows.set(JSON.stringify({ module, page, translationKey }), row);
        return row;
      },
    },
  };
  for (const [owner, items] of modules) {
    const scoped = selectReportSeeds(owner, items);
    await seedTranslationItems(db, owner, scoped);
    const key = JSON.stringify({
      module: owner,
      page: reportPage(owner),
      translationKey: 'page_title',
    });
    rows.get(key)!.englishText = 'Admin edit';
    assert.equal((await seedTranslationItems(db, owner, scoped)).created, 0);
    assert.equal(rows.get(key)!.englishText, 'Admin edit');
  }
});
