import "@testing-library/jest-dom";

import { Accordion } from "./index";

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

// Mock dependencies
jest.mock("@shared/components/button", () => ({
  Button: ({ children, onClick, ...props }: any) => (
    <button onClick={onClick} {...props}>
      {children}
    </button>
  ),
}));

jest.mock("@shared/components/collapse", () => ({
  Collapse: ({ open, children }: any) => (
    <div data-testid="collapse" data-open={open}>
      {open ? children : null}
    </div>
  ),
}));

jest.mock("@shared/components/material-icon", () => ({
  MaterialIcon: ({ name, className }: any) => (
    <span data-testid="material-icon" data-name={name} className={className}>
      {name}
    </span>
  ),
}));

jest.mock("@shared/utils", () => ({
  cx: (...args: any[]) => args.filter(Boolean).join(" "),
}));

describe("Accordion", () => {
  const defaultProps = {
    title: "Accordion Title",
    children: <p>Accordion content</p>,
  };

  it("renders without crashing", () => {
    render(<Accordion {...defaultProps} />);
    expect(screen.getByText("Accordion Title")).toBeInTheDocument();
  });

  it("has displayName set to Accordion", () => {
    expect(Accordion.displayName).toBe("Accordion");
  });

  describe("initial state", () => {
    it("starts closed by default", () => {
      render(<Accordion {...defaultProps} />);
      const collapse = screen.getByTestId("collapse");
      expect(collapse).toHaveAttribute("data-open", "false");
    });

    it("starts open when defaultOpen is true", () => {
      render(<Accordion {...defaultProps} defaultOpen={true} />);
      const collapse = screen.getByTestId("collapse");
      expect(collapse).toHaveAttribute("data-open", "true");
    });

    it("starts closed when defaultOpen is false", () => {
      render(<Accordion {...defaultProps} defaultOpen={false} />);
      const collapse = screen.getByTestId("collapse");
      expect(collapse).toHaveAttribute("data-open", "false");
    });
  });

  describe("openOnlyOnDesktop", () => {
    it("opens on desktop (width >= 1024)", () => {
      Object.defineProperty(window, "innerWidth", {
        writable: true,
        value: 1024,
      });
      render(<Accordion {...defaultProps} openOnlyOnDesktop={true} />);
      const collapse = screen.getByTestId("collapse");
      expect(collapse).toHaveAttribute("data-open", "true");
    });

    it("stays closed on mobile (width < 1024)", () => {
      Object.defineProperty(window, "innerWidth", {
        writable: true,
        value: 768,
      });
      render(<Accordion {...defaultProps} openOnlyOnDesktop={true} />);
      const collapse = screen.getByTestId("collapse");
      expect(collapse).toHaveAttribute("data-open", "false");
    });

    it("ignores defaultOpen when openOnlyOnDesktop is true", () => {
      Object.defineProperty(window, "innerWidth", {
        writable: true,
        value: 500,
      });
      render(
        <Accordion
          {...defaultProps}
          openOnlyOnDesktop={true}
          defaultOpen={true}
        />
      );
      const collapse = screen.getByTestId("collapse");
      expect(collapse).toHaveAttribute("data-open", "false");
    });
  });

  describe("toggle behavior", () => {
    it("opens when button is clicked while closed", () => {
      render(<Accordion {...defaultProps} />);
      const button = screen.getByRole("button");
      fireEvent.click(button);
      const collapse = screen.getByTestId("collapse");
      expect(collapse).toHaveAttribute("data-open", "true");
    });

    it("closes when button is clicked while open", () => {
      render(<Accordion {...defaultProps} defaultOpen={true} />);
      const button = screen.getByRole("button");
      fireEvent.click(button);
      const collapse = screen.getByTestId("collapse");
      expect(collapse).toHaveAttribute("data-open", "false");
    });

    it("toggles multiple times", () => {
      render(<Accordion {...defaultProps} />);
      const button = screen.getByRole("button");
      const collapse = screen.getByTestId("collapse");

      fireEvent.click(button);
      expect(collapse).toHaveAttribute("data-open", "true");

      fireEvent.click(button);
      expect(collapse).toHaveAttribute("data-open", "false");

      fireEvent.click(button);
      expect(collapse).toHaveAttribute("data-open", "true");
    });
  });

  describe("icon state", () => {
    it("shows keyboard_arrow_down when closed", () => {
      render(<Accordion {...defaultProps} />);
      const icon = screen.getByTestId("material-icon");
      expect(icon).toHaveAttribute("data-name", "keyboard_arrow_down");
    });

    it("shows keyboard_arrow_up when open", () => {
      render(<Accordion {...defaultProps} defaultOpen={true} />);
      const icon = screen.getByTestId("material-icon");
      expect(icon).toHaveAttribute("data-name", "keyboard_arrow_up");
    });

    it("toggles icon when clicked", () => {
      render(<Accordion {...defaultProps} />);
      const button = screen.getByRole("button");
      const icon = screen.getByTestId("material-icon");

      expect(icon).toHaveAttribute("data-name", "keyboard_arrow_down");
      fireEvent.click(button);
      expect(icon).toHaveAttribute("data-name", "keyboard_arrow_up");
    });
  });

  describe("children rendering", () => {
    it("renders children when open", () => {
      render(<Accordion {...defaultProps} defaultOpen={true} />);
      expect(screen.getByText("Accordion content")).toBeInTheDocument();
    });

    it("does not render children when closed", () => {
      render(<Accordion {...defaultProps} />);
      expect(screen.queryByText("Accordion content")).not.toBeInTheDocument();
    });

    it("renders complex children", () => {
      render(
        <Accordion title="Test">
          <div data-testid="child-1">Child 1</div>
          <div data-testid="child-2">Child 2</div>
        </Accordion>
      );
      const button = screen.getByRole("button");
      fireEvent.click(button);
      expect(screen.getByTestId("child-1")).toBeInTheDocument();
      expect(screen.getByTestId("child-2")).toBeInTheDocument();
    });
  });

  describe("className props", () => {
    it("applies containerClassName to outer div", () => {
      const { container } = render(
        <Accordion {...defaultProps} containerClassName="custom-container" />
      );
      expect(container.firstChild).toHaveClass("custom-container");
    });

    it("applies titleClassName to title span", () => {
      render(<Accordion {...defaultProps} titleClassName="custom-title" />);
      const titleSpan = screen.getByText("Accordion Title");
      expect(titleSpan).toHaveClass("custom-title");
    });

    it("applies buttonClassName to button", () => {
      render(<Accordion {...defaultProps} buttonClassName="custom-button" />);
      const button = screen.getByRole("button");
      expect(button.className).toContain("custom-button");
    });

    it("applies iconClassName to material icon", () => {
      render(<Accordion {...defaultProps} iconClassName="custom-icon" />);
      const icon = screen.getByTestId("material-icon");
      expect(icon).toHaveClass("custom-icon");
    });

    it("applies className to content div when open", () => {
      render(
        <Accordion
          {...defaultProps}
          defaultOpen={true}
          className="custom-content"
        />
      );
      const contentDiv = screen.getByText("Accordion content").parentElement;
      expect(contentDiv).toHaveClass("custom-content");
    });
  });

  describe("borderRadiusNone", () => {
    it("applies rounded-none when borderRadiusNone is true", () => {
      const { container } = render(
        <Accordion {...defaultProps} borderRadiusNone={true} />
      );
      expect(container.firstChild).toHaveClass("rounded-none");
    });

    it("applies rounded-surface-xs when borderRadiusNone is false", () => {
      const { container } = render(
        <Accordion {...defaultProps} borderRadiusNone={false} />
      );
      expect(container.firstChild).toHaveClass("rounded-surface-xs");
    });

    it("applies rounded-surface-xs by default", () => {
      const { container } = render(<Accordion {...defaultProps} />);
      expect(container.firstChild).toHaveClass("rounded-surface-xs");
    });

    it("applies rounded-none to button when borderRadiusNone is true", () => {
      render(<Accordion {...defaultProps} borderRadiusNone={true} />);
      const button = screen.getByRole("button");
      expect(button.className).toContain("rounded-none");
    });

    it("applies rounded-t-surface-xs to button when borderRadiusNone is false", () => {
      render(<Accordion {...defaultProps} borderRadiusNone={false} />);
      const button = screen.getByRole("button");
      expect(button.className).toContain("rounded-t-surface-xs");
    });
  });

  describe("button attributes", () => {
    it("renders button with type button", () => {
      render(<Accordion {...defaultProps} />);
      const button = screen.getByRole("button");
      expect(button).toHaveAttribute("type", "button");
    });
  });
});
