<script lang="ts">
  import "leaflet/dist/leaflet.css";
  import { onMount, onDestroy } from "svelte";
  import type { WindArea } from "$lib/windkarte";

  let {
    areas,
    geojsonUrl,
    onselect,
  }: {
    areas: WindArea[];
    geojsonUrl: string;
    onselect: (area: WindArea | null) => void;
  } = $props();

  let mapEl: HTMLDivElement;
  let map: import("leaflet").Map | null = null;
  let bufferLayer: import("leaflet").LayerGroup | null = null;
  let selectedSlug = $state<string | null>(null);
  let geojsonLayer: import("leaflet").GeoJSON | null = null;

  const COLORS: Record<string, { fill: string; stroke: string }> = {
    rechtskraeftig: { fill: "#2d7a45", stroke: "#1a4d28" },
    entwurf_2: { fill: "#b08a52", stroke: "#6e5530" },
    entwurf_3: { fill: "#436e85", stroke: "#264150" },
  };

  function style(status: string, selected: boolean) {
    const c = COLORS[status] ?? COLORS.rechtskraeftig;
    return {
      color: c.stroke,
      fillColor: c.fill,
      weight: selected ? 2.5 : 1.5,
      fillOpacity: selected ? 0.45 : 0.25,
      opacity: 1,
    };
  }

  async function drawBuffer(L: typeof import("leaflet"), feature: GeoJSON.Feature) {
    const { buffer } = await import("@turf/buffer");
    if (bufferLayer) bufferLayer.clearLayers();
    else bufferLayer = L.layerGroup().addTo(map!);

    const distances = [
      { m: 200, label: "200 m", color: "#e35651", dash: "4 4" },
      { m: 600, label: "600 m", color: "#b08a52", dash: "6 3" },
      { m: 1000, label: "1000 m", color: "#436e85", dash: "8 4" },
    ];
    for (const { m, color, dash } of distances) {
      const buffered = buffer(feature, m / 1000, { units: "kilometers" });
      if (!buffered) continue;
      L.geoJSON(buffered, {
        style: { color, fillColor: color, fillOpacity: 0.05, weight: 1.5, dashArray: dash },
      }).addTo(bufferLayer!);
    }
  }

  onMount(async () => {
    const L = await import("leaflet");

    // Fix Leaflet default icon path issue with Vite bundling
    const iconUrl = new URL("leaflet/dist/images/marker-icon.png", import.meta.url).href;
    const icon2xUrl = new URL("leaflet/dist/images/marker-icon-2x.png", import.meta.url).href;
    const shadowUrl = new URL("leaflet/dist/images/marker-shadow.png", import.meta.url).href;
    L.Icon.Default.mergeOptions({ iconUrl, iconRetinaUrl: icon2xUrl, shadowUrl });

    map = L.map(mapEl, { zoomControl: true }).setView([50.62, 10.42], 9);

    L.tileLayer("https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png", {
      attribution:
        '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> &copy; <a href="https://carto.com/attributions">CARTO</a> | Geodaten: © GDI-Th, dl-de/by-2-0',
      subdomains: "abcd",
      maxZoom: 16,
    }).addTo(map);

    const byNr = Object.fromEntries(areas.map((a) => [a.gebiets_nr, a]));

    try {
      const geoRes = await fetch(geojsonUrl);
      const geo: GeoJSON.FeatureCollection = await geoRes.json();

      geojsonLayer = L.geoJSON(geo, {
        style: (f) => {
          const s = f?.properties?.status ?? "rechtskraeftig";
          return style(s, false);
        },
        onEachFeature: (feature, layer) => {
          const cmsArea = byNr[feature.properties?.name] ?? null;
          if (cmsArea) feature.properties.cms = cmsArea;

          layer.on("click", async () => {
            const name = feature.properties?.name;
            const prev = selectedSlug;
            selectedSlug = name ?? null;

            // Re-style all layers
            geojsonLayer?.eachLayer((l) => {
              const f = (l as import("leaflet").Path & { feature?: GeoJSON.Feature }).feature;
              if (!f) return;
              const s = f.properties?.status ?? "rechtskraeftig";
              const sel = f.properties?.name === selectedSlug;
              (l as import("leaflet").Path).setStyle(style(s, sel));
            });

            if (cmsArea) {
              onselect(cmsArea);
              await drawBuffer(L, feature);
            } else {
              onselect(null);
              bufferLayer?.clearLayers();
            }

            // Zoom to feature if first click or switching areas
            if (prev !== name) {
              map!.fitBounds((layer as import("leaflet").Polygon).getBounds(), { padding: [60, 60] });
            }
          });

          // Tooltip with name
          const label = feature.properties?.bezeichnung ?? feature.properties?.name ?? "";
          layer.bindTooltip(label, { sticky: true, className: "windkarte-tooltip" });
        },
      }).addTo(map);
    } catch (e) {
      console.error("GeoJSON laden fehlgeschlagen:", e);
    }
  });

  onDestroy(() => {
    map?.remove();
    map = null;
  });
</script>

<div bind:this={mapEl} class="h-full w-full"></div>

<style>
  :global(.windkarte-tooltip) {
    background: white;
    border: 1px solid #d5d8d6;
    border-radius: 6px;
    box-shadow: 0 1px 4px rgba(0,0,0,0.15);
    color: #333735;
    font-size: 12px;
    font-weight: 500;
    padding: 4px 8px;
  }
  :global(.windkarte-tooltip::before) {
    display: none;
  }
</style>
