import type { Map as MapLibreMap } from "maplibre-gl";
import { describe, expect, it, vi } from "vitest";
import { fitNetworkBounds, getResponsiveWorkbenchPadding, getWorkbenchPadding } from "./camera";
import { WATER_NETWORK_GLOBAL_VIEW } from "./sources";

function createMap(width = 1280, height = 720) {
  const fitBounds = vi.fn();
  const map = {
    fitBounds,
    getCanvas: () => ({ clientWidth: width, clientHeight: height, width, height })
  } as unknown as MapLibreMap;

  return { fitBounds, map };
}

describe("workbench camera padding", () => {
  it.each([
    {
      agentOpen: false,
      conditionOpen: false,
      expected: { top: 72, right: 72, bottom: 32, left: 96 }
    },
    {
      agentOpen: true,
      conditionOpen: false,
      expected: { top: 72, right: 72, bottom: 32, left: 524 }
    },
    {
      agentOpen: false,
      conditionOpen: true,
      expected: { top: 72, right: 504, bottom: 32, left: 96 }
    },
    {
      agentOpen: true,
      conditionOpen: true,
      expected: { top: 72, right: 504, bottom: 32, left: 524 }
    }
  ])(
    "covers agent=$agentOpen and condition=$conditionOpen",
    ({ agentOpen, conditionOpen, expected }) => {
      expect(getWorkbenchPadding(agentOpen, conditionOpen)).toEqual(expected);
    }
  );

  it("uses a committed Agent width for camera-safe operations", () => {
    expect(getWorkbenchPadding(true, false, false, 620)).toEqual({
      top: 72,
      right: 72,
      bottom: 32,
      left: 540
    });
  });

  it("caps combined padding on constrained desktop widths", () => {
    const { map } = createMap(1024, 720);
    const padding = getResponsiveWorkbenchPadding(map, true, true);

    expect(padding.left + padding.right).toBeLessThanOrEqual(Math.floor(1024 * 0.58) + 1);
    expect(padding.top + padding.bottom).toBeLessThanOrEqual(Math.floor(720 * 0.58) + 1);
    expect(padding.left).toBeGreaterThan(padding.top);
    expect(padding.right).toBeGreaterThan(padding.top);
  });

  it("uses mobile-safe padding below the dock breakpoint", () => {
    const { map } = createMap(375, 667);

    expect(getResponsiveWorkbenchPadding(map, true, true)).toEqual({
      top: 72,
      right: 24,
      bottom: 72,
      left: 24
    });
  });
});

describe("fitNetworkBounds", () => {
  it("uses the configured global extent for initial and home views", () => {
    const { fitBounds, map } = createMap();

    fitNetworkBounds(map, WATER_NETWORK_GLOBAL_VIEW);

    expect(fitBounds).toHaveBeenCalledTimes(1);
    const [bounds, options] = fitBounds.mock.calls[0] ?? [];

    expect(bounds[0][0]).toBeCloseTo(121.351632, 6);
    expect(bounds[0][1]).toBeCloseTo(30.8105, 6);
    expect(bounds[1][0]).toBeCloseTo(121.772482, 6);
    expect(bounds[1][1]).toBeCloseTo(31.007207, 6);
    expect(options).toMatchObject({
      duration: 600,
      maxZoom: 13,
      padding: { top: 96, right: 48, bottom: 48, left: 48 }
    });
    expect(options).not.toHaveProperty("zoom");
  });
});
