import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from 'node:fs';
import { tmpdir } from 'node:os';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { audit, loadTokens } from '../audit.js';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const tokensFile = path.resolve(__dirname, '../../../tokens.json');

function writeFile(root: string, rel: string, content: string): void {
  const abs = path.join(root, rel);
  mkdirSync(path.dirname(abs), { recursive: true });
  writeFileSync(abs, content, 'utf-8');
}

/** Make caps.hasComponent('DateInput'|'EnumSelect'|'MultiSelect') true (R26 gate). */
function shipsPrimitives(root: string): void {
  for (const name of ['DateInput', 'EnumSelect', 'MultiSelect']) {
    writeFile(root, `src/components/ui/${name}.tsx`, `export function ${name}() { return null; }`);
  }
}

async function run(tmpDir: string) {
  const tokens = await loadTokens(tokensFile);
  return audit(
    { projectPath: tmpDir, mode: 'audit', rules: ['R26'], paths: [], urls: [], regenerateThreshold: 0 },
    tokens,
  );
}

describe('R26-native-form-control', () => {
  let tmpDir: string;
  beforeEach(() => { tmpDir = mkdtempSync(path.join(tmpdir(), 'ui-polish-r26-')); });
  afterEach(() => { rmSync(tmpDir, { recursive: true, force: true }); });

  it('FIRES (warning) — native <input type="date"> when DateInput ships', async () => {
    shipsPrimitives(tmpDir);
    writeFile(tmpDir, 'src/pages/test/FooFormPage.tsx', `
export function FooFormPage() {
  return (<form><input type="date" value="" onChange={() => {}} /></form>);
}
`);
    const report = await run(tmpDir);
    expect(report.findings).toHaveLength(1);
    expect(report.findings[0].ruleId).toBe('R26-native-form-control');
    expect(report.findings[0].severity).toBe('warning');
    expect(report.findings[0].message).toContain('DateInput');
  });

  it('FIRES (warning) — native <select> recommends EnumSelect', async () => {
    shipsPrimitives(tmpDir);
    writeFile(tmpDir, 'src/pages/test/FooFormPage.tsx', `
export function FooFormPage() {
  return (<form><select value=""><option value="a">A</option></select></form>);
}
`);
    const report = await run(tmpDir);
    expect(report.findings).toHaveLength(1);
    expect(report.findings[0].message).toContain('EnumSelect');
  });

  it('FIRES (warning) — <select multiple> recommends MultiSelect', async () => {
    shipsPrimitives(tmpDir);
    writeFile(tmpDir, 'src/pages/test/FooFormPage.tsx', `
export function FooFormPage() {
  return (<form><select multiple value={[]}><option value="a">A</option></select></form>);
}
`);
    const report = await run(tmpDir);
    expect(report.findings).toHaveLength(1);
    expect(report.findings[0].message).toContain('MultiSelect');
  });

  it('SILENT — native controls but project ships NO primitive (project-aware)', async () => {
    // No DateInput/EnumSelect/MultiSelect under src/components → never demands them.
    writeFile(tmpDir, 'src/pages/test/FooFormPage.tsx', `
export function FooFormPage() {
  return (<form><input type="date" value="" /><select value=""><option value="a">A</option></select></form>);
}
`);
    const report = await run(tmpDir);
    expect(report.findings).toHaveLength(0);
  });

  it('SILENT — page already uses the theme-compliant primitives', async () => {
    shipsPrimitives(tmpDir);
    writeFile(tmpDir, 'src/pages/test/FooFormPage.tsx', `
import { DateInput } from '@/components/ui/DateInput';
import { EnumSelect } from '@/components/ui/EnumSelect';
export function FooFormPage() {
  return (<form><DateInput value={null} onChange={() => {}} /><EnumSelect options={[]} value={null} onChange={() => {}} /></form>);
}
`);
    const report = await run(tmpDir);
    expect(report.findings).toHaveLength(0);
  });

  it('SILENT — plain <input type="text"> is not a native form-control bypass', async () => {
    shipsPrimitives(tmpDir);
    writeFile(tmpDir, 'src/pages/test/FooFormPage.tsx', `
export function FooFormPage() {
  return (<form><input type="text" value="" onChange={() => {}} /></form>);
}
`);
    const report = await run(tmpDir);
    expect(report.findings).toHaveLength(0);
  });
});
