import { describe, expect, it } from "vitest";

import { waterNetworkBusinessLayers, waterNetworkLayers } from "./layers";
import { SUPPLY_LAYER_VISUALS } from "./map-layer-visuals";
import { SUPPLY_ASSET_IMAGE_IDS } from "./supply-icons";
import {
  supplyFacilityOpacityExpression,
  supplyPipeColorExpression,
  supplyPipeDashExpression
} from "./supply-style-expressions";

describe("supply network layer styling", () => {
  it("encodes pipe hierarchy by diameter and zoom without inventing risk", () => {
    const pipe = waterNetworkLayers.find((layer) => layer.id === "pipes-flow");
    const paint = pipe?.paint as Record<string, unknown> | undefined;

    expect(paint?.["line-color"]).toEqual(supplyPipeColorExpression);
    expect(paint?.["line-width"]).toEqual(SUPPLY_LAYER_VISUALS.pipes.width);
    expect(paint?.["line-dasharray"]).toEqual(supplyPipeDashExpression);
    expect(JSON.stringify(paint?.["line-width"])).toContain("diameter");
    expect(JSON.stringify(paint?.["line-width"])).toContain("zoom");
    expect(waterNetworkBusinessLayers.some((layer) => layer.id === "pipes-risk-glow")).toBe(false);
    expect(getLayer("pipes-inactive")).toMatchObject({
      type: "line",
      paint: { "line-dasharray": [2, 1.5] }
    });
  });

  it("keeps facilities visible from overview while deferring ordinary junctions", () => {
    expect(getLayer("valves")).toMatchObject({ minzoom: 8.5 });
    expect(getLayer("valves-symbol")).toMatchObject({ minzoom: 8.5 });
    expect(getLayer("reservoirs")).toMatchObject({ minzoom: 8.5 });
    expect(getLayer("reservoirs-symbol")).toMatchObject({
      minzoom: 8.5,
      layout: { "icon-image": SUPPLY_ASSET_IMAGE_IDS.reservoir }
    });
    expect(getLayer("junctions")).toMatchObject({ minzoom: 15 });

    const valvePaint = getLayer("valves")?.paint as Record<string, unknown> | undefined;
    expect(valvePaint?.["circle-opacity"]).toEqual(supplyFacilityOpacityExpression);

    const reservoirPaint = getLayer("reservoirs")?.paint as Record<string, unknown> | undefined;
    expect(reservoirPaint?.["circle-opacity"]).toBe(0);
  });

  it("keeps interaction and hit layers above business layers", () => {
    const ids = waterNetworkLayers.map((layer) => layer.id);
    expect(ids.indexOf("pipes-flow")).toBeLessThan(ids.indexOf("pipes-hover"));
    expect(ids.indexOf("pipes-hover")).toBeLessThan(ids.indexOf("pipes-hit"));
    expect(ids.at(-1)).toBe("reservoirs-hit");
  });
});

function getLayer(id: string) {
  return waterNetworkLayers.find((layer) => layer.id === id);
}
