import React from "react";
import { ProductCard } from "./index";

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

jest.mock("@shared/components/button", () => ({
  Button: ({ children, onClick, className }: any) => (
    <button
      data-testid="feature-toggle"
      onClick={onClick}
      className={className}
    >
      {children}
    </button>
  ),
}));

jest.mock("@shared/components/checklist", () => ({
  Checklist: ({ items }: any) => (
    <ul data-testid="checklist">
      {items?.map((item: any, i: number) => (
        <li key={i}>{item}</li>
      ))}
    </ul>
  ),
}));

jest.mock("@shared/components/image", () => ({
  Image: ({ src, alt, width, height }: any) => (
    <img
      data-testid="badge-image"
      src={src}
      alt={alt}
      width={width}
      height={height}
    />
  ),
}));

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

jest.mock("@shared/components/select-plan-button", () => ({
  SelectPlanButton: ({ onSelect, speed }: any) => (
    <button data-testid="select-plan-btn" onClick={onSelect}>
      Select {speed}
    </button>
  ),
}));

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

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

describe("ProductCard", () => {
  const defaultProps = {
    planName: "Kinetic 500",
    planSubtext: "Up to 500 Mbps",
    speed: "500",
    price: "49.99",
    description: "Fast internet for your home",
    features: ["Wi-Fi included", "No data caps"],
    onCtaClick: jest.fn(),
    hostType: "residential" as const,
  };

  beforeEach(() => {
    jest.clearAllMocks();
  });

  describe("Rendering", () => {
    it("renders the article element", () => {
      const { container } = render(<ProductCard {...defaultProps} />);
      expect(container.querySelector("article")).toBeInTheDocument();
    });

    it("renders plan name", () => {
      render(<ProductCard {...defaultProps} />);
      expect(screen.getByText("Kinetic 500")).toBeInTheDocument();
    });

    it("renders plan subtext", () => {
      render(<ProductCard {...defaultProps} />);
      expect(screen.getByText("Up to 500 Mbps")).toBeInTheDocument();
    });

    it("renders price dollar sign", () => {
      render(<ProductCard {...defaultProps} />);
      expect(screen.getByText("$")).toBeInTheDocument();
    });

    it("renders price whole number", () => {
      render(<ProductCard {...defaultProps} />);
      expect(screen.getByText("49")).toBeInTheDocument();
    });

    it("renders price decimal and /mo", () => {
      render(<ProductCard {...defaultProps} />);
      expect(screen.getByText("99/mo")).toBeInTheDocument();
    });

    it("renders description", () => {
      render(<ProductCard {...defaultProps} />);
      expect(
        screen.getByText("Fast internet for your home")
      ).toBeInTheDocument();
    });
  });

  describe("Best Value", () => {
    it("renders best value banner when bestValue is true", () => {
      render(<ProductCard {...defaultProps} bestValue={true} />);
      expect(screen.getByText("best value")).toBeInTheDocument();
    });

    it("renders custom best value text", () => {
      render(
        <ProductCard
          {...defaultProps}
          bestValue={true}
          bestValueText="Top pick"
        />
      );
      expect(screen.getByText("Top pick")).toBeInTheDocument();
    });

    it("does not render best value banner by default", () => {
      render(<ProductCard {...defaultProps} />);
      expect(screen.queryByText("best value")).not.toBeInTheDocument();
    });
  });

  describe("Theme", () => {
    it("applies light theme by default", () => {
      const { container } = render(<ProductCard {...defaultProps} />);
      const card = container.querySelector("article > div");
      expect(card?.className).toContain("bg-bg");
    });

    it("applies dark theme classes", () => {
      const { container } = render(
        <ProductCard {...defaultProps} theme="dark" />
      );
      const card = container.querySelector("article > div");
      expect(card?.className).toContain("bg-bg-fill-inverse");
    });
  });

  describe("Features", () => {
    it("renders features section when features are provided", () => {
      render(<ProductCard {...defaultProps} />);
      expect(screen.getByTestId("checklist")).toBeInTheDocument();
    });

    it("does not render features section when features is empty", () => {
      render(<ProductCard {...defaultProps} features={[]} />);
      expect(screen.queryByTestId("checklist")).not.toBeInTheDocument();
    });

    it("renders features title", () => {
      render(<ProductCard {...defaultProps} />);
      expect(
        screen.getByText("Business Ready Internet features")
      ).toBeInTheDocument();
    });

    it("renders custom features title", () => {
      render(<ProductCard {...defaultProps} featuresTitle="Custom features" />);
      expect(screen.getByText("Custom features")).toBeInTheDocument();
    });
  });

  describe("Expand/Collapse", () => {
    it("toggles internal expanded state on click", () => {
      const { container } = render(<ProductCard {...defaultProps} />);
      const toggleBtn = screen.getByTestId("feature-toggle");
      fireEvent.click(toggleBtn);
      // Check the features container shows opacity-100
      const featuresDiv = container.querySelector(".opacity-100");
      expect(featuresDiv).toBeInTheDocument();
    });

    it("uses controlled expanded state when provided", () => {
      const { container } = render(
        <ProductCard {...defaultProps} isExpanded={true} />
      );
      const featuresDiv = container.querySelector(".opacity-100");
      expect(featuresDiv).toBeInTheDocument();
    });

    it("calls onToggleExpand when provided", () => {
      const onToggleExpand = jest.fn();
      render(<ProductCard {...defaultProps} onToggleExpand={onToggleExpand} />);
      fireEvent.click(screen.getByTestId("feature-toggle"));
      expect(onToggleExpand).toHaveBeenCalledTimes(1);
    });
  });

  describe("Gift Badge", () => {
    it("renders gift badges when provided", () => {
      const giftBadge = [{ title: "Free router", icon: "/router.png" }] as any;
      render(<ProductCard {...defaultProps} giftBadge={giftBadge} />);
      expect(screen.getByText("Free router")).toBeInTheDocument();
      expect(screen.getByAltText("Free router")).toBeInTheDocument();
    });

    it("does not render gift badges when not provided", () => {
      render(<ProductCard {...defaultProps} />);
      expect(screen.queryByText("Free router")).not.toBeInTheDocument();
    });
  });

  describe("Inner Badge", () => {
    it("renders inner badge with pipe-separated text", () => {
      const innerBadge = { badgeText: "Bold|Normal", badgeIcon: "/icon.png" };
      render(
        <ProductCard
          {...defaultProps}
          isExpanded={true}
          innerBadge={innerBadge}
        />
      );
      expect(screen.getByText("Bold")).toBeInTheDocument();
      expect(screen.getByText("Normal")).toBeInTheDocument();
    });

    it("renders inner badge without pipe as bold", () => {
      const innerBadge = { badgeText: "Simple Badge", badgeIcon: "/icon.png" };
      render(
        <ProductCard
          {...defaultProps}
          isExpanded={true}
          innerBadge={innerBadge}
        />
      );
      expect(screen.getByText("Simple Badge")).toBeInTheDocument();
    });
  });

  describe("CTA", () => {
    it("renders SelectPlanButton", () => {
      render(<ProductCard {...defaultProps} />);
      expect(screen.getByTestId("select-plan-btn")).toBeInTheDocument();
    });

    it("calls onCtaClick when CTA is clicked", () => {
      render(<ProductCard {...defaultProps} />);
      fireEvent.click(screen.getByTestId("select-plan-btn"));
      expect(defaultProps.onCtaClick).toHaveBeenCalledTimes(1);
    });
  });
});
