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('PageTemplate') true (R25 gate). */
function withPageTemplate(root: string): void {
  writeFile(root, 'src/components/ui/PageTemplate.tsx', `export function PageTemplate() { return null; }`);
}

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

describe('R25-content-width', () => {
  let tmpDir: string;
  beforeEach(() => { tmpDir = mkdtempSync(path.join(tmpdir(), 'ui-polish-r25-')); });
  afterEach(() => { rmSync(tmpDir, { recursive: true, force: true }); });

  it('FIRES (warning) — Tailwind `container mx-auto` on a page', async () => {
    withPageTemplate(tmpDir);
    writeFile(tmpDir, 'src/pages/test/FooListPage.tsx', `
export function FooListPage() {
  return (<div className="container mx-auto p-4"><h1>Foo</h1></div>);
}
`);
    const report = await run(tmpDir);
    expect(report.findings).toHaveLength(1);
    expect(report.findings[0].ruleId).toBe('R25-content-width');
    expect(report.findings[0].severity).toBe('warning');
    expect(report.findings[0].message).toContain('width="focused"');
  });

  it('FIRES (warning) — page-root max-w-4xl mx-auto', async () => {
    withPageTemplate(tmpDir);
    writeFile(tmpDir, 'src/pages/test/FooListPage.tsx', `
export function FooListPage() {
  return (<div className="max-w-4xl mx-auto space-y-6 py-4"><h1>Foo</h1></div>);
}
`);
    const report = await run(tmpDir);
    expect(report.findings).toHaveLength(1);
    expect(report.findings[0].snippet).toContain('max-w-4xl');
  });

  it('SILENT — modal/overlay max-w (fixed inset-0) is legitimate', async () => {
    withPageTemplate(tmpDir);
    writeFile(tmpDir, 'src/pages/test/FooListPage.tsx', `
export function FooListPage() {
  return (
    <div className="space-y-6">
      <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50">
        <div className="w-full max-w-2xl mx-auto bg-[var(--bg-card)] rounded p-6">modal</div>
      </div>
    </div>
  );
}
`);
    const report = await run(tmpDir);
    expect(report.findings).toHaveLength(0);
  });

  it('SILENT — standard full-width page (no width hack)', async () => {
    withPageTemplate(tmpDir);
    writeFile(tmpDir, 'src/pages/test/FooListPage.tsx', `
export function FooListPage() {
  return (<div className="space-y-6"><h1>Foo</h1></div>);
}
`);
    const report = await run(tmpDir);
    expect(report.findings).toHaveLength(0);
  });

  it('SILENT — project ships no PageTemplate (no width contract to point at)', async () => {
    // No PageTemplate component → R25 cannot recommend the width prop → stays quiet.
    writeFile(tmpDir, 'src/pages/test/FooListPage.tsx', `
export function FooListPage() {
  return (<div className="container mx-auto p-4"><h1>Foo</h1></div>);
}
`);
    const report = await run(tmpDir);
    expect(report.findings).toHaveLength(0);
  });
});
