import React from "react";
import { Footer } from "./index";
import { FooterProps } from "./types";

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

// Mock dependencies
jest.mock("@shared/components/divider", () => ({
  Divider: ({ className }: { className?: string }) => (
    <hr data-testid="divider" className={className} />
  ),
}));

jest.mock("@shared/components/text", () => ({
  Text: ({ as: Tag = "span", children, className }: any) => (
    <Tag className={className}>{children}</Tag>
  ),
}));

jest.mock("../button", () => ({
  Button: ({
    onClick,
    linkClassName,
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    linkVariant,
    buttonLabel,
    ...rest
  }: any) => (
    <button
      data-testid="footer-button"
      className={linkClassName}
      onClick={onClick}
    >
      {buttonLabel || rest.children || "Link"}
    </button>
  ),
}));

const mockLinks = [
  {
    title: "Products",
    items: {
      items: [
        { buttonLabel: "Internet", href: "/internet" },
        { buttonLabel: "TV", href: "/tv" },
        { buttonLabel: "Phone", href: "/phone" },
      ],
    },
  },
  {
    title: "Support",
    items: {
      items: [
        { buttonLabel: "Help Center", href: "/help" },
        { buttonLabel: "Contact Us", href: "/contact" },
      ],
    },
  },
];

const mockBottomLinks = [
  { buttonLabel: "Privacy Policy", href: "/privacy" },
  { buttonLabel: "Terms of Use", href: "/terms" },
  { buttonLabel: "Accessibility", href: "/accessibility" },
];

const defaultProps: FooterProps = {
  body: <p>Promotional content and disclaimers go here.</p>,
  links: mockLinks,
  bottomLinks: mockBottomLinks,
  copyrights: "All rights reserved.",
  terms: "Kinetic by Windstream.",
  maxWidth: true,
};

describe("Footer", () => {
  describe("Rendering", () => {
    it("renders with all props", () => {
      render(<Footer {...defaultProps} />);
      expect(
        screen.getByText("Promotional content and disclaimers go here.")
      ).toBeInTheDocument();
      expect(screen.getByText("Products")).toBeInTheDocument();
      expect(screen.getByText("Support")).toBeInTheDocument();
      expect(screen.getByText("All rights reserved.")).toBeInTheDocument();
    });

    it("renders with minimal props (body only)", () => {
      render(<Footer body={<span>Minimal body</span>} />);
      expect(screen.getByText("Minimal body")).toBeInTheDocument();
    });

    it("renders body content in aside with proper aria-label", () => {
      render(<Footer {...defaultProps} />);
      const aside = screen.getByLabelText("Promotions and disclaimers");
      expect(aside.tagName).toBe("ASIDE");
      expect(aside).toHaveClass("break-words");
    });
  });

  describe("Promotional section (body)", () => {
    it("renders ReactNode body content", () => {
      render(
        <Footer
          body={
            <div data-testid="promo">
              <strong>Big Sale!</strong> Save 50%
            </div>
          }
        />
      );
      expect(screen.getByTestId("promo")).toBeInTheDocument();
      expect(screen.getByText("Save 50%")).toBeInTheDocument();
    });

    it("renders plain text body", () => {
      render(<Footer body="Simple promotional text" />);
      expect(screen.getByText("Simple promotional text")).toBeInTheDocument();
    });
  });

  describe("Footer link groups", () => {
    it("renders link group titles", () => {
      render(<Footer {...defaultProps} />);
      expect(screen.getByText("Products")).toBeInTheDocument();
      expect(screen.getByText("Support")).toBeInTheDocument();
    });

    it("renders all link items within groups", () => {
      render(<Footer {...defaultProps} />);
      const buttons = screen.getAllByTestId("footer-button");
      // 3 Products links + 2 Support links + 3 bottom links = 8
      expect(buttons).toHaveLength(8);
    });

    it("renders nav elements with proper aria-labelledby", () => {
      const { container } = render(<Footer {...defaultProps} />);
      const navs = container.querySelectorAll("nav.site-links-group");
      expect(navs).toHaveLength(2);
      expect(navs[0]).toHaveAttribute("aria-labelledby", "footer-Products");
      expect(navs[1]).toHaveAttribute("aria-labelledby", "footer-Support");
    });

    it("renders no link groups when links is undefined", () => {
      render(<Footer body="No links" />);
      expect(screen.queryByText("Products")).not.toBeInTheDocument();
    });

    it("renders no link groups when links is empty", () => {
      render(<Footer body="No links" links={[]} />);
      expect(screen.queryByText("Products")).not.toBeInTheDocument();
    });

    it("handles link groups with missing title and items gracefully", () => {
      const partialLinks = [
        { title: undefined, items: undefined },
        { title: "Valid", items: { items: undefined } },
        { title: "Also Valid", items: { items: [] } },
      ];
      const { container } = render(
        <Footer body="Partial" links={partialLinks} />
      );
      const navs = container.querySelectorAll("nav.site-links-group");
      expect(navs).toHaveLength(3);
      expect(screen.getByText("Valid")).toBeInTheDocument();
      expect(screen.getByText("Also Valid")).toBeInTheDocument();
    });

    it("renders dividers between link groups on mobile", () => {
      render(<Footer {...defaultProps} />);
      const dividers = screen.getAllByTestId("divider");
      // 1 main divider + 2 mobile dividers (one per link group) + 1 bottom divider = 4
      expect(dividers.length).toBeGreaterThanOrEqual(3);
    });
  });

  describe("Footer layout", () => {
    it("renders with 4-column grid layout", () => {
      const { container } = render(<Footer {...defaultProps} />);
      const grid = container.querySelector(".lg\\:grid-cols-4");
      expect(grid).toBeInTheDocument();
    });

    it("applies inverse background and white text", () => {
      const { container } = render(<Footer {...defaultProps} />);
      expect(container.firstChild).toHaveClass("bg-bg-inverse");
      expect(container.firstChild).toHaveClass("text-white");
    });
  });

  describe("Max width", () => {
    it("applies max-w-120 when maxWidth is true (default)", () => {
      const { container } = render(<Footer {...defaultProps} />);
      const wrapper = container.querySelector(".max-w-120");
      expect(wrapper).toBeInTheDocument();
    });

    it("does not apply max-w-120 when maxWidth is false", () => {
      const { container } = render(
        <Footer {...defaultProps} maxWidth={false} />
      );
      const wrapper = container.querySelector(".max-w-120");
      expect(wrapper).not.toBeInTheDocument();
    });
  });

  describe("Copyright and terms", () => {
    it("renders copyright year with current year", () => {
      render(<Footer {...defaultProps} />);
      const currentYear = new Date().getFullYear().toString();
      const termsEl = screen.getByText(
        content =>
          content.includes(currentYear) &&
          content.includes("Kinetic by Windstream.")
      );
      expect(termsEl).toBeInTheDocument();
    });

    it("renders copyrights text", () => {
      render(<Footer {...defaultProps} />);
      expect(screen.getByText("All rights reserved.")).toBeInTheDocument();
    });

    it("renders terms with copyright symbol", () => {
      render(<Footer {...defaultProps} />);
      const termsEl = screen.getByText(/©.*Kinetic by Windstream/);
      expect(termsEl).toBeInTheDocument();
      expect(termsEl).toHaveClass("terms-text");
    });

    it("renders copyrights with whitespace-pre-line class", () => {
      render(<Footer {...defaultProps} />);
      const copyEl = screen.getByText("All rights reserved.");
      expect(copyEl).toHaveClass("copy-rights");
      expect(copyEl).toHaveClass("whitespace-pre-line");
    });
  });

  describe("Bottom links", () => {
    it("renders bottom links", () => {
      render(<Footer {...defaultProps} />);
      const legalNav = screen.getByLabelText("Footer legal");
      expect(legalNav).toBeInTheDocument();
    });

    it("renders correct number of bottom links", () => {
      render(<Footer {...defaultProps} />);
      const legalNav = screen.getByLabelText("Footer legal");
      const items = legalNav.querySelectorAll("li");
      expect(items).toHaveLength(3);
    });

    it("renders no bottom links when not provided", () => {
      render(<Footer body="No bottom" />);
      const legalNav = screen.getByLabelText("Footer legal");
      const items = legalNav.querySelectorAll("li");
      expect(items).toHaveLength(0);
    });
  });

  describe("onClick handler", () => {
    it("calls onClick when a site link is clicked", () => {
      const handleClick = jest.fn();
      render(<Footer {...defaultProps} onClick={handleClick} />);
      const buttons = screen.getAllByTestId("footer-button");
      fireEvent.click(buttons[0]);
      expect(handleClick).toHaveBeenCalledTimes(1);
    });

    it("calls onClick for each link clicked", () => {
      const handleClick = jest.fn();
      render(<Footer {...defaultProps} onClick={handleClick} />);
      const buttons = screen.getAllByTestId("footer-button");
      fireEvent.click(buttons[0]);
      fireEvent.click(buttons[1]);
      expect(handleClick).toHaveBeenCalledTimes(2);
    });

    it("does not error when onClick is not provided", () => {
      render(<Footer body="No click handler" links={mockLinks} />);
      const buttons = screen.getAllByTestId("footer-button");
      expect(() => fireEvent.click(buttons[0])).not.toThrow();
    });
  });

  describe("Dividers", () => {
    it("renders main divider between body and links", () => {
      render(<Footer {...defaultProps} />);
      const dividers = screen.getAllByTestId("divider");
      expect(dividers.length).toBeGreaterThanOrEqual(1);
    });

    it("renders dividers with inverse border class", () => {
      render(<Footer {...defaultProps} />);
      const dividers = screen.getAllByTestId("divider");
      const inverseDividers = dividers.filter(d =>
        d.className.includes("border-border-inverse")
      );
      expect(inverseDividers.length).toBeGreaterThanOrEqual(1);
    });
  });
});
