import assert from 'node:assert/strict';
import fs from 'node:fs';
import path from 'node:path';
import test from 'node:test';
import { fileURLToPath } from 'node:url';

const here = path.dirname(fileURLToPath(import.meta.url));
const rendererRoot = path.resolve(here, '../..');

const SECONDARY_WINDOW_MAINS = [
  'editor/main.tsx',
  'npcs/npcsEditorMain.tsx',
  'npcs/npcsMain.tsx',
  'materials/main.tsx',
  'sceneEditor/main.tsx',
  'sceneDescription/main.tsx',
  'control/main.tsx',
  'presentation/main.tsx',
] as const;

void test('secondary window mains: WindowErrorBoundary wraps app root', () => {
  for (const rel of SECONDARY_WINDOW_MAINS) {
    const src = fs.readFileSync(path.join(rendererRoot, rel), 'utf8');
    assert.ok(
      src.includes('WindowErrorBoundary'),
      `${rel}: must wrap with WindowErrorBoundary to avoid black screen on React crash`,
    );
    assert.match(
      src,
      /<WindowErrorBoundary[\s\S]*?>[\s\S]*<\/WindowErrorBoundary>/,
      `${rel}: WindowErrorBoundary must wrap children`,
    );
  }
});

void test('NpcDescriptionField: TipTap StrictMode-safe (no black screen on NPC open)', () => {
  const src = fs.readFileSync(path.join(rendererRoot, 'npcs/NpcDescriptionField.tsx'), 'utf8');
  assert.match(src, /immediatelyRender:\s*false/);
  assert.ok(src.includes('readTipTapHtmlSafe'));
  assert.ok(src.includes('isDestroyed'));
  assert.doesNotMatch(src, /immediatelyRender:\s*true/);
});

void test('NpcsEditorApp: no undefined controlStyles (inspector crash)', () => {
  const src = fs.readFileSync(path.join(rendererRoot, 'npcs/NpcsEditorApp.tsx'), 'utf8');
  assert.doesNotMatch(src, /controlStyles/);
});

void test('NPC binding removed from editor UI', () => {
  const editor = fs.readFileSync(path.join(rendererRoot, 'npcs/NpcsEditorApp.tsx'), 'utf8');
  const modal = fs.readFileSync(path.join(rendererRoot, 'npcs/NpcEditModal.tsx'), 'utf8');
  assert.doesNotMatch(editor, /NpcBindingFields|binding/);
  assert.doesNotMatch(modal, /NpcBindingFields|binding|noneBinding/);
  assert.ok(!fs.existsSync(path.join(rendererRoot, 'npcs/NpcBindingFields.tsx')));
  assert.ok(!fs.existsSync(path.join(rendererRoot, '../shared/npcs/npcBinding.ts')));
});

void test('storyline export modal: NPC selection step', () => {
  const src = fs.readFileSync(path.join(rendererRoot, 'editor/StorylineTransferModals.tsx'), 'utf8');
  assert.match(src, /step === 'npcs'/);
  assert.match(src, /export\.selectAllNpcs/);
  assert.match(src, /npcIds/);
  assert.match(src, /Array\.isArray\(res\?\.npcs\)/);
  assert.doesNotMatch(src, /filterNpcsForStorylineExport/);
});

void test('WindowErrorBoundary component exists and catches errors', () => {
  const src = fs.readFileSync(path.join(here, 'WindowErrorBoundary.tsx'), 'utf8');
  assert.ok(src.includes('getDerivedStateFromError'));
  assert.ok(src.includes('componentDidCatch'));
  assert.ok(src.includes('role="alert"'));
});
