import { afterEach, expect, test } from "bun:test";
import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
import { join } from "node:path";
import { tmpdir } from "node:os";
import {
  compileWireArtifacts,
  setCompileCacheDir,
  setCompileImportOptions,
} from "../src/pipeline.ts";

const roots: string[] = [];
afterEach(() => {
  for (const root of roots.splice(0)) rmSync(root, { recursive: true, force: true });
});

function fixture(): { root: string; page: string } {
  const root = mkdtempSync(join(tmpdir(), "wrn-import-mode-"));
  roots.push(root);
  mkdirSync(join(root, "app/pages"), { recursive: true });
  mkdirSync(join(root, "app/components"), { recursive: true });
  writeFileSync(
    join(root, "app/components/Card.wrn"),
    "component Card { view { <div>Card</div> } }",
  );
  const page = join(root, "app/pages/index.wrn");
  writeFileSync(page, "page Home { view { <Card /> } }");
  setCompileCacheDir(join(root, ".wrnexus"));
  return { root, page };
}

test("legacy, compatible, and explicit import modes are enforced from app config", () => {
  const { root, page } = fixture();
  setCompileImportOptions(root, { mode: "legacy" });
  expect(() => compileWireArtifacts(page, 1)).not.toThrow();

  const warnings: string[] = [];
  const originalWarn = console.warn;
  console.warn = (...args) => warnings.push(args.join(" "));
  try {
    setCompileImportOptions(root, { mode: "compatible" });
    expect(() => compileWireArtifacts(page, 2)).not.toThrow();
    expect(warnings.some((message) => message.includes("WRN-IMPORT-IMPLICIT"))).toBe(true);

    setCompileImportOptions(root, { mode: "explicit" });
    expect(() => compileWireArtifacts(page, 3)).toThrow("WRN-IMPORT-IMPLICIT");

    writeFileSync(
      page,
      'import Card from "@/components/Card.wrn"\npage Home { view { <Card /> } }',
    );
    expect(() => compileWireArtifacts(page, 4)).not.toThrow();
  } finally {
    console.warn = originalWarn;
  }
});

test("compiler-native reactive elements do not require application imports", () => {
  const { root, page } = fixture();
  writeFileSync(
    page,
    `page Home {
      state active = "Admin"
      view {
        <Transition name="fade"><Component is={active}><div data-component-case="Admin">Admin</div></Component></Transition>
        <Portal to="body"><p>Notice</p></Portal>
        <Async source="profile"><Loading>Loading</Loading><Success data="profile">Ready</Success><Error error="error">Failed</Error></Async>
      }
    }`,
  );
  setCompileImportOptions(root, { mode: "explicit" });
  expect(() => compileWireArtifacts(page, 5)).not.toThrow();
});
