import { readFile } from 'node:fs/promises';
import path from 'node:path';
import { fail, pass, repositoryRoot } from './lib.mjs';

function parseCsv(text) {
  const rows = [];
  let row = [];
  let field = '';
  let quoted = false;
  for (let index = 0; index < text.length; index += 1) {
    const character = text[index];
    if (quoted) {
      if (character === '"' && text[index + 1] === '"') {
        field += '"';
        index += 1;
      } else if (character === '"') {
        quoted = false;
      } else {
        field += character;
      }
    } else if (character === '"') {
      quoted = true;
    } else if (character === ',') {
      row.push(field);
      field = '';
    } else if (character === '\n') {
      row.push(field.replace(/\r$/, ''));
      rows.push(row);
      row = [];
      field = '';
    } else {
      field += character;
    }
  }
  if (quoted) throw new Error('Unterminated CSV quote.');
  if (field || row.length) {
    row.push(field.replace(/\r$/, ''));
    rows.push(row);
  }
  return rows;
}

const failures = [];
for (const file of [
  'docs/IMPLEMENTATION_ISSUE_REGISTER_v1.4.csv',
  'docs/quality/PHASE_14_MANUAL_QA_RESULTS_v1.0.csv',
]) {
  const rows = parseCsv(await readFile(path.join(repositoryRoot, file), 'utf8'));
  const expected = rows[0]?.length ?? 0;
  for (const [index, row] of rows.entries()) {
    if (row.length !== expected) {
      failures.push(`${file}:${index + 1} has ${row.length} columns; expected ${expected}.`);
    }
  }
}

const contentType = await readFile(
  path.join(repositoryRoot, 'src/lib/security/content-type.ts'),
  'utf8',
);
const route = await readFile(path.join(repositoryRoot, 'src/app/api/demo/route.ts'), 'utf8');
if (!contentType.includes("=== 'application/json'")) {
  failures.push('Exact JSON media-type comparison is missing.');
}
if (!route.includes('isApplicationJson(contentType)')) {
  failures.push('Demo API does not use the exact JSON media-type helper.');
}
if (route.includes("startsWith('application/json')")) {
  failures.push('Demo API still accepts look-alike JSON media types by prefix.');
}

const componentVisual = await readFile(
  path.join(repositoryRoot, 'tests/visual/component-system.visual.spec.ts'),
  'utf8',
);
const integrationVisual = await readFile(
  path.join(repositoryRoot, 'tests/visual/integrations.visual.spec.ts'),
  'utf8',
);
if (!componentVisual.includes('hpc.theme.preference')) {
  failures.push('Component visual test does not use the canonical theme storage key.');
}
if (componentVisual.includes('rdg-theme-preference')) {
  failures.push('Component visual test still uses the stale theme storage key.');
}
for (const [name, text] of [
  ['component-system.visual.spec.ts', componentVisual],
  ['integrations.visual.spec.ts', integrationVisual],
]) {
  if (!text.includes("project.name !== 'chromium'")) {
    failures.push(`${name} is not restricted to canonical Chromium snapshots.`);
  }
}

const workflow = await readFile(path.join(repositoryRoot, '.github/workflows/ci.yml'), 'utf8');
for (const command of [
  'pnpm test:integration',
  'pnpm test:security',
  'pnpm test:privacy',
  'pnpm test:browser',
  'pnpm test:a11y',
  'pnpm test:visual',
]) {
  if (!workflow.includes(command)) failures.push(`CI omits required command: ${command}`);
}

if (failures.length) fail(failures);
else
  pass(
    'Phase 15 evidence CSVs, exact media-type control, deterministic visual setup, and CI test gates are present.',
  );
