import { RadioButton } from "./index";

import { fireEvent, render, screen } from "@testing-library/react";

describe("RadioButton", () => {
  const defaultProps = {
    name: "plan",
    label: "Option A",
  };

  it("renders with label text", () => {
    render(<RadioButton {...defaultProps} />);
    expect(screen.getByText("Option A")).toBeInTheDocument();
  });

  it("renders a hidden radio input", () => {
    const { container } = render(<RadioButton {...defaultProps} />);
    const input = container.querySelector('input[type="radio"]');
    expect(input).toBeInTheDocument();
    expect(input).toHaveClass("hidden");
  });

  it("sets name and value on the input", () => {
    const { container } = render(
      <RadioButton {...defaultProps} value="optA" />
    );
    const input = container.querySelector('input[type="radio"]');
    expect(input).toHaveAttribute("name", "plan");
    expect(input).toHaveAttribute("value", "optA");
  });

  it("calls onChange with value when clicked", () => {
    const onChange = jest.fn();
    render(<RadioButton {...defaultProps} value="optA" onChange={onChange} />);
    const buttons = screen.getAllByRole("button");
    fireEvent.click(buttons[0]);
    expect(onChange).toHaveBeenCalledWith("optA");
  });

  it("calls onChange with name when no value is provided", () => {
    const onChange = jest.fn();
    render(<RadioButton {...defaultProps} onChange={onChange} />);
    const buttons = screen.getAllByRole("button");
    fireEvent.click(buttons[0]);
    expect(onChange).toHaveBeenCalledWith("plan");
  });

  it("calls onChange when label button is clicked", () => {
    const onChange = jest.fn();
    render(<RadioButton {...defaultProps} value="optA" onChange={onChange} />);
    const buttons = screen.getAllByRole("button");
    fireEvent.click(buttons[1]);
    expect(onChange).toHaveBeenCalledWith("optA");
  });

  it("does not throw when onChange is not provided", () => {
    render(<RadioButton {...defaultProps} />);
    const buttons = screen.getAllByRole("button");
    expect(() => fireEvent.click(buttons[0])).not.toThrow();
  });

  it("shows checked indicator when checked", () => {
    const { container } = render(
      <RadioButton {...defaultProps} checked={true} />
    );
    const indicator = container.querySelector(".bg-bg-fill-brand");
    expect(indicator).toBeInTheDocument();
  });

  it("does not show checked indicator when unchecked", () => {
    const { container } = render(
      <RadioButton {...defaultProps} checked={false} />
    );
    const indicator = container.querySelector(".bg-bg-fill-brand");
    expect(indicator).not.toBeInTheDocument();
  });

  it("applies border-brand class to outer button when checked", () => {
    render(<RadioButton {...defaultProps} checked={true} />);
    const buttons = screen.getAllByRole("button");
    expect(buttons[0].className).toContain("border-border-brand");
  });

  it("renders subText", () => {
    render(<RadioButton {...defaultProps} subText="Extra info" />);
    expect(screen.getByText("Extra info")).toBeInTheDocument();
  });

  it("applies custom className to the label wrapper", () => {
    const { container } = render(
      <RadioButton {...defaultProps} className="custom-wrapper" />
    );
    const label = container.querySelector("label");
    expect(label?.className).toContain("custom-wrapper");
  });

  it("applies custom labelClassName", () => {
    render(<RadioButton {...defaultProps} labelClassName="text-bold" />);
    const labelDiv = screen.getByText("Option A");
    expect(labelDiv.className).toContain("text-bold");
  });

  it("passes data-cy to the label", () => {
    const { container } = render(
      <RadioButton {...defaultProps} data-cy="radio-cy" />
    );
    const label = container.querySelector('[data-cy="radio-cy"]');
    expect(label).toBeInTheDocument();
  });

  it("passes labelProps to the label element", () => {
    const { container } = render(
      <RadioButton {...defaultProps} labelProps={{ id: "custom-label-id" }} />
    );
    const label = container.querySelector("#custom-label-id");
    expect(label).toBeInTheDocument();
  });

  it("disables buttons and input when disabled", () => {
    const { container } = render(
      <RadioButton {...defaultProps} disabled={true} />
    );
    const input = container.querySelector('input[type="radio"]');
    const buttons = screen.getAllByRole("button");
    expect(input).toBeDisabled();
    expect(buttons[0]).toBeDisabled();
    expect(buttons[1]).toBeDisabled();
  });

  it("applies opacity-50 class when disabled", () => {
    render(<RadioButton {...defaultProps} disabled={true} />);
    const buttons = screen.getAllByRole("button");
    expect(buttons[0].className).toContain("opacity-50");
  });

  it("sets tabIndex -1 on label button when no label is provided", () => {
    render(<RadioButton name="plan" />);
    const buttons = screen.getAllByRole("button");
    expect(buttons[1]).toHaveAttribute("tabindex", "-1");
  });

  it("sets tabIndex 0 on label button when label is provided", () => {
    render(<RadioButton {...defaultProps} />);
    const buttons = screen.getAllByRole("button");
    expect(buttons[1]).toHaveAttribute("tabindex", "0");
  });

  it("has the correct displayName", () => {
    expect(RadioButton.displayName).toBe("RadioButton");
  });
});
