import { fireEvent, render } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { Accordion } from "../Accordion";
import AccordionStatic from "../Accordion.static";
import AccordionHeader from "../AccordionHeader";
import { AccordionItem } from "../AccordionItem";
import HeadingContext from "../HeadingContext";
import testData from "./data";

// Helper function to initialize accordion static behavior
const initializeAccordion = (container) => {
  const accordionElement = container.querySelector('[data-accordion="true"]');
  if (accordionElement && !accordionElement.ODS_Accordion) {
    new AccordionStatic(accordionElement);
  }
  return accordionElement;
};

// Helper to wait for accordion to be initialized and working
const waitForAccordionInteractivity = async (container) => {
  const accordionElement = initializeAccordion(container);

  // Small delay to ensure event listeners are attached
  await new Promise((resolve) => setTimeout(resolve, 0));
  return accordionElement;
};

const TestingAccordion = () => (
  <Accordion data-testid="test-id">
    <AccordionItem title="title-1" data-testid="item-test-id-1" id="item-1">
      text-1
    </AccordionItem>
    <AccordionItem title="title-2" data-testid="item-test-id-2" id="item-2">
      text-2
    </AccordionItem>
  </Accordion>
);

const TestingAccordionWithData = () => (
  <Accordion data-testid="test-id">
    {testData.map((item, index) => (
      <AccordionItem
        key={index}
        title={item.title}
        data-testid={`item-${index}`}
        id={`item-${index}`}
      >
        {item.children}
      </AccordionItem>
    ))}
  </Accordion>
);

describe("Accordion Component Tests", () => {
  describe("Accordion Component", () => {
    describe("initial state", () => {
      it("has default class accordion", () => {
        const { getByTestId } = render(<Accordion data-testid="test-id" />);
        expect(getByTestId("test-id")).toHaveClass("accordion");
      });

      it("renders as ul element with data-accordion attribute", () => {
        const { getByTestId } = render(<Accordion data-testid="test-id" />);
        const accordion = getByTestId("test-id");
        expect(accordion.tagName).toBe("UL");
        expect(accordion).toHaveAttribute("data-accordion");
      });

      it("has default heading level of 3", () => {
        const { container } = render(<TestingAccordion />);
        const headers = container.querySelectorAll("h3");
        expect(headers).toHaveLength(2);
      });
    });

    describe("props and variants", () => {
      it("applies custom heading level", () => {
        const { container } = render(
          <Accordion headingLevel={2} data-testid="test-id">
            <AccordionItem
              title="title-1"
              data-testid="item-test-id-1"
              id="item-1"
            >
              text-1
            </AccordionItem>
          </Accordion>,
        );
        const headers = container.querySelectorAll("h2");
        expect(headers).toHaveLength(1);
      });

      it("applies large size class", () => {
        const { getByTestId } = render(
          <Accordion size="large" data-testid="test-id" />,
        );
        expect(getByTestId("test-id")).toHaveClass("accordion--large");
      });

      it("applies enclosed class", () => {
        const { getByTestId } = render(
          <Accordion isEnclosed data-testid="test-id" />,
        );
        expect(getByTestId("test-id")).toHaveClass("accordion--enclosed");
      });

      it("applies no top border class", () => {
        const { getByTestId } = render(
          <Accordion noTopBorder data-testid="test-id" />,
        );
        expect(getByTestId("test-id")).toHaveClass("accordion--no-top-border");
      });

      it("applies custom className", () => {
        const { getByTestId } = render(
          <Accordion className="custom-class" data-testid="test-id" />,
        );
        expect(getByTestId("test-id")).toHaveClass("custom-class");
      });

      it("passes additional props to ul element", () => {
        const { getByTestId } = render(
          <Accordion data-testid="test-id" data-custom="value" />,
        );
        expect(getByTestId("test-id")).toHaveAttribute("data-custom", "value");
      });
    });

    describe("rendering with test data", () => {
      it("renders all items from data.js", () => {
        const { getByText } = render(<TestingAccordionWithData />);

        testData.forEach((item) => {
          expect(getByText(item.title)).toBeInTheDocument();
          expect(getByText(item.children)).toBeInTheDocument();
        });
      });

      it("renders correct number of accordion items", () => {
        const { container } = render(<TestingAccordionWithData />);
        const items = container.querySelectorAll(".accordion__item");
        expect(items).toHaveLength(testData.length);
      });
    });

    describe("mouse interactions", () => {
      let accordion;
      beforeEach(async () => {
        accordion = render(<TestingAccordion />);
        // Initialize static accordion behavior
        await waitForAccordionInteractivity(accordion.container);
      });

      it("AccordionItem div has hidden attribute set to false after button click", () => {
        const { getByTestId, getByText } = accordion;
        fireEvent.click(getByTestId("item-test-id-1"));
        expect(getByText("text-1")).not.toHaveAttribute("hidden");
      });

      it("AccordionItem div has hidden attribute set to true after two button clicks", () => {
        const { getByTestId, getByText } = accordion;
        fireEvent.click(getByTestId("item-test-id-1"));
        fireEvent.click(getByTestId("item-test-id-1"));
        expect(getByText("text-1")).toHaveAttribute("hidden");
      });

      it("multiple items can be opened simultaneously", () => {
        const { getByTestId, getByText } = accordion;
        fireEvent.click(getByTestId("item-test-id-1"));
        fireEvent.click(getByTestId("item-test-id-2"));

        expect(getByText("text-1")).not.toHaveAttribute("hidden");
        expect(getByText("text-2")).not.toHaveAttribute("hidden");
        expect(
          getByTestId("item-test-id-1").getAttribute("aria-expanded"),
        ).toBe("true");
        expect(
          getByTestId("item-test-id-2").getAttribute("aria-expanded"),
        ).toBe("true");
      });

      it("scrolls modal dialog to clicked accordion button when inside modal", async () => {
        accordion.unmount();

        const { container, getByTestId } = render(
          <div className="modal__dialog">
            <div className="modal__header" />
            <TestingAccordion />
          </div>,
        );

        await waitForAccordionInteractivity(container);

        const modalDialog = container.querySelector(".modal__dialog");
        const modalHeader = container.querySelector(".modal__header");
        const button = getByTestId("item-test-id-1");

        modalDialog.scrollTop = 120;
        modalDialog.getBoundingClientRect = vi.fn(() => ({
          top: 40,
        }));
        modalHeader.getBoundingClientRect = vi.fn(() => ({
          bottom: 120,
        }));
        button.getBoundingClientRect = vi.fn(() => ({
          top: 170,
        }));
        modalDialog.scrollTo = vi.fn();

        const rafSpy = vi
          .spyOn(window, "requestAnimationFrame")
          .mockImplementation((callback) => {
            callback();
            return 1;
          });

        fireEvent.click(getByTestId("item-test-id-1"));

        expect(modalDialog.scrollTo).toHaveBeenCalledWith({
          top: 162,
          behavior: "smooth",
        });

        rafSpy.mockRestore();
      });

      it("does not scroll when accordion is outside modal dialog", async () => {
        const { getByTestId } = accordion;

        const rafSpy = vi.spyOn(window, "requestAnimationFrame");

        fireEvent.click(getByTestId("item-test-id-1"));

        expect(rafSpy).not.toHaveBeenCalled();

        rafSpy.mockRestore();
      });

      it("scrolls to the clicked button when multiple items are open", async () => {
        accordion.unmount();

        const { container, getByTestId } = render(
          <div className="modal__dialog">
            <div className="modal__header" />
            <TestingAccordion />
          </div>,
        );

        await waitForAccordionInteractivity(container);

        const modalDialog = container.querySelector(".modal__dialog");
        const modalHeader = container.querySelector(".modal__header");
        const firstButton = getByTestId("item-test-id-1");
        const secondButton = getByTestId("item-test-id-2");

        modalDialog.scrollTop = 50;
        modalDialog.getBoundingClientRect = vi.fn(() => ({
          top: 20,
        }));
        modalHeader.getBoundingClientRect = vi.fn(() => ({
          bottom: 100,
        }));
        firstButton.getBoundingClientRect = vi.fn(() => ({
          top: 120,
        }));
        secondButton.getBoundingClientRect = vi.fn(() => ({
          top: 260,
        }));
        modalDialog.scrollTo = vi.fn();

        const rafSpy = vi
          .spyOn(window, "requestAnimationFrame")
          .mockImplementation((callback) => {
            callback();
            return 1;
          });

        fireEvent.click(firstButton);
        fireEvent.click(secondButton);

        expect(firstButton.getAttribute("aria-expanded")).toBe("true");
        expect(secondButton.getAttribute("aria-expanded")).toBe("true");
        expect(modalDialog.scrollTo).toHaveBeenLastCalledWith({
          top: 202,
          behavior: "smooth",
        });

        rafSpy.mockRestore();
      });
    });

    describe("keyboard interactions", () => {
      let accordion;
      beforeEach(async () => {
        window.document.getSelection = vi.fn();
        accordion = render(<TestingAccordion />);
        // Initialize static accordion behavior
        await waitForAccordionInteractivity(accordion.container);
      });

      it("AccordionItem focus changes after tab press", async () => {
        const { getByTestId } = accordion;
        let accordionItem1 = getByTestId("item-test-id-1");
        let accordionItem2 = getByTestId("item-test-id-2");
        accordionItem1.focus();
        expect(accordionItem1).toHaveFocus();
        await userEvent.tab();
        expect(accordionItem2).toHaveFocus();
      });

      it("space key toggles accordion item", async () => {
        const { getByTestId, getByText } = accordion;
        let accordionItem1 = getByTestId("item-test-id-1");
        accordionItem1.focus();

        await userEvent.keyboard(" ");
        expect(getByText("text-1").hidden).toBe(false);
        expect(
          getByTestId("item-test-id-1").getAttribute("aria-expanded"),
        ).toBe("true");

        await userEvent.keyboard(" ");
        expect(getByText("text-1").hidden).toBe(true);
        expect(
          getByTestId("item-test-id-1").getAttribute("aria-expanded"),
        ).toBe("false");
      });
    });

    describe("accessibility features", () => {
      it("has proper ARIA attributes", () => {
        const { getByTestId } = render(<TestingAccordion />);
        const button = getByTestId("item-test-id-1");
        const section = getByTestId("item-test-id-1").nextElementSibling;

        expect(button).toHaveAttribute("aria-controls", "item-1-section");
        const ariaExpanded = button.getAttribute("aria-expanded");
        expect([null, "false"]).toContain(ariaExpanded);
        if (section) {
          expect(section).toHaveAttribute("aria-labelledby", "item-1");
          expect(section).toHaveAttribute("id", "item-1-section");
        }
      });
    });

    describe("edge cases", () => {
      it("handles empty accordion gracefully", () => {
        const { getByTestId } = render(<Accordion data-testid="test-id" />);
        expect(getByTestId("test-id")).toBeInTheDocument();
      });

      it("handles accordion with single item", () => {
        const { getByText } = render(
          <Accordion>
            <AccordionItem title="Single Item" id="single">
              Single content
            </AccordionItem>
          </Accordion>,
        );
        expect(getByText("Single Item")).toBeInTheDocument();
        expect(getByText("Single content")).toBeInTheDocument();
      });
    });
  });

  describe("AccordionItem Component", () => {
    describe("initial state and context provider", () => {
      let accordionItem;

      beforeEach(() => {
        accordionItem = render(
          <HeadingContext.Provider value={1}>
            <AccordionItem title="Test Title" />
          </HeadingContext.Provider>,
        );
      });

      it("renders list item with class accordion__item", () => {
        const { container } = accordionItem;
        expect(container.querySelector("li")).toBeInTheDocument();
        expect(container.querySelector("li")).toHaveClass("accordion__item");
      });

      it("renders div with class accordion__body", () => {
        const { container } = accordionItem;
        expect(container.querySelector("div")).toBeInTheDocument();
        expect(container.querySelector("div")).toHaveClass("accordion__body");
      });

      it("renders AccordionHeader component with h1 heading when value 1 is provided by context", () => {
        const { container } = accordionItem;
        expect(container.querySelector("h1")).toBeInTheDocument();
        expect(container.querySelector("h1")).toHaveClass("accordion__header");
      });

      it("div has hidden attribute set to true when isActive is not passed", () => {
        const { container } = accordionItem;
        expect(container.querySelector("div").hidden).toBeTruthy();
      });
    });

    describe("props and functionality", () => {
      it("renders children inside div", () => {
        const { container } = render(
          <HeadingContext.Provider value={1}>
            <AccordionItem title="Test">test content</AccordionItem>
          </HeadingContext.Provider>,
        );
        expect(container.querySelector("div").textContent).toBe("test content");
      });

      it("renders title when title is passed", () => {
        const { getByText } = render(
          <HeadingContext.Provider value={1}>
            <AccordionItem title="test-title" />
          </HeadingContext.Provider>,
        );
        expect(getByText("test-title")).toBeInTheDocument();
      });

      it("button has aria-expanded attribute set to true when isActive is passed", () => {
        const { container } = render(
          <HeadingContext.Provider value={1}>
            <AccordionItem isActive title="Test" />
          </HeadingContext.Provider>,
        );
        expect(
          container.querySelector("button").getAttribute("aria-expanded"),
        ).toBe("true");
      });

      it("div has hidden attribute set to false when isActive is passed", () => {
        const { container } = render(
          <HeadingContext.Provider value={1}>
            <AccordionItem isActive title="Test" />
          </HeadingContext.Provider>,
        );
        expect(container.querySelector("div").hidden).toBeFalsy();
      });

      it("div has additional class is-active when isActive is passed", () => {
        const { container } = render(
          <HeadingContext.Provider value={1}>
            <AccordionItem isActive title="Test" />
          </HeadingContext.Provider>,
        );
        expect(container.querySelector("div")).toHaveClass("accordion__body");
        expect(container.querySelector("div")).toHaveClass("is-active");
      });

      it("renders custom header when renderHeader is passed", () => {
        const renderHeader = (title, currentId, isActive) => (
          <p id={currentId} aria-expanded={isActive}>
            {title}
          </p>
        );
        const { container } = render(
          <HeadingContext.Provider value={1}>
            <AccordionItem
              renderHeader={(title, currentId, isActive) =>
                renderHeader(title, currentId, isActive)
              }
              title="test-title"
            />
          </HeadingContext.Provider>,
        );
        expect(container.querySelector("h1")).not.toBeInTheDocument();
        expect(container.querySelector("p")).toBeInTheDocument();
        expect(container.querySelector("p").textContent).toBe("test-title");
      });
    });

    describe("state management", () => {
      it("toggles isActive state correctly", () => {
        const { rerender, container } = render(
          <HeadingContext.Provider value={1}>
            <AccordionItem title="Test" isActive={false} />
          </HeadingContext.Provider>,
        );

        // Initially inactive
        expect(container.querySelector("div")).toHaveClass("accordion__body");
        expect(container.querySelector("div")).not.toHaveClass("is-active");
        expect(container.querySelector("div").hidden).toBe(true);
        expect(
          container.querySelector("button").getAttribute("aria-expanded"),
        ).toBe("false");

        // Change to active
        rerender(
          <HeadingContext.Provider value={1}>
            <AccordionItem title="Test" isActive={true} />
          </HeadingContext.Provider>,
        );

        expect(container.querySelector("div")).toHaveClass("is-active");
        expect(container.querySelector("div").hidden).toBe(false);
        expect(
          container.querySelector("button").getAttribute("aria-expanded"),
        ).toBe("true");
      });
    });
  });

  describe("AccordionHeader Component", () => {
    describe("initial state and context provider", () => {
      let accordionHeader;

      beforeEach(() => {
        accordionHeader = render(
          <HeadingContext.Provider value={1}>
            <AccordionHeader
              data-testid="test-id"
              id="test-id"
              title="Test Title"
            />
          </HeadingContext.Provider>,
        );
      });

      it("renders button with default class accordion__button", () => {
        const { getByTestId } = accordionHeader;
        expect(getByTestId("test-id").tagName).toBe("BUTTON");
        expect(getByTestId("test-id")).toHaveClass("accordion__button");
      });

      it("renders button with type button", () => {
        const { getByTestId } = accordionHeader;
        expect(getByTestId("test-id").tagName).toBe("BUTTON");
        expect(getByTestId("test-id").getAttribute("type")).toBe("button");
      });

      it("renders button with data-accordion-toggle attribute set to true", () => {
        const { getByTestId } = accordionHeader;
        expect(getByTestId("test-id").tagName).toBe("BUTTON");
        expect(
          getByTestId("test-id").getAttribute("data-accordion-toggle"),
        ).toBeTruthy();
      });

      it("renders button with data-accordion-toggle attribute", () => {
        const { getByTestId } = accordionHeader;
        expect(
          getByTestId("test-id").getAttribute("data-accordion-toggle"),
        ).toBeTruthy();
      });

      it("renders button without data-toggle attribute (uses Accordion.static for toggle logic)", () => {
        const { getByTestId } = accordionHeader;
        const toggleAttribute =
          getByTestId("test-id").getAttribute("data-toggle");
        expect(toggleAttribute).toBeNull();
      });

      it("renders h1 header when value 1 is provided by context", () => {
        const { container } = accordionHeader;
        expect(container.querySelector("h1")).toBeInTheDocument();
      });

      it("header has class accordion__header", () => {
        const { container } = accordionHeader;
        expect(container.querySelector("h1")).toBeInTheDocument();
        expect(container.querySelector("h1")).toHaveClass("accordion__header");
      });

      it("renders span with class accordion__title", () => {
        const { container } = accordionHeader;
        expect(container.querySelector("span")).toBeInTheDocument();
        expect(container.querySelector("span")).toHaveClass("accordion__title");
      });

      it("renders icon with correct classes", () => {
        const { container } = accordionHeader;
        expect(container.querySelector("svg")).toBeInTheDocument();
        expect(container.querySelector("svg")).toHaveClass("icon--medium");
        expect(container.querySelector("svg")).toHaveClass("accordion__icon");
      });
    });

    describe("props and functionality", () => {
      it("renders title inside span element", () => {
        const { container } = render(
          <HeadingContext.Provider value={1}>
            <AccordionHeader
              id="test-id"
              title="test-title"
              isActive
              className="test-class"
            />
          </HeadingContext.Provider>,
        );
        expect(container.querySelector("span")).toBeInTheDocument();
        expect(container.querySelector("span")).toHaveTextContent("test-title");
      });

      it("renders button with aria-expanded attribute set to true when isActive prop is passed", () => {
        const { container } = render(
          <HeadingContext.Provider value={1}>
            <AccordionHeader id="test-id" title="test-title" isActive />
          </HeadingContext.Provider>,
        );
        expect(container.querySelector("button")).toBeInTheDocument();
        expect(
          container.querySelector("button").getAttribute("aria-expanded"),
        ).toBe("true");
      });

      it("renders button with aria-controls attribute set to test-id-section when id prop is set to test-id", () => {
        const { container } = render(
          <HeadingContext.Provider value={1}>
            <AccordionHeader id="test-id" title="test-title" />
          </HeadingContext.Provider>,
        );
        expect(container.querySelector("button")).toBeInTheDocument();
        expect(
          container.querySelector("button").getAttribute("aria-controls"),
        ).toBe("test-id-section");
      });

      it("renders button with id attribute set to id prop", () => {
        const { container } = render(
          <HeadingContext.Provider value={1}>
            <AccordionHeader id="test-id" title="test-title" />
          </HeadingContext.Provider>,
        );
        expect(container.querySelector("button")).toBeInTheDocument();
        expect(container.querySelector("button").getAttribute("id")).toBe(
          "test-id",
        );
      });
    });

    describe("heading level context variations", () => {
      it("renders h2 when context value is 2", () => {
        const { container } = render(
          <HeadingContext.Provider value={2}>
            <AccordionHeader id="test" title="Test" />
          </HeadingContext.Provider>,
        );
        expect(container.querySelector("h2")).toBeInTheDocument();
        expect(container.querySelector("h2")).toHaveClass("accordion__header");
      });

      it("renders h6 when context value is 6", () => {
        const { container } = render(
          <HeadingContext.Provider value={6}>
            <AccordionHeader id="test" title="Test" />
          </HeadingContext.Provider>,
        );
        expect(container.querySelector("h6")).toBeInTheDocument();
        expect(container.querySelector("h6")).toHaveClass("accordion__header");
      });

      it("defaults to h3 when no context is provided", () => {
        const { container } = render(
          <AccordionHeader id="test" title="Test" />,
        );
        expect(container.querySelector("h3")).toBeInTheDocument();
        expect(container.querySelector("h3")).toHaveClass("accordion__header");
      });
    });

    describe("state management", () => {
      it("toggles isActive state correctly", () => {
        const { rerender, container } = render(
          <HeadingContext.Provider value={1}>
            <AccordionHeader id="test-id" title="Test" isActive={false} />
          </HeadingContext.Provider>,
        );

        // Initially inactive
        expect(
          container.querySelector("button").getAttribute("aria-expanded"),
        ).toBe("false");

        // Change to active
        rerender(
          <HeadingContext.Provider value={1}>
            <AccordionHeader id="test-id" title="Test" isActive={true} />
          </HeadingContext.Provider>,
        );

        expect(
          container.querySelector("button").getAttribute("aria-expanded"),
        ).toBe("true");
      });
    });
  });

  describe("Integration Tests", () => {
    describe("complex accordion scenarios", () => {
      it("renders accordion with all variants and props", () => {
        const { container } = render(
          <Accordion
            headingLevel={2}
            size="large"
            isEnclosed
            className="custom-accordion"
            data-testid="complex-accordion"
          >
            <AccordionItem
              title="Active Item"
              id="active-item"
              isActive={true}
              className="custom-item"
            >
              <p>Active content</p>
            </AccordionItem>
            <AccordionItem
              title="Inactive Item"
              id="inactive-item"
              isActive={false}
            >
              <p>Inactive content</p>
            </AccordionItem>
          </Accordion>,
        );

        // Check accordion classes
        const accordion = container.querySelector(".accordion");
        expect(accordion).toHaveClass("accordion--large");
        expect(accordion).toHaveClass("accordion--enclosed");
        expect(accordion).toHaveClass("custom-accordion");

        // Check heading level
        const headers = container.querySelectorAll("h2");
        expect(headers).toHaveLength(2);

        // Check active item
        const activeItem = container.querySelector("#active-item");
        const activeSection = container.querySelector("#active-item-section");
        expect(activeItem.getAttribute("aria-expanded")).toBe("true");
        expect(activeSection).toHaveClass("is-active");
        expect(activeSection.hidden).toBe(false);

        // Check inactive item
        const inactiveItem = container.querySelector("#inactive-item");
        const inactiveSection = container.querySelector(
          "#inactive-item-section",
        );
        expect(inactiveItem.getAttribute("aria-expanded")).toBe("false");
        expect(inactiveSection).not.toHaveClass("is-active");
        expect(inactiveSection.hidden).toBe(true);
      });

      it("handles multiple accordion items with complex interactions", async () => {
        const user = userEvent.setup();

        const { getByText, getByTestId, container } = render(
          <Accordion data-testid="multi-accordion">
            {testData.map((item, index) => (
              <AccordionItem
                key={index}
                title={item.title}
                data-testid={`item-${index}`}
                id={`item-${index}`}
              >
                {item.children}
              </AccordionItem>
            ))}
          </Accordion>,
        );

        // Initialize static accordion behavior
        await waitForAccordionInteractivity(container);

        // Open first item
        await user.click(getByTestId("item-0"));
        expect(getByText(testData[0].children)).toBeVisible();
        expect(getByTestId("item-0").getAttribute("aria-expanded")).toBe(
          "true",
        );

        // Open second item
        await user.click(getByTestId("item-1"));
        expect(getByText(testData[1].children)).toBeVisible();
        expect(getByTestId("item-1").getAttribute("aria-expanded")).toBe(
          "true",
        );

        // First item should still be open
        expect(getByText(testData[0].children)).toBeVisible();
        expect(getByTestId("item-0").getAttribute("aria-expanded")).toBe(
          "true",
        );

        // Close first item
        await user.click(getByTestId("item-0"));
        expect(getByText(testData[0].children)).not.toBeVisible();
        expect(getByTestId("item-0").getAttribute("aria-expanded")).toBe(
          "false",
        );

        // Second item should still be open
        expect(getByText(testData[1].children)).toBeVisible();
        expect(getByTestId("item-1").getAttribute("aria-expanded")).toBe(
          "true",
        );
      });
    });

    describe("custom header rendering", () => {
      it("renders custom header with complex layout", () => {
        const CustomHeader = ({ title, currentId, isActive }) => (
          <div className="custom-header" data-testid="custom-header">
            <div className="header-content">
              <h3>{title}</h3>
              <span className="status">{isActive ? "Open" : "Closed"}</span>
            </div>
            <button
              className="custom-button"
              aria-expanded={isActive}
              aria-controls={`${currentId}-section`}
              id={currentId}
              data-accordion-toggle
            >
              Toggle
            </button>
          </div>
        );

        const { getByTestId } = render(
          <Accordion>
            <AccordionItem
              title="Custom Header Item"
              renderHeader={CustomHeader}
              isActive={false}
            >
              <p>Custom header content</p>
            </AccordionItem>
          </Accordion>,
        );

        const customHeader = getByTestId("custom-header");
        expect(customHeader).toBeInTheDocument();
        expect(customHeader.querySelector(".status")).toHaveTextContent(
          "Closed",
        );
        const customButton = customHeader.querySelector(".custom-button");
        const ariaExpanded = customButton.getAttribute("aria-expanded");
        expect([null, "false"]).toContain(ariaExpanded);
      });
    });

    describe("keyboard navigation scenarios", () => {
      it("handles keyboard activation of items", async () => {
        const user = userEvent.setup();

        const { getByTestId, getByText, container } = render(
          <Accordion>
            {testData.map((item, index) => (
              <AccordionItem
                key={index}
                title={item.title}
                data-testid={`item-${index}`}
                id={`item-${index}`}
              >
                {item.children}
              </AccordionItem>
            ))}
          </Accordion>,
        );

        // Initialize static accordion behavior
        await waitForAccordionInteractivity(container);

        const firstItem = getByTestId("item-0");
        firstItem.focus();

        // Activate with Enter
        await user.keyboard("{Enter}");
        expect(getByText(testData[0].children)).toBeVisible();
        expect(firstItem.getAttribute("aria-expanded")).toBe("true");

        // Deactivate with Enter
        await user.keyboard("{Enter}");
        expect(getByText(testData[0].children)).not.toBeVisible();
        expect(firstItem.getAttribute("aria-expanded")).toBe("false");

        // Activate with Space
        await user.keyboard(" ");
        expect(getByText(testData[0].children)).toBeVisible();
        expect(firstItem.getAttribute("aria-expanded")).toBe("true");

        // Deactivate with Space
        await user.keyboard(" ");
        expect(getByText(testData[0].children)).not.toBeVisible();
        expect(firstItem.getAttribute("aria-expanded")).toBe("false");
      });
    });

    describe("accessibility integration", () => {
      it("maintains proper ARIA relationships", () => {
        const { container } = render(
          <Accordion>
            <AccordionItem title="Item 1" id="item1">
              <p>Content 1</p>
            </AccordionItem>
            <AccordionItem title="Item 2" id="item2">
              <p>Content 2</p>
            </AccordionItem>
          </Accordion>,
        );

        const buttons = container.querySelectorAll("button");

        buttons.forEach((button, index) => {
          const sectionId = `item${index + 1}-section`;
          const section = container.querySelector(`#${sectionId}`);

          expect(button).toHaveAttribute("aria-controls", sectionId);
          expect(section).toHaveAttribute(
            "aria-labelledby",
            `item${index + 1}`,
          );
          expect(button).toHaveAttribute("id", `item${index + 1}`);
        });
      });
    });

    describe("performance and edge cases", () => {
      it("handles large number of items", () => {
        const manyItems = Array.from({ length: 100 }, (_, i) => ({
          title: `Item ${i + 1}`,
          content: `Content for item ${i + 1}`,
        }));

        const { container, getByText } = render(
          <Accordion>
            {manyItems.map((item, index) => (
              <AccordionItem
                key={index}
                title={item.title}
                id={`item-${index}`}
              >
                {item.content}
              </AccordionItem>
            ))}
          </Accordion>,
        );

        const items = container.querySelectorAll(".accordion__item");
        expect(items).toHaveLength(100);

        // Check first and last items are rendered
        expect(getByText("Item 1")).toBeInTheDocument();
        expect(getByText("Item 100")).toBeInTheDocument();
        expect(getByText("Content for item 1")).toBeInTheDocument();
        expect(getByText("Content for item 100")).toBeInTheDocument();
      });

      it("handles rapid state changes", async () => {
        const user = userEvent.setup();

        const { getByTestId, container } = render(
          <Accordion>
            <AccordionItem
              title="Rapid Item"
              data-testid="rapid-item"
              id="rapid"
            >
              Rapid content
            </AccordionItem>
          </Accordion>,
        );

        // Initialize static accordion behavior
        await waitForAccordionInteractivity(container);

        const item = getByTestId("rapid-item");

        // Rapidly click the item
        for (let i = 0; i < 10; i++) {
          await user.click(item);
        }

        // Should end up in a consistent state
        const finalState = item.getAttribute("aria-expanded");
        expect(["true", "false", null]).toContain(finalState);
      });
    });
  });
});
