import type { Map as MapLibreMap } from "maplibre-gl";
import type { BaseLayerOption, MapLayerControlItem, MapLegendItem } from "@/features/map/core";
import { GEOSERVER_WORKSPACE } from "./geoserver-config";
import { MAP_STYLE_TOKENS } from "./map-colors";
import {
  AVAILABLE_WATER_NETWORK_SOURCE_IDS,
  SUPPLY_LAYER_CATALOG,
  type WaterNetworkSourceId
} from "./sources";
import { SCADA_ICON_PATHS } from "./scada";
import { SUPPLY_ASSET_ICON_PATHS } from "./supply-icons";

export const WORKBENCH_LAYER_GROUPS: Record<string, string[]> = {
  simulation: [
    "simulation-impact-fill",
    "simulation-impact-outline",
    "simulation-burst-halo",
    "simulation-burst-point",
    "simulation-pipe-label",
    "simulation-impact-label",
    "simulation-district-label",
    "simulation-burst-label"
  ]
};

export const INITIAL_LAYER_VISIBILITY: Record<string, boolean> = {
  ...Object.fromEntries(AVAILABLE_WATER_NETWORK_SOURCE_IDS.map((sourceId) => [sourceId, true])),
  simulation: false
};

const SOURCE_CONTROL_LABELS = Object.fromEntries(
  SUPPLY_LAYER_CATALOG
    .filter((layer) => layer.available)
    .map((layer) => [
      layer.id,
      {
        label: layer.label,
        description: `${GEOSERVER_WORKSPACE}:${layer.sourceLayer}`
      }
    ])
) as Record<WaterNetworkSourceId, { label: string; description: string }>;

export const MAP_LEGEND_ITEMS: MapLegendItem[] = [
  { id: "major-pipe", label: "DN600 及以上管线", color: MAP_STYLE_TOKENS.supply.pipeMajor, shape: "line" },
  { id: "medium-pipe", label: "DN300-DN599 管线", color: MAP_STYLE_TOKENS.supply.pipeMedium, shape: "line" },
  { id: "minor-pipe", label: "DN300 以下管线", color: MAP_STYLE_TOKENS.supply.pipeMinor, shape: "line" },
  { id: "inactive-pipe", label: "停运管线", color: MAP_STYLE_TOKENS.state.inactive, shape: "dashed-line" },
  { id: "junction", label: "节点", color: MAP_STYLE_TOKENS.supply.junction, shape: "dot" },
  { id: "valve", label: "阀门", color: MAP_STYLE_TOKENS.supply.valve, imageSrc: SUPPLY_ASSET_ICON_PATHS.valve },
  { id: "reservoir", label: "水库", color: MAP_STYLE_TOKENS.supply.reservoir, imageSrc: SUPPLY_ASSET_ICON_PATHS.reservoir },
  { id: "scada-flow", label: "SCADA 流量", color: MAP_STYLE_TOKENS.supply.scadaFlow, imageSrc: SCADA_ICON_PATHS.flow },
  { id: "scada-pressure", label: "SCADA 压力", color: MAP_STYLE_TOKENS.supply.scadaPressure, imageSrc: SCADA_ICON_PATHS.pressure },
  { id: "impact-area", label: "影响范围", color: MAP_STYLE_TOKENS.state.incident, shape: "square" }
];

export const BASE_LAYER_IDS = ["mapbox-light", "mapbox-satellite"] as const;

export function applyBaseLayerVisibility(map: MapLibreMap, activeBaseLayerId: string) {
  BASE_LAYER_IDS.forEach((layerId) => {
    if (map.getLayer(layerId)) {
      map.setLayoutProperty(
        layerId,
        "visibility",
        activeBaseLayerId === layerId ? "visible" : "none"
      );
    }
  });
}

export const BASE_LAYER_OPTIONS: BaseLayerOption[] = [
  {
    id: "mapbox-light",
    label: "浅色",
    description: "道路底图",
    swatchClassName: "bg-gradient-to-br from-slate-50 via-slate-100 to-blue-100"
  },
  {
    id: "mapbox-satellite",
    label: "影像",
    description: "卫星街道",
    swatchClassName: "bg-gradient-to-br from-emerald-950 via-emerald-700 to-yellow-200"
  },
  {
    id: "none",
    label: "无底图",
    description: "仅业务图层",
    swatchClassName: "bg-slate-100"
  }
];

export function createLayerControlItems(layerVisibility: Record<string, boolean>): MapLayerControlItem[] {
  return [
    ...AVAILABLE_WATER_NETWORK_SOURCE_IDS.map((sourceId) => ({
      id: sourceId,
      ...SOURCE_CONTROL_LABELS[sourceId],
      visible: layerVisibility[sourceId]
    })),
    {
      id: "simulation",
      label: "模拟结果",
      description: "影响范围与事故标注",
      visible: layerVisibility.simulation
    }
  ];
}

export function getWorkbenchLayerIds(
  map: Pick<MapLibreMap, "getLayer" | "getStyle">,
  groupId: string
) {
  if (isWaterNetworkSourceId(groupId)) {
    return map
      .getStyle()
      .layers.filter((layer) => "source" in layer && layer.source === groupId)
      .map((layer) => layer.id);
  }

  const layerIds = WORKBENCH_LAYER_GROUPS[groupId] ?? [];
  return layerIds.filter((layerId) => map.getLayer(layerId));
}

function isWaterNetworkSourceId(value: string): value is WaterNetworkSourceId {
  return (AVAILABLE_WATER_NETWORK_SOURCE_IDS as readonly string[]).includes(value);
}
