import { expect, test } from "bun:test";
import { mkdirSync, mkdtempSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { checkWrnSource } from "../src/index.ts";

function fixture(): string {
  const root = mkdtempSync(join(tmpdir(), "wrn-v060-contracts-"));
  mkdirSync(join(root, "app", "components"), { recursive: true });
  mkdirSync(join(root, "app", "stores", "global"), { recursive: true });
  mkdirSync(join(root, "app", "types"), { recursive: true });
  writeFileSync(
    join(root, "app", "types", "global.d.ts"),
    "declare interface AppMarker { ready: boolean }\n",
  );
  writeFileSync(
    join(root, "app", "components", "UserCard.wrn"),
    `component UserCard {
    props { name: string role: "admin" | "member" = "member" }
    outputs { select(payload: string) }
    view { <button>{name}</button> }
  }`,
  );
  writeFileSync(
    join(root, "app", "stores", "global", "counter.wrn"),
    `global store CounterStore {
    state { count: number = 0 }
    functions { client function increment(amount: number): void { count += amount } }
  }`,
  );
  return root;
}

test("checks imported component props and output names", () => {
  const root = fixture();
  const filePath = join(root, "app", "pages", "home.wrn");
  const diagnostics = checkWrnSource(
    `import UserCard from "@/components/UserCard.wrn"
page Home {
  view { <UserCard role="owner" unknown="x" @missing='noop(payload)' /> }
}`,
    { appRoot: root, filePath },
  );
  expect(diagnostics.some((item) => item.code === "WRN-COMPONENT-MISSING-PROP")).toBe(true);
  expect(diagnostics.some((item) => item.code === "WRN-COMPONENT-UNKNOWN-PROP")).toBe(true);
  expect(diagnostics.some((item) => item.code === "WRN-COMPONENT-PROP-LITERAL")).toBe(true);
  expect(diagnostics.some((item) => item.code === "WRN-OUTPUT-UNKNOWN-HANDLER")).toBe(true);
}, 15_000);

test("types imported store actions", () => {
  const root = fixture();
  const filePath = join(root, "app", "pages", "home.wrn");
  const diagnostics = checkWrnSource(
    `import counterStore from "@/stores/global/counter.wrn"
page Home {
  functions { client function update(): void { counterStore.increment("wrong") } }
  view { <button></button> }
}`,
    { appRoot: root, filePath },
  );
  expect(diagnostics.some((item) => item.code === "WRN-TYPE-2345")).toBe(true);
}, 15_000);

test("accepts WRN boolean string literals and reserved class props", () => {
  const root = fixture();
  const componentPath = join(root, "app", "components", "Toggle.wrn");
  writeFileSync(
    componentPath,
    `component Toggle {
      props { enabled: boolean = false class: string = "" }
      view { <button class='{class}'></button> }
    }`,
  );
  const filePath = join(root, "app", "pages", "home.wrn");
  const diagnostics = checkWrnSource(
    `import Toggle from "@/components/Toggle.wrn"
page Home {
  view { <Toggle enabled="true" class="demo" /> }
}`,
    { appRoot: root, filePath },
  );
  expect(diagnostics.some((item) => item.code === "WRN-COMPONENT-PROP-TYPE")).toBe(false);
  expect(diagnostics.some((item) => item.code === "WRN-TYPE-1389")).toBe(false);
  expect(diagnostics.some((item) => item.code === "WRN-TYPE-1005")).toBe(false);
}, 15_000);
