import { expect, test } from "bun:test";
import {
  compilePlayground,
  createPlaygroundHandler,
  decodePlaygroundShare,
  encodePlaygroundShare,
} from "../src/index.ts";

const source = `component Hello { props { name = "World" } view { <h1>Hello {name}</h1> } }`;
test("playground exposes generated, client, SSR-shaped and diagnostic output", () => {
  const result = compilePlayground(source);
  expect(result.generated).toContain("export function render");
  expect(result.client).toContain("Hello");
  expect(result.html).toContain("Hello");
  expect(result.interactiveHtml).toContain("Content-Security-Policy");
  expect(result.diagnostics).toEqual([]);
});
test("share URLs round-trip Unicode and enforce bounds", () => {
  const unicode = `${source}\n// नमस्ते`;
  expect(decodePlaygroundShare(encodePlaygroundShare(unicode))).toBe(unicode);
  expect(() => encodePlaygroundShare("x".repeat(70_000))).toThrow("WRN-PLAYGROUND-SHARE-LIMIT");
});
test("deployable handler compiles and serves a sandboxed CSP page", async () => {
  const handler = createPlaygroundHandler();
  const response = await handler(
    new Request("https://play.test/api/compile", {
      method: "POST",
      body: JSON.stringify({ source }),
    }),
  );
  expect(response.status).toBe(200);
  expect(await response.json()).toHaveProperty("share");
  const html = await handler(new Request("https://play.test/"));
  expect(html.headers.get("content-security-policy")).toContain("script-src 'self'");
  const page = await html.text();
  expect(page).toContain('sandbox="allow-scripts"');
  expect(page).toContain('id="compare"');
  expect(page).toContain('id="examples"');
});

test("handler exposes examples and optional version comparisons", async () => {
  const handler = createPlaygroundHandler({
    examples: { hello: source },
    versions: [{ version: "0.7.0", compile: async () => compilePlayground(source, "0.7.0") }],
  });
  const examples = await handler(new Request("https://play.test/api/examples"));
  expect(await examples.json()).toEqual({ hello: source });
  const comparison = await handler(
    new Request("https://play.test/api/compile", {
      method: "POST",
      body: JSON.stringify({ source, versions: true }),
    }),
  );
  const result = (await comparison.json()) as { comparisons: Array<{ version: string }> };
  expect(result.comparisons[0]?.version).toBe("0.7.0");
});

test("reactive preview interprets only bounded state operations", () => {
  const result = compilePlayground(
    `component Counter {
      state count = 0
      functions { client function increment(): void { count++ } }
      view { <button @click="increment">{count}</button> }
    }`,
  );
  expect(result.interactiveHtml).toContain('"operation":"++"');
  expect(result.interactiveHtml).toContain("data-play-event-click");
});
