import { fireEvent, render, screen } from "@solidjs/testing-library";
import type { JSX } from "solid-js";
import { describe, expect, it, vi } from "vitest";
import { Wizard, WizardMeta, WizardRootPropsSchema } from "../../../src/components/wizard/index";
import type { WizardRootProps } from "../../../src/components/wizard/index";

interface ThreeStepWizardProps extends Omit<WizardRootProps, "children"> {}

function ThreeStepWizard(props: ThreeStepWizardProps): JSX.Element {
  return (
    <Wizard {...props}>
      <Wizard.StepList>
        <Wizard.Step index={0}>
          <Wizard.StepTrigger data-testid="trigger-0">Step 1</Wizard.StepTrigger>
          <Wizard.StepContent data-testid="content-0">Content 0</Wizard.StepContent>
        </Wizard.Step>
        <Wizard.Step index={1}>
          <Wizard.StepTrigger data-testid="trigger-1">Step 2</Wizard.StepTrigger>
          <Wizard.StepContent data-testid="content-1">Content 1</Wizard.StepContent>
        </Wizard.Step>
        <Wizard.Step index={2}>
          <Wizard.StepTrigger data-testid="trigger-2">Step 3</Wizard.StepTrigger>
          <Wizard.StepContent data-testid="content-2">Content 2</Wizard.StepContent>
        </Wizard.Step>
      </Wizard.StepList>
      <Wizard.Prev data-testid="prev">Prev</Wizard.Prev>
      <Wizard.Next data-testid="next">Next</Wizard.Next>
    </Wizard>
  );
}

function renderWizard(props: ThreeStepWizardProps = {}) {
  return render(() => <ThreeStepWizard {...props} />);
}

describe("Wizard — rendering", () => {
  it("renders first step content by default", () => {
    renderWizard();
    expect(screen.getByTestId("content-0")).toBeTruthy();
    expect(screen.queryByTestId("content-1")).toBeNull();
    expect(screen.queryByTestId("content-2")).toBeNull();
  });

  it("first trigger has aria-selected=true", () => {
    renderWizard();
    expect(screen.getByTestId("trigger-0").getAttribute("aria-selected")).toBe("true");
    expect(screen.getByTestId("trigger-1").getAttribute("aria-selected")).toBe("false");
  });

  it("step list has role=tablist", () => {
    renderWizard();
    expect(screen.getByRole("tablist")).toBeTruthy();
  });

  it("active content has role=tabpanel", () => {
    renderWizard();
    expect(screen.getByRole("tabpanel")).toBeTruthy();
  });
});

describe("Wizard — navigation", () => {
  it("next button advances to step 1", () => {
    renderWizard();
    fireEvent.click(screen.getByTestId("next"));
    expect(screen.getByTestId("content-1")).toBeTruthy();
    expect(screen.queryByTestId("content-0")).toBeNull();
  });

  it("prev button goes back", () => {
    renderWizard();
    fireEvent.click(screen.getByTestId("next"));
    fireEvent.click(screen.getByTestId("prev"));
    expect(screen.getByTestId("content-0")).toBeTruthy();
  });

  it("prev button not disabled after advancing", () => {
    renderWizard();
    fireEvent.click(screen.getByTestId("next"));
    expect(screen.getByTestId("prev")).not.toBeDisabled();
  });
});

describe("Wizard — linear mode", () => {
  it("unreached step triggers are disabled", () => {
    renderWizard();
    expect(screen.getByTestId("trigger-1")).toBeDisabled();
    expect(screen.getByTestId("trigger-2")).toBeDisabled();
  });

  it("clicking disabled trigger does not navigate", () => {
    renderWizard();
    fireEvent.click(screen.getByTestId("trigger-2"));
    expect(screen.getByTestId("content-0")).toBeTruthy();
  });

  it("trigger becomes enabled after completing prior step", () => {
    renderWizard();
    fireEvent.click(screen.getByTestId("next"));
    expect(screen.getByTestId("trigger-1")).not.toBeDisabled();
  });

  it("non-linear: all triggers enabled from start", () => {
    renderWizard({ linear: false });
    expect(screen.getByTestId("trigger-2")).not.toBeDisabled();
  });
});

describe("Wizard — callbacks", () => {
  it("onStepChange called on advance", () => {
    const onStepChange = vi.fn();
    renderWizard({ onStepChange });
    fireEvent.click(screen.getByTestId("next"));
    expect(onStepChange).toHaveBeenCalledWith(1);
  });

  it("onStepChange called on prev", () => {
    const onStepChange = vi.fn();
    renderWizard({ onStepChange });
    fireEvent.click(screen.getByTestId("next"));
    fireEvent.click(screen.getByTestId("prev"));
    expect(onStepChange).toHaveBeenCalledWith(0);
  });

  it("onComplete called after last step", () => {
    const onComplete = vi.fn();
    renderWizard({ onComplete });
    fireEvent.click(screen.getByTestId("next"));
    fireEvent.click(screen.getByTestId("next"));
    fireEvent.click(screen.getByTestId("next"));
    expect(onComplete).toHaveBeenCalledTimes(1);
  });
});

describe("Wizard — schema and meta", () => {
  it("schema validates correct input", () => {
    const result = WizardRootPropsSchema.safeParse({ step: 1, linear: true, orientation: "horizontal" });
    expect(result.success).toBe(true);
  });

  it("schema rejects invalid orientation", () => {
    const result = WizardRootPropsSchema.safeParse({ orientation: "diagonal" });
    expect(result.success).toBe(false);
  });

  it("meta has name and required parts", () => {
    expect(WizardMeta.name).toBe("Wizard");
    expect(WizardMeta.parts).toContain("Root");
    expect(WizardMeta.parts).toContain("StepContent");
  });
});
