import { expect, test } from "bun:test";
import { Window } from "happy-dom";
import { renderToStaticMarkup } from "react-dom/server";
import type { ReactNode } from "react";
import { Card } from "./Card";
import { ContainerShowcase } from "./ContainerShowcase";
import { Field } from "./Field";

function render(content: ReactNode) {
  const window = new Window();
  window.document.body.innerHTML = renderToStaticMarkup(content);
  return window.document.body;
}

test("Field connects its label and hint to the rendered control", () => {
  const body = render(
    <Field id="habit" label="Habit name" hint="Keep it short.">
      {(id, describedBy) => <input id={id} aria-describedby={describedBy} />}
    </Field>,
  );
  expect(body.querySelector("label")?.htmlFor).toBe("habit");
  expect(body.querySelector("input")?.getAttribute("aria-describedby")).toBe("habit-hint");
  expect(body.querySelector("#habit-hint")?.textContent).toBe("Keep it short.");
});

test("Field generates unique control IDs and omits absent hint references", () => {
  const body = render(<>
    <Field label="First">{(id, describedBy) => <input id={id} aria-describedby={describedBy} />}</Field>
    <Field label="Second">{(id, describedBy) => <input id={id} aria-describedby={describedBy} />}</Field>
  </>);
  const controls = [...body.querySelectorAll("input")];
  expect(new Set(controls.map((control) => control.id)).size).toBe(2);
  expect(controls.every((control) => !control.hasAttribute("aria-describedby"))).toBe(true);
  expect(body.querySelectorAll("small")).toHaveLength(0);
});

test("Card preserves its title styling and accessible name at each heading level", () => {
  for (const headingLevel of [2, 3, 4, 5, 6] as const) {
    const body = render(<Card heading="A clear boundary" headingLevel={headingLevel}>Content</Card>);
    const heading = body.querySelector(`h${headingLevel}.ds-card-title`);
    expect(heading?.textContent).toBe("A clear boundary");
    expect(body.querySelector("article")?.getAttribute("aria-labelledby")).toBe(heading?.id);
  }
  expect(render(<Card heading="Default" />).querySelector("h3")?.textContent).toBe("Default");
});

test("Layout uses subsection headings above the card titles", () => {
  const body = render(<ContainerShowcase />);
  expect(body.querySelectorAll("h2")).toHaveLength(1);
  expect(body.querySelectorAll("h3")).toHaveLength(2);
  expect(body.querySelectorAll("h4.ds-card-title")).toHaveLength(6);
});
