import { fireEvent, render } from "@testing-library/react";
import { describe, expect, it, vi } from "vitest";
import { ZoomControls } from "../ZoomControls";

describe("ZoomControls component", () => {
  const defaultProps = {
    onZoomIn: vi.fn(),
    onZoomOut: vi.fn(),
    onReset: vi.fn(),
    showResetButton: false,
    zoom: 1,
    minZoom: 1,
    maxZoom: 5,
    isVisible: true,
  };

  it("should render zoom in and zoom out buttons", () => {
    const { getByLabelText } = render(<ZoomControls {...defaultProps} />);

    expect(getByLabelText("Zoom in")).toBeDefined();
    expect(getByLabelText("Zoom out")).toBeDefined();
  });

  it("should call onZoomIn when + button is clicked", () => {
    const onZoomIn = vi.fn();
    const { getByLabelText } = render(<ZoomControls {...defaultProps} onZoomIn={onZoomIn} />);

    fireEvent.click(getByLabelText("Zoom in"));

    expect(onZoomIn).toHaveBeenCalledTimes(1);
  });

  it("should call onZoomOut when - button is clicked", () => {
    const onZoomOut = vi.fn();
    const { getByLabelText } = render(
      <ZoomControls {...defaultProps} zoom={2} onZoomOut={onZoomOut} />,
    );

    fireEvent.click(getByLabelText("Zoom out"));

    expect(onZoomOut).toHaveBeenCalledTimes(1);
  });

  it("should disable zoom in button when at maxZoom", () => {
    const onZoomIn = vi.fn();
    const { getByLabelText } = render(
      <ZoomControls {...defaultProps} zoom={5} maxZoom={5} onZoomIn={onZoomIn} />,
    );

    const zoomInButton = getByLabelText("Zoom in") as HTMLButtonElement;
    expect(zoomInButton.disabled).toBe(true);

    fireEvent.click(zoomInButton);
    expect(onZoomIn).not.toHaveBeenCalled();
  });

  it("should disable zoom out button when at minZoom", () => {
    const onZoomOut = vi.fn();
    const { getByLabelText } = render(
      <ZoomControls {...defaultProps} zoom={1} minZoom={1} onZoomOut={onZoomOut} />,
    );

    const zoomOutButton = getByLabelText("Zoom out") as HTMLButtonElement;
    expect(zoomOutButton.disabled).toBe(true);

    fireEvent.click(zoomOutButton);
    expect(onZoomOut).not.toHaveBeenCalled();
  });

  it("should hide reset button when showResetButton is false", () => {
    const { getByLabelText } = render(<ZoomControls {...defaultProps} showResetButton={false} />);

    const resetButton = getByLabelText("Reset zoom");
    const container = resetButton.parentElement as HTMLElement;
    expect(container.style.opacity).toBe("0");
    expect(container.style.pointerEvents).toBe("none");
  });

  it("should render reset button when showResetButton is true", () => {
    const { getByLabelText } = render(
      <ZoomControls {...defaultProps} showResetButton={true} zoom={2} />,
    );

    expect(getByLabelText("Reset zoom")).toBeDefined();
  });

  it("should call onReset when reset button is clicked", () => {
    const onReset = vi.fn();
    const { getByLabelText } = render(
      <ZoomControls {...defaultProps} showResetButton={true} zoom={2} onReset={onReset} />,
    );

    fireEvent.click(getByLabelText("Reset zoom"));

    expect(onReset).toHaveBeenCalledTimes(1);
  });

  it("should display reset icon in reset button", () => {
    const { getByLabelText } = render(
      <ZoomControls {...defaultProps} showResetButton={true} zoom={1.5} />,
    );

    const resetButton = getByLabelText("Reset zoom");
    expect(resetButton.textContent).toContain("↺");
  });
});
