import { render, screen } from "@solidjs/testing-library";
import { describe, expect, it } from "vitest";
import { z } from "zod/v4";
import { Form, FormRootPropsSchema, FormMeta } from "../../../src/components/form/index";

const schema = z.object({
  username: z.string().min(3, "Username must be at least 3 characters"),
});

describe("Form — rendering", () => {
  it("renders form with fields", () => {
    render(() => (
      <Form>
        <Form.Field name="username">
          <Form.Label>Username</Form.Label>
          <Form.Control>{(p) => <input {...p} data-testid="u" />}</Form.Control>
        </Form.Field>
        <Form.Submit>Submit</Form.Submit>
      </Form>
    ));
    expect(screen.getByText("Username")).toBeTruthy();
    expect(screen.getByTestId("u")).toBeTruthy();
    expect(screen.getByRole("button", { name: "Submit" })).toBeTruthy();
  });

  it("label htmlFor links to control id", () => {
    render(() => (
      <Form>
        <Form.Field name="username">
          <Form.Label>Username</Form.Label>
          <Form.Control>{(p) => <input {...p} />}</Form.Control>
        </Form.Field>
      </Form>
    ));
    const label = screen.getByText("Username");
    expect(label.getAttribute("for")).toBe(screen.getByRole("textbox").id);
  });

  it("description aria-describedby is linked to control", () => {
    render(() => (
      <Form>
        <Form.Field name="username">
          <Form.Control>{(p) => <input {...p} data-testid="ctrl" />}</Form.Control>
          <Form.Description>Enter your username</Form.Description>
        </Form.Field>
      </Form>
    ));
    const desc = screen.getByText("Enter your username");
    expect(screen.getByTestId("ctrl").getAttribute("aria-describedby")).toContain(desc.id);
  });

  it("error message hidden when no errors", () => {
    render(() => (
      <Form schema={schema}>
        <Form.Field name="username">
          <Form.Control>{(p) => <input {...p} />}</Form.Control>
          <Form.ErrorMessage>Required</Form.ErrorMessage>
        </Form.Field>
      </Form>
    ));
    expect(screen.queryByRole("alert")).toBeNull();
  });

  it("submit button is disabled when form is disabled", () => {
    render(() => <Form disabled><Form.Submit>Submit</Form.Submit></Form>);
    expect(screen.getByRole("button", { name: "Submit" })).toBeDisabled();
  });
});

describe("Form — schema and meta", () => {
  it("schema validates validateOn enum", () => {
    expect(FormRootPropsSchema.safeParse({ validateOn: "submit" }).success).toBe(true);
    expect(FormRootPropsSchema.safeParse({ validateOn: "blur" }).success).toBe(true);
    expect(FormRootPropsSchema.safeParse({ validateOn: "change" }).success).toBe(true);
    expect(FormRootPropsSchema.safeParse({ validateOn: "invalid" }).success).toBe(false);
  });

  it("meta has fields", () => {
    expect(FormMeta.name).toBe("Form");
    expect(FormMeta.parts).toContain("Root");
    expect(FormMeta.parts).toContain("Field");
    expect(FormMeta.parts).toContain("Label");
    expect(FormMeta.parts).toContain("Control");
    expect(FormMeta.parts).toContain("ErrorMessage");
    expect(FormMeta.parts).toContain("Submit");
  });
});
