const { test } = require('node:test');
const assert = require('node:assert/strict');
const fs = require('node:fs');
const path = require('node:path');

const root = path.join(__dirname, '..');

function read(relativePath) {
  return fs.readFileSync(path.join(root, relativePath), 'utf8');
}

test('AI memory context is limited to saved template categories', () => {
  const route = read('src/routes/memories.js');
  assert.match(route, /var AI_CONTEXT_CATEGORIES = \[/);
  assert.match(route, /'physical_exam'/);
  assert.match(route, /'template_ed'/);
  assert.match(route, /rows = rows\.filter\(function\(r\) \{ return AI_CONTEXT_CATEGORIES\.indexOf\(r\.category\) !== -1; \}\)/);
  assert.doesNotMatch(route.match(/var AI_CONTEXT_CATEGORIES = \[[\s\S]*?\];/)[0], /'custom'/);
});

test('template settings do not offer new custom AI memories', () => {
  const settings = read('public/components/settings.html');
  const memories = read('public/js/memories.js');
  assert.doesNotMatch(settings, /<option value="custom">/);
  assert.match(settings, /Only template categories are sent to AI/);
  assert.match(memories, /custom: 'Custom \(not used by AI\)'/);
  assert.match(memories, /window\.getUserMemoryContext = function\(\)/);
});

test('note refine corrections still call AI without storing learning memories', () => {
  const app = read('public/js/app.js');
  const refine = read('src/routes/refine.js');
  assert.match(app, /function refineDocument\(outputElementId, inputElementId\)/);
  assert.match(app, /fetch\('\/api\/refine'/);
  assert.match(app, /currentDocument: docText, instructions: instructions/);
  assert.match(refine, /router\.post\('\/refine'/);
  assert.match(refine, /PROMPTS\.refine \+ INJECTION_GUARD/);
  assert.match(refine, /sourceContext/);
  assert.doesNotMatch(refine, /INSERT INTO user_memories|correction_/);
});

test('browser Whisper is removed from public runtime and user settings', () => {
  assert.equal(fs.existsSync(path.join(root, 'public/js/browserWhisper.js')), false);
  assert.equal(fs.existsSync(path.join(root, 'public/js/whisperWorker.js')), false);
  assert.equal(fs.existsSync(path.join(root, 'public/js/whisperWorkerV2.js')), false);
  assert.equal(fs.existsSync(path.join(root, 'docs/browser-whisper-setup.md')), false);
  assert.equal(fs.existsSync(path.join(root, 'docs/browser-whisper-troubleshooting.md')), false);
  assert.equal(fs.existsSync(path.join(root, 'scripts/download-whisper-models.sh')), false);
  const publicRuntimeFiles = [
    'public/index.html',
    'public/js/app.js',
    'public/js/transcriptionSettings.js',
    'public/components/settings.html',
    'public/components/faq.html'
  ];
  publicRuntimeFiles.forEach((file) => {
    assert.doesNotMatch(read(file), /BrowserWhisper|browser-whisper|Browser Whisper|Xenova\/whisper|transformers\.min\.js/, file);
  });
  const dockerfile = read('Dockerfile');
  assert.doesNotMatch(dockerfile, /Xenova\/whisper|transformers\.min\.js|Browser Whisper/);
  const server = read('server.js');
  assert.doesNotMatch(server, /wasm-unsafe-eval|unsafe-eval|huggingface\.co|cdn-lfs|transformers/);
});

test('browser speech recognition is gated by explicit user setting', () => {
  const app = read('public/js/app.js');
  const speechFactory = app.match(/function createSpeechRecognition\(\) \{[\s\S]*?\n\}/)[0];
  assert.match(speechFactory, /window\.WebSpeechRecognition && !window\.WebSpeechRecognition\.isEnabled\(\)/);
});

test('audio backup settings render without dynamic HTML templates', () => {
  const audioBackup = read('public/js/audioBackup.js');
  const renderer = audioBackup.match(/window\.renderAudioBackups = function\(\) \{[\s\S]*?\n  \};/)[0];
  assert.doesNotMatch(renderer, /innerHTML/);
  assert.match(renderer, /document\.createElement\('button'\)/);
  assert.match(renderer, /textContent =/);
});
