import { writeFileSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import type { PrismaClient } from '../../../src/generated/prisma/client';
import { profileMenuSeeds } from './profile-menu-labels.seed';

type MenuRow = {
  id: number;
  module: string | null;
  translationKey: string;
  englishText: string;
  khmerText: string;
  isActive: boolean;
  updatedAt: Date;
};

// Keep the canonical copy on reruns. During migration prefer Admin-edited
// records over defaults, then the most recently edited record.
export function chooseProfileMenuSource<T extends MenuRow>(rows: T[], key: string): T | undefined {
  const candidates = rows.filter(row => row.translationKey === key);
  const shared = candidates.find(row => row.module === 'shared');
  if (shared) return shared;
  const fallback = profileMenuSeeds().find(row => row.translationKey === key);
  const edited = candidates.filter(row => !fallback ||
    row.englishText !== fallback.englishText || row.khmerText !== fallback.khmerText || !row.isActive);
  return [...(edited.length ? edited : candidates)].sort((a, b) =>
    b.updatedAt.getTime() - a.updatedAt.getTime() || b.id - a.id,
  )[0];
}

export async function mergeProfileMenuTranslations(prisma: PrismaClient) {
  return prisma.$transaction(async (tx) => {
      const rows = await tx.translation.findMany({ where: {
        page: 'profile_menu', module: { in: ['shared', 'pswg', 'ministry', 'cdc', 'cefp', 'cdcgpsf'] },
      } });
      const legacyIds = rows.filter(row => row.module !== 'shared').map(row => row.id);
      if (legacyIds.length) {
        const backup = join(tmpdir(), `gpsf-profile-menu-${Date.now()}.json`);
        writeFileSync(backup, JSON.stringify(rows, null, 2), { flag: 'wx' });
        console.log('Original profile menu backup:', backup);
        const outsideChildren = await tx.translation.count({ where: {
          parentId: { in: legacyIds }, id: { notIn: rows.map(row => row.id) },
        } });
        if (outsideChildren) throw new Error('Other pages reference these profile menu rows; migration stopped.');
      }

      const defaults = profileMenuSeeds();
      const keys = [...new Set([...defaults.map(row => row.translationKey), ...rows.map(row => row.translationKey)])];
      let rootId: number | null = null;
      let created = 0;
      for (const key of keys) {
        const source = chooseProfileMenuSource(rows, key) ?? defaults.find(row => row.translationKey === key)!;
        const existing = rows.find(row => row.module === 'shared' && row.translationKey === key);
        const parentId = key === 'page_title' ? null : rootId;
        const canonical = existing
          ? existing.parentId === parentId ? existing
            : await tx.translation.update({ where: { id: existing.id }, data: { parentId } })
          : await tx.translation.create({ data: {
              module: 'shared', page: 'profile_menu', translationKey: key, parentId,
              englishText: source.englishText, khmerText: source.khmerText, isActive: source.isActive,
            } });
        if (!existing) created += 1;
        if (key === 'page_title') rootId = canonical.id;
      }
      await tx.translation.deleteMany({ where: { id: { in: legacyIds } } });
      console.log(`Profile Menu: ${keys.length} shared records; ${legacyIds.length} duplicate module records merged.`);
      return { module: 'shared' as const, total: keys.length, created, kept: keys.length - created };
    }, { timeout: 30000 });
}
