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

const inventoryPath = path.join(repositoryRoot, 'docs/phase12/COMPONENT_INVENTORY_v1.0.json');
const inventory = JSON.parse(await readFile(inventoryPath, 'utf8'));
const errors = [];
const allowedStatus = new Set(['implemented', 'partially-implemented', 'blocked', 'excluded']);
const names = new Set();

if (inventory.phase !== 12 || !Array.isArray(inventory.entries)) {
  errors.push('Component inventory must identify Phase 12 and contain an entries array.');
}
for (const entry of inventory.entries ?? []) {
  if (names.has(entry.name)) errors.push(`Duplicate inventory component: ${entry.name}`);
  names.add(entry.name);
  if (!allowedStatus.has(entry.status))
    errors.push(`${entry.name}: invalid status ${entry.status}`);
  for (const field of ['sourceSpecification', 'variants', 'openIssues', 'homepageConsumers']) {
    if (!Array.isArray(entry[field])) errors.push(`${entry.name}: ${field} must be an array.`);
  }
  if (
    !entry.tests ||
    !['unit', 'interaction', 'accessibility', 'visual'].every(
      (key) => typeof entry.tests[key] === 'boolean',
    )
  ) {
    errors.push(`${entry.name}: test coverage flags are incomplete.`);
  }
  if (entry.status === 'blocked' && entry.openIssues.length === 0) {
    errors.push(`${entry.name}: blocked components require an issue reference.`);
  }
}

for (const required of [
  'Button',
  'ActionLink',
  'FormField',
  'Tabs',
  'Accordion',
  'Dialog',
  'Alert',
  'Card',
  'Workflow',
  'Comparison',
  'Metric',
  'CTA',
  'ProductPreview',
]) {
  if (!names.has(required)) errors.push(`Required component missing from inventory: ${required}`);
}

const componentFiles = await walk(path.join(repositoryRoot, 'src/components'), (file) =>
  /\.(?:ts|tsx|css)$/.test(file),
);
const forbiddenRawToken = /var\(--color-(?:blue|orange|gray|green|amber|red|navy)-/g;
const forbiddenLiteralColor = /(?:#[0-9a-f]{3,8}\b|rgba?\(|hsla?\()/gi;
for (const file of componentFiles) {
  const text = await readFile(file, 'utf8');
  const relative = path.relative(repositoryRoot, file);
  if (file.endsWith('.css') && forbiddenRawToken.test(text))
    errors.push(`${relative}: consumes a raw palette token.`);
  if (file.endsWith('.css') && forbiddenLiteralColor.test(text))
    errors.push(`${relative}: contains a literal color.`);
  if (/href=["']#["']/.test(text)) errors.push(`${relative}: contains a placeholder href="#".`);
}

for (const artifact of [
  'COMPONENT_SPECIFICATION_TRACEABILITY_v1.0.csv',
  'VARIANT_INVENTORY_v1.0.csv',
  'ACCESSIBILITY_BEHAVIOR_MATRIX_v1.0.csv',
  'RTL_BEHAVIOR_MATRIX_UPDATE_v1.0.csv',
  'RESPONSIVE_VALIDATION_MATRIX_v1.0.csv',
  'STORY_AND_FIXTURE_INVENTORY_v1.0.csv',
  'TEST_COVERAGE_REPORT_v1.0.csv',
  'COMPONENT_CATALOG_v1.0.md',
]) {
  try {
    await stat(path.join(repositoryRoot, 'docs/phase12', artifact));
  } catch {
    errors.push(`Required Phase 12 artifact missing: ${artifact}`);
  }
}

const fixturePage = await readFile(
  path.join(repositoryRoot, 'src/app/[locale]/component-lab/page.tsx'),
  'utf8',
);
if (!fixturePage.includes("COMPONENT_FIXTURES_ENABLED !== 'true'")) {
  errors.push('Component fixture route is not protected by the production environment guard.');
}

if (errors.length > 0) fail(errors);
else
  pass(
    `${inventory.entries.length} inventory entries and ${componentFiles.length} component source files satisfy Phase 12 static controls.`,
  );
