/**
 * CSV File Reference Extraction Test Runner
 *
 * Tests extractCsvRefs() from validate-file-refs.js against fixtures.
 * Verifies correct extraction of workflow-file references from CSV files.
 *
 * Usage: node test/test-file-refs-csv.js
 * Exit codes: 0 = all tests pass, 1 = test failures
 */

const fs = require('node:fs');
const path = require('node:path');
const { extractCsvRefs } = require('../tools/validate-file-refs.js');

// ANSI color codes
const colors = {
  reset: '\u001B[0m',
  green: '\u001B[32m',
  red: '\u001B[31m',
  cyan: '\u001B[36m',
  dim: '\u001B[2m',
};

const FIXTURES = path.join(__dirname, 'fixtures/file-refs-csv');

let totalTests = 0;
let passedTests = 0;
const failures = [];

function test(name, fn) {
  totalTests++;
  try {
    fn();
    passedTests++;
    console.log(`  ${colors.green}\u2713${colors.reset} ${name}`);
  } catch (error) {
    console.log(`  ${colors.red}\u2717${colors.reset} ${name} ${colors.red}${error.message}${colors.reset}`);
    failures.push({ name, message: error.message });
  }
}

function assert(condition, message) {
  if (!condition) throw new Error(message);
}

function loadFixture(relativePath) {
  const fullPath = path.join(FIXTURES, relativePath);
  const content = fs.readFileSync(fullPath, 'utf-8');
  return { fullPath, content };
}

// --- Valid fixtures ---

console.log(`\n${colors.cyan}CSV File Reference Extraction Tests${colors.reset}\n`);
console.log(`${colors.cyan}Valid fixtures${colors.reset}`);

test('bmm-style.csv: extracts workflow-file refs with trailing commas', () => {
  const { fullPath, content } = loadFixture('valid/bmm-style.csv');
  const refs = extractCsvRefs(fullPath, content);
  assert(refs.length === 2, `Expected 2 refs, got ${refs.length}`);
  assert(refs[0].raw === '_bmad/bmm/workflows/document-project/workflow.md', `Wrong raw[0]: ${refs[0].raw}`);
  assert(refs[1].raw === '_bmad/core/workflows/brainstorming/workflow.md', `Wrong raw[1]: ${refs[1].raw}`);
  assert(refs[0].type === 'project-root', `Wrong type: ${refs[0].type}`);
  assert(refs[0].line === 2, `Wrong line for row 0: ${refs[0].line}`);
  assert(refs[1].line === 3, `Wrong line for row 1: ${refs[1].line}`);
  assert(refs[0].file === fullPath, 'Wrong file path');
});

test('core-style.csv: extracts refs from core module-help format', () => {
  const { fullPath, content } = loadFixture('valid/core-style.csv');
  const refs = extractCsvRefs(fullPath, content);
  assert(refs.length === 2, `Expected 2 refs, got ${refs.length}`);
  assert(refs[0].raw === '_bmad/core/workflows/brainstorming/workflow.md', `Wrong raw[0]: ${refs[0].raw}`);
  assert(refs[1].raw === '_bmad/core/workflows/bmad-party-mode/workflow.md', `Wrong raw[1]: ${refs[1].raw}`);
});

test('minimal.csv: extracts refs from minimal 3-column CSV', () => {
  const { fullPath, content } = loadFixture('valid/minimal.csv');
  const refs = extractCsvRefs(fullPath, content);
  assert(refs.length === 1, `Expected 1 ref, got ${refs.length}`);
  assert(refs[0].raw === '_bmad/core/tasks/help.md', `Wrong raw: ${refs[0].raw}`);
  assert(refs[0].line === 2, `Wrong line: ${refs[0].line}`);
});

// --- Invalid fixtures ---

console.log(`\n${colors.cyan}Invalid fixtures (expect 0 refs)${colors.reset}`);

test('no-workflow-column.csv: returns 0 refs when workflow-file column missing', () => {
  const { fullPath, content } = loadFixture('invalid/no-workflow-column.csv');
  const refs = extractCsvRefs(fullPath, content);
  assert(refs.length === 0, `Expected 0 refs, got ${refs.length}`);
});

test('empty-data.csv: returns 0 refs when CSV has header only', () => {
  const { fullPath, content } = loadFixture('invalid/empty-data.csv');
  const refs = extractCsvRefs(fullPath, content);
  assert(refs.length === 0, `Expected 0 refs, got ${refs.length}`);
});

test('all-empty-workflow.csv: returns 0 refs when all workflow-file cells empty', () => {
  const { fullPath, content } = loadFixture('invalid/all-empty-workflow.csv');
  const refs = extractCsvRefs(fullPath, content);
  assert(refs.length === 0, `Expected 0 refs, got ${refs.length}`);
});

test('unresolvable-vars.csv: filters out template variables, keeps normal refs', () => {
  const { fullPath, content } = loadFixture('invalid/unresolvable-vars.csv');
  const refs = extractCsvRefs(fullPath, content);
  assert(refs.length === 1, `Expected 1 ref, got ${refs.length}`);
  assert(refs[0].raw === '_bmad/core/tasks/help.md', `Wrong raw: ${refs[0].raw}`);
});

// --- Summary ---

console.log(`\n${colors.cyan}${'═'.repeat(55)}${colors.reset}`);
console.log(`${colors.cyan}Test Results:${colors.reset}`);
console.log(`  Total:  ${totalTests}`);
console.log(`  Passed: ${colors.green}${passedTests}${colors.reset}`);
console.log(`  Failed: ${passedTests === totalTests ? colors.green : colors.red}${totalTests - passedTests}${colors.reset}`);
console.log(`${colors.cyan}${'═'.repeat(55)}${colors.reset}\n`);

if (failures.length > 0) {
  console.log(`${colors.red}FAILED TESTS:${colors.reset}\n`);
  for (const failure of failures) {
    console.log(`${colors.red}\u2717${colors.reset} ${failure.name}`);
    console.log(`  ${failure.message}\n`);
  }
  process.exit(1);
}

console.log(`${colors.green}All tests passed!${colors.reset}\n`);
process.exit(0);
