import { AnchoredBottomBanner } from "./index";

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

// Mock next/link
jest.mock("next/link", () => {
  // eslint-disable-next-line react/display-name
  return ({ children, href, target, ...rest }: any) => (
    <a href={href} target={target} {...rest}>
      {children}
    </a>
  );
});

describe("AnchoredBottomBanner", () => {
  beforeEach(() => {
    jest.useFakeTimers();
    jest.setSystemTime(new Date("2026-05-19T12:00:00Z"));
  });

  afterEach(() => {
    jest.useRealTimers();
  });

  it("renders with default anchorId", () => {
    const { container } = render(<AnchoredBottomBanner />);
    expect(container.querySelector("#anchored-banner")).toBeInTheDocument();
  });

  it("renders with custom anchorId", () => {
    const { container } = render(
      <AnchoredBottomBanner anchorId="custom-banner" />
    );
    expect(container.querySelector("#custom-banner")).toBeInTheDocument();
  });

  it("renders ctaButtonLabel", () => {
    render(<AnchoredBottomBanner ctaButtonLabel="Shop now" />);
    expect(screen.getByText("Shop now")).toBeInTheDocument();
  });

  it("renders ctaSuffixText", () => {
    render(<AnchoredBottomBanner ctaSuffixText="Limited time" />);
    expect(screen.getByText("Limited time")).toBeInTheDocument();
  });

  it("renders iconName", () => {
    render(<AnchoredBottomBanner iconName="local_offer" />);
    expect(screen.getByText("local_offer")).toBeInTheDocument();
  });

  it("does not render icon when iconName is not provided", () => {
    const { container } = render(<AnchoredBottomBanner />);
    expect(
      container.querySelector(".material-symbols-rounded")
    ).not.toBeInTheDocument();
  });

  it("uses ctaButtonLink in the link href", () => {
    render(<AnchoredBottomBanner ctaButtonLink="/offers" />);
    const link = screen.getByRole("link");
    expect(link).toHaveAttribute("href", "/offers");
  });

  it("defaults link href to # when ctaButtonLink is not provided", () => {
    render(<AnchoredBottomBanner />);
    const link = screen.getByRole("link");
    expect(link).toHaveAttribute("href", "#");
  });

  it("uses ctaButtonTarget for link target", () => {
    render(<AnchoredBottomBanner ctaButtonTarget="_blank" />);
    const link = screen.getByRole("link");
    expect(link).toHaveAttribute("target", "_blank");
  });

  it("defaults link target to _self", () => {
    render(<AnchoredBottomBanner />);
    const link = screen.getByRole("link");
    expect(link).toHaveAttribute("target", "_self");
  });

  // Background colors
  it("applies yellow background by default (no backgroundColor)", () => {
    const { container } = render(<AnchoredBottomBanner />);
    const div = container.querySelector(".bg-bg-fill-brand-accent");
    expect(div).toBeInTheDocument();
  });

  it("applies navy background", () => {
    const { container } = render(
      <AnchoredBottomBanner backgroundColor="navy" />
    );
    expect(container.querySelector(".bg-bg-fill-inverse")).toBeInTheDocument();
  });

  it("applies green background", () => {
    const { container } = render(
      <AnchoredBottomBanner backgroundColor="green" />
    );
    expect(container.querySelector(".bg-bg-fill-success")).toBeInTheDocument();
  });

  it("applies blue background", () => {
    const { container } = render(
      <AnchoredBottomBanner backgroundColor="blue" />
    );
    expect(
      container.querySelector(".bg-bg-fill-brand-supporting")
    ).toBeInTheDocument();
  });

  it("applies purple background", () => {
    const { container } = render(
      <AnchoredBottomBanner backgroundColor="purple" />
    );
    expect(
      container.querySelector(".bg-bg-fill-brand-tertiary")
    ).toBeInTheDocument();
  });

  it("applies white background", () => {
    const { container } = render(
      <AnchoredBottomBanner backgroundColor="white" />
    );
    expect(container.querySelector(".bg-white")).toBeInTheDocument();
  });

  // Text colors
  it("uses dark text for yellow/white/no background", () => {
    const { container } = render(
      <AnchoredBottomBanner ctaButtonLabel="Test" />
    );
    expect(container.querySelector(".text-text-primary")).toBeInTheDocument();
  });

  it("uses white text for dark backgrounds", () => {
    const { container } = render(
      <AnchoredBottomBanner backgroundColor="navy" ctaButtonLabel="Test" />
    );
    expect(container.querySelector(".text-white")).toBeInTheDocument();
  });

  // Box shadow
  it("uses default shadow when boxShadow is not provided", () => {
    const { container } = render(<AnchoredBottomBanner />);
    const div = container.querySelector(
      '[class*="shadow-[0_-4px_10px_rgba(0,0,0,0.1)]"]'
    );
    expect(div).toBeInTheDocument();
  });

  it("uses boxShadow value when provided", () => {
    const { container } = render(
      <AnchoredBottomBanner boxShadow={true as any} />
    );
    const div = container.querySelector(
      '[class*="shadow-[0_-4px_10px_rgba(0,0,0,0.1)]"]'
    );
    expect(div).not.toBeInTheDocument();
  });

  // Countdown timer
  it("shows countdown when timer is enabled and within range", () => {
    const end = new Date("2026-05-19T13:00:00Z").toISOString();
    render(
      <AnchoredBottomBanner
        enableCountdownTimer={true}
        countdownEndDateTime={end}
      />
    );
    // 1 hour remaining: 01H : 00M : 00
    expect(screen.getByText(/01H : 00M : 00/)).toBeInTheDocument();
  });

  it("does not show countdown when timer is disabled", () => {
    const end = new Date("2026-05-19T13:00:00Z").toISOString();
    render(<AnchoredBottomBanner countdownEndDateTime={end} />);
    expect(screen.queryByText(/H :/)).not.toBeInTheDocument();
  });

  it("does not show countdown before start time", () => {
    const start = new Date("2026-05-19T14:00:00Z").toISOString();
    const end = new Date("2026-05-19T15:00:00Z").toISOString();
    render(
      <AnchoredBottomBanner
        enableCountdownTimer={true}
        countdownStartDateTime={start}
        countdownEndDateTime={end}
      />
    );
    expect(screen.queryByText(/H :/)).not.toBeInTheDocument();
  });

  it("does not show countdown after end time", () => {
    const end = new Date("2026-05-19T11:00:00Z").toISOString();
    render(
      <AnchoredBottomBanner
        enableCountdownTimer={true}
        countdownEndDateTime={end}
      />
    );
    expect(screen.queryByText(/H :/)).not.toBeInTheDocument();
  });

  it("updates countdown every second", () => {
    const end = new Date("2026-05-19T12:00:10Z").toISOString();
    render(
      <AnchoredBottomBanner
        enableCountdownTimer={true}
        countdownEndDateTime={end}
      />
    );
    expect(screen.getByText(/00H : 00M : 10/)).toBeInTheDocument();

    act(() => {
      jest.advanceTimersByTime(1000);
    });
    expect(screen.getByText(/00H : 00M : 09/)).toBeInTheDocument();
  });

  it("clears interval when countdown reaches zero", () => {
    const end = new Date("2026-05-19T12:00:01Z").toISOString();
    render(
      <AnchoredBottomBanner
        enableCountdownTimer={true}
        countdownEndDateTime={end}
      />
    );

    act(() => {
      jest.advanceTimersByTime(2000);
    });
    // After expiry, countdown should not show
    expect(screen.queryByText(/H :/)).not.toBeInTheDocument();
  });

  it("handles invalid countdownEndDateTime gracefully", () => {
    const consoleSpy = jest.spyOn(console, "error").mockImplementation(() => {
      /* noop */
    });
    render(
      <AnchoredBottomBanner
        enableCountdownTimer={true}
        countdownEndDateTime="not-a-date"
      />
    );
    expect(screen.queryByText(/H :/)).not.toBeInTheDocument();
    consoleSpy.mockRestore();
  });

  it("handles invalid countdownStartDateTime gracefully", () => {
    const consoleSpy = jest.spyOn(console, "error").mockImplementation(() => {
      /* noop */
    });
    const end = new Date("2026-05-19T13:00:00Z").toISOString();
    render(
      <AnchoredBottomBanner
        enableCountdownTimer={true}
        countdownStartDateTime="not-a-date"
        countdownEndDateTime={end}
      />
    );
    expect(screen.queryByText(/H :/)).not.toBeInTheDocument();
    consoleSpy.mockRestore();
  });

  it("logs error when start is after end", () => {
    const consoleSpy = jest.spyOn(console, "error").mockImplementation(() => {
      /* noop */
    });
    const start = new Date("2026-05-19T15:00:00Z").toISOString();
    const end = new Date("2026-05-19T13:00:00Z").toISOString();
    render(
      <AnchoredBottomBanner
        enableCountdownTimer={true}
        countdownStartDateTime={start}
        countdownEndDateTime={end}
      />
    );
    expect(consoleSpy).toHaveBeenCalledWith(
      "Invalid countdown range: start must be before end",
      expect.any(Object)
    );
    consoleSpy.mockRestore();
  });
});
