import { useState } from "react";
import { CheckboxOption } from "../../src/components/ui/Checkbox";

// First real component test — mounts CheckboxOption in isolation (no
// router, no backend), unlike everything under cypress/e2e/ which always
// visits a full routed page. See cypress.config.ts's `component` block.

describe("CheckboxOption", () => {
  it("renders its label content", () => {
    cy.mount(
      <CheckboxOption checked={false} onChange={() => {}}>
        Végétarien
      </CheckboxOption>,
    );

    cy.contains("label", "Végétarien").should("be.visible");
  });

  it("reflects the checked prop on the native input, and the is-selected class", () => {
    cy.mount(
      <CheckboxOption checked={false} onChange={() => {}}>
        Végétarien
      </CheckboxOption>,
    );
    cy.get("input[type=checkbox]").should("not.be.checked");
    cy.get("label").should("not.have.class", "is-selected");

    cy.mount(
      <CheckboxOption checked={true} onChange={() => {}}>
        Végétarien
      </CheckboxOption>,
    );
    cy.get("input[type=checkbox]").should("be.checked");
    cy.get("label").should("have.class", "is-selected");
  });

  it("calls onChange with the toggled value when clicked", () => {
    const onChange = cy.stub().as("onChange");
    cy.mount(
      <CheckboxOption checked={false} onChange={onChange}>
        Végétarien
      </CheckboxOption>,
    );

    cy.get("input[type=checkbox]").click();

    cy.get("@onChange").should("have.been.calledOnceWith", true);
  });

  it("is a controlled component — stays checked only while the parent says so", () => {
    // A tiny stateful wrapper, since CheckboxOption itself takes no
    // internal state — this is what actually exercises the checked/onChange
    // contract the way a real caller (AllergySelect, the theme picker…)
    // would.
    function Wrapper() {
      const [checked, setChecked] = useState(false);
      return (
        <CheckboxOption checked={checked} onChange={setChecked}>
          Végétarien
        </CheckboxOption>
      );
    }
    cy.mount(<Wrapper />);

    cy.get("input[type=checkbox]").should("not.be.checked").click();
    cy.get("input[type=checkbox]").should("be.checked");
  });

  it("calls onChange with false when clicking while already checked", () => {
    const onChange = cy.stub().as("onChange");
    cy.mount(
      <CheckboxOption checked={true} onChange={onChange}>
        Végétarien
      </CheckboxOption>,
    );

    cy.get("input[type=checkbox]").click();

    cy.get("@onChange").should("have.been.calledOnceWith", false);
  });

  it("merges the caller's className with the container layout, alongside is-selected", () => {
    cy.mount(
      <CheckboxOption checked={false} onChange={() => {}} className="allergy-select__option">
        Végétarien
      </CheckboxOption>,
    );
    cy.get("label")
      .should("have.class", "allergy-select__option")
      .and("not.have.class", "is-selected");

    cy.mount(
      <CheckboxOption checked={true} onChange={() => {}} className="allergy-select__option">
        Végétarien
      </CheckboxOption>,
    );
    cy.get("label").should("have.class", "allergy-select__option").and("have.class", "is-selected");
  });

  it("has no className at all when the caller doesn't pass one", () => {
    cy.mount(
      <CheckboxOption checked={false} onChange={() => {}}>
        Végétarien
      </CheckboxOption>,
    );
    // `[className, checked && "is-selected"].filter(Boolean).join(" ")` with
    // both falsy collapses to "" — worth pinning down since a stray
    // "false"/"null" string in `class` would be a real (if harmless-looking)
    // regression.
    cy.get("label").should("have.attr", "class", "");
  });

  it("toggles when the click lands on the label text, not just the input itself", () => {
    // The label wraps the input (native HTML forwards the click), which is
    // what actually makes the whole row clickable — not just a tiny
    // checkbox hitbox. This is real browser behavior, not something the
    // component's own code implements, but it's exactly the contract the
    // "selectable card" look (global.scss) relies on, so it's worth pinning
    // down here rather than trusting it silently.
    const onChange = cy.stub().as("onChange");
    cy.mount(
      <CheckboxOption checked={false} onChange={onChange}>
        Végétarien
      </CheckboxOption>,
    );

    cy.contains("label", "Végétarien").click();

    cy.get("@onChange").should("have.been.calledOnceWith", true);
  });

  it("marks the check-mark decoration as aria-hidden, so screen readers only announce the checkbox itself", () => {
    cy.mount(
      <CheckboxOption checked={false} onChange={() => {}}>
        Végétarien
      </CheckboxOption>,
    );
    cy.get("span.check-mark").should("have.attr", "aria-hidden", "true");
  });
});
