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

import { describe, expect, it, jest } from "@jest/globals";
import "@testing-library/jest-dom/jest-globals";
import { render, screen } from "@testing-library/react";

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

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

jest.mock("../../button", () => ({
  Button: ({ children, linkClassName, ...rest }: any) => (
    <button data-testid="cta-button" className={linkClassName}>
      {rest.buttonLabel || children}
    </button>
  ),
}));

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

describe("FloatingImageCard", () => {
  const defaultCard = {
    title: "Card Title",
    header: "Card Header",
    body: "Card body content",
    image: { href: "/image.jpg", title: "Test Image", width: 400, height: 285 },
  };

  describe("Rendering", () => {
    it("renders the section element", () => {
      const { container } = render(<FloatingImageCard card={defaultCard} />);
      expect(container.querySelector("section")).toBeInTheDocument();
    });

    it("renders header text", () => {
      render(<FloatingImageCard card={defaultCard} />);
      expect(screen.getByText("Card Header")).toBeInTheDocument();
    });

    it("renders body text", () => {
      render(<FloatingImageCard card={defaultCard} />);
      expect(screen.getByText("Card body content")).toBeInTheDocument();
    });

    it("renders image when provided", () => {
      render(<FloatingImageCard card={defaultCard} />);
      const img = screen.getByTestId("next-image");
      expect(img).toHaveAttribute("src", "/image.jpg");
      expect(img).toHaveAttribute("alt", "Test Image");
    });

    it("does not render image when not provided", () => {
      render(<FloatingImageCard card={{ ...defaultCard, image: undefined }} />);
      expect(screen.queryByTestId("next-image")).not.toBeInTheDocument();
    });

    it("does not render header when not provided", () => {
      render(
        <FloatingImageCard card={{ ...defaultCard, header: undefined }} />
      );
      expect(screen.queryByText("Card Header")).not.toBeInTheDocument();
    });

    it("does not render body when not provided", () => {
      render(<FloatingImageCard card={{ ...defaultCard, body: undefined }} />);
      expect(screen.queryByText("Card body content")).not.toBeInTheDocument();
    });
  });

  describe("CTA", () => {
    it("renders CTA button when cta is provided", () => {
      const card = {
        ...defaultCard,
        cta: { buttonLabel: "Learn More", href: "/learn" },
      };
      render(<FloatingImageCard card={card} />);
      expect(screen.getByTestId("cta-button")).toBeInTheDocument();
    });

    it("does not render CTA when not provided", () => {
      render(<FloatingImageCard card={defaultCard} />);
      expect(screen.queryByTestId("cta-button")).not.toBeInTheDocument();
    });

    it("renders Button when buttonIconName is provided", () => {
      const card = {
        ...defaultCard,
        cta: {
          buttonLabel: "See Jobs",
          href: "/jobs",
          showButtonAs: "text" as const,
          buttonIconName: "expand_circle_right",
          buttonIconPosition: "left" as const,
        },
      };

      render(<FloatingImageCard card={card} />);
      expect(screen.getByTestId("cta-button")).toBeInTheDocument();
    });

    it("renders Button for primary_inverse text CTA variant", () => {
      const card = {
        ...defaultCard,
        cta: {
          buttonLabel: "See Jobs",
          href: "/jobs",
          showButtonAs: "text" as const,
          buttonVariant: "primary_inverse" as const,
          buttonIconName: "expand_circle_right",
        },
      };

      render(<FloatingImageCard card={card} />);
      expect(screen.getByTestId("cta-button")).toBeInTheDocument();
    });

    it("renders Button for primary_navy alias", () => {
      const card = {
        ...defaultCard,
        cta: {
          buttonLabel: "See Jobs",
          href: "/jobs",
          showButtonAs: "text" as const,
          buttonVariant: "primary_navy" as any,
          buttonIconName: "expand_circle_right",
        },
      };

      render(<FloatingImageCard card={card} />);
      expect(screen.getByTestId("cta-button")).toBeInTheDocument();
    });

    it("renders authored icon CTA when buttonIconName is set even if href is missing", () => {
      const card = {
        ...defaultCard,
        cta: {
          buttonLabel: "See Jobs",
          showButtonAs: "text" as const,
          buttonIconName: "expand_circle_right",
        },
      };

      render(<FloatingImageCard card={card} />);
      expect(screen.getByTestId("cta-button")).toBeInTheDocument();
    });
  });

  describe("CTA alignment", () => {
    it("applies left alignment by default", () => {
      const card = {
        ...defaultCard,
        cta: { buttonLabel: "Click", href: "/click" },
      };
      render(<FloatingImageCard card={card} />);
      const ctaWrapper = screen.getByTestId("cta-button").parentElement;
      expect(ctaWrapper?.className).toContain("justify-start");
    });

    it("applies center alignment", () => {
      const card = {
        ...defaultCard,
        cta: { buttonLabel: "Click", href: "/click" },
        ctaAlignment: "center" as const,
      };
      render(<FloatingImageCard card={card} />);
      const ctaWrapper = screen.getByTestId("cta-button").parentElement;
      expect(ctaWrapper?.className).toContain("justify-center");
    });

    it("applies right alignment", () => {
      const card = {
        ...defaultCard,
        cta: { buttonLabel: "Click", href: "/click" },
        ctaAlignment: "right" as const,
      };
      render(<FloatingImageCard card={card} />);
      const ctaWrapper = screen.getByTestId("cta-button").parentElement;
      expect(ctaWrapper?.className).toContain("justify-end");
    });
  });

  describe("PromoBar mode", () => {
    it("renders only image when isPromoBarImg is true", () => {
      const card = {
        ...defaultCard,
        isPromoBarImg: true,
      };
      const { container } = render(<FloatingImageCard card={card} />);
      expect(container.querySelector("section")).not.toBeInTheDocument();
      expect(screen.getByTestId("next-image")).toBeInTheDocument();
    });

    it("returns null when isPromoBarImg is true and no image", () => {
      const card = {
        ...defaultCard,
        image: undefined,
        isPromoBarImg: true,
      };
      const { container } = render(<FloatingImageCard card={card} />);
      expect(container.firstChild).toBeNull();
    });
  });

  describe("Image link", () => {
    it("makes image clickable when imageLink is provided", () => {
      const windowOpen = jest
        .spyOn(window, "open")
        .mockImplementation(() => null);
      const card = {
        ...defaultCard,
        imageLink: "https://example.com",
      };
      render(<FloatingImageCard card={card} />);
      const img = screen.getByTestId("next-image");
      img.click();
      expect(windowOpen).toHaveBeenCalledWith("https://example.com", "_blank");
      windowOpen.mockRestore();
    });
  });

  describe("Layout props", () => {
    it("applies lgWidth class", () => {
      const { container } = render(
        <FloatingImageCard card={defaultCard} lgWidth="lg:w-1/3" />
      );
      expect(container.querySelector("section")?.className).toContain(
        "lg:w-1/3"
      );
    });

    it("applies mdWidth class", () => {
      const { container } = render(
        <FloatingImageCard card={defaultCard} mdWidth="md:w-1/2" />
      );
      expect(container.querySelector("section")?.className).toContain(
        "md:w-1/2"
      );
    });

    it("applies shadow class when shadow is true", () => {
      const card = { ...defaultCard, shadow: true };
      const { container } = render(<FloatingImageCard card={card} />);
      expect(container.querySelector("section")?.className).toContain(
        "shadow-card"
      );
    });
  });
});
