<script lang="ts">
  import "leaflet/dist/leaflet.css";
  import { onMount, onDestroy } from "svelte";
  import { getBlockLayoutClasses } from "$lib/block-layout";
  import type { OrganisationsMapBlockData, OrganisationEntry, ContactEntry } from "$lib/block-types";
  import Icon from "@iconify/svelte";
  import "$lib/iconify-offline";
  import { marked } from "$lib/markdown-safe";

  let { block }: { block: OrganisationsMapBlockData } = $props();

  const layoutClasses = $derived(getBlockLayoutClasses(block.layout));

  const orgs = $derived(
    (block.organisations ?? []).filter(
      (o): o is OrganisationEntry =>
        typeof o === "object" &&
        o !== null &&
        typeof o.location?.lat === "number" &&
        typeof o.location?.lng === "number",
    ),
  );

  let mapEl: HTMLDivElement;
  let map: import("leaflet").Map | null = null;
  let selectedOrg = $state<OrganisationEntry | null>(null);
  // Keep reference to highlight active marker
  let activeMarker: import("leaflet").CircleMarker | null = null;

  const descriptionHtml = $derived(
    selectedOrg?.description
      ? (marked.parse(selectedOrg.description) as string)
      : "",
  );

  const contacts = $derived(
    (selectedOrg?.contacts ?? []).filter(
      (c): c is ContactEntry => typeof c === "object" && c !== null && !!c.name,
    ),
  );

  function getLink(org: OrganisationEntry): string | null {
    if (!org.link || typeof org.link === "string") return null;
    return org.link.url ?? null;
  }

  function getLinkLabel(org: OrganisationEntry): string {
    if (!org.link || typeof org.link === "string") return "Website";
    return org.link.linkName ?? "Website";
  }

  function closePanel() {
    selectedOrg = null;
    if (activeMarker) {
      activeMarker.setStyle({ fillColor: "#3d6b4f", radius: 8 });
      activeMarker = null;
    }
  }

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

    map = L.map(mapEl, { zoomControl: true });

    L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
      attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>',
      maxZoom: 18,
    }).addTo(map);

    for (const org of orgs) {
      const { lat, lng } = org.location!;
      const marker = L.circleMarker([lat!, lng!], {
        radius: 8,
        fillColor: "#3d6b4f",
        color: "#fff",
        weight: 2,
        opacity: 1,
        fillOpacity: 0.9,
      })
        .bindTooltip(org.name ?? "", {
          permanent: false,
          direction: "top",
          className: "orgs-map-tip",
          offset: [0, -6],
        })
        .addTo(map!)
        .on("click", () => {
          if (activeMarker && activeMarker !== marker) {
            activeMarker.setStyle({ fillColor: "#3d6b4f", radius: 8 });
          }
          marker.setStyle({ fillColor: "#1a4030", radius: 11 });
          activeMarker = marker;
          selectedOrg = org;
        });
    }

    if (orgs.length > 0) {
      const bounds = L.latLngBounds(
        orgs.map((o) => [o.location!.lat!, o.location!.lng!] as [number, number]),
      );
      map.fitBounds(bounds, { padding: [50, 50], maxZoom: 11 });
    }
  });

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

<div class="not-prose {layoutClasses}" data-block-type="organisations_map">
  {#if block.headline}
    <h2 class="mb-3 text-xl font-bold text-stein-900">{block.headline}</h2>
  {/if}

  <div
    class="relative overflow-hidden rounded-sm border border-stein-200"
    style="height: clamp(400px, 65vh, 560px)"
  >
    <!-- Leaflet map fills the container -->
    <div bind:this={mapEl} class="absolute inset-0"></div>

    <!-- Detail panel slides in from right (desktop) / bottom (mobile) -->
    {#if selectedOrg}
      <div
        class="absolute bottom-0 left-0 right-0 z-[1000] max-h-[55%] overflow-y-auto border-t border-stein-200 bg-white shadow-lg
               lg:bottom-0 lg:left-auto lg:right-0 lg:top-0 lg:w-72 lg:max-h-full lg:border-t-0 lg:border-l"
      >
        <div class="p-4">
          <div class="mb-3 flex items-start justify-between gap-2">
            <p class="text-sm font-semibold leading-snug text-stein-900">
              {selectedOrg.name}
            </p>
            <button
              type="button"
              onclick={closePanel}
              class="shrink-0 text-stein-400 transition-colors hover:text-stein-700"
              aria-label="Schließen"
            >
              <Icon icon="mdi:close" class="size-4" />
            </button>
          </div>

          {#if selectedOrg.location?.text}
            <p class="mb-3 flex items-center gap-1 text-xs text-stein-500">
              <Icon icon="mdi:map-marker-outline" class="size-3.5 shrink-0" />
              {selectedOrg.location.text}
            </p>
          {/if}

          {#if selectedOrg.resolvedLogoSrc}
            <img
              src={selectedOrg.resolvedLogoSrc}
              alt={selectedOrg.name ?? ""}
              class="mb-3 max-h-10 object-contain"
            />
          {/if}

          {#if descriptionHtml}
            <div class="markdown prose prose-sm mb-3 max-w-none text-xs text-stein-600">
              {@html descriptionHtml}
            </div>
          {/if}

          {#if contacts.length > 0}
            <div class="mb-3 space-y-2 border-t border-stein-100 pt-3">
              <p class="text-[0.65rem] font-semibold uppercase tracking-wider text-stein-500">Ansprechpartner</p>
              {#each contacts as c}
                <div class="text-xs">
                  <p class="font-semibold text-stein-800">{c.name}</p>
                  {#if c.role}
                    <p class="text-stein-500">{c.role}</p>
                  {/if}
                  {#if c.email}
                    <a href="mailto:{c.email}" class="mt-0.5 flex items-center gap-1 text-wald-700 hover:underline">
                      <Icon icon="mdi:email-outline" class="size-3 shrink-0" />
                      <span class="truncate">{c.email}</span>
                    </a>
                  {/if}
                  {#if c.phone}
                    <a href="tel:{c.phone.replace(/\s+/g, '')}" class="mt-0.5 flex items-center gap-1 text-wald-700 hover:underline">
                      <Icon icon="mdi:phone" class="size-3 shrink-0" />
                      {c.phone}
                    </a>
                  {/if}
                  {#if c.note}
                    <p class="mt-0.5 italic text-stein-500">{c.note}</p>
                  {/if}
                </div>
              {/each}
            </div>
          {/if}

          {#if getLink(selectedOrg)}
            <a
              href={getLink(selectedOrg)}
              target="_blank"
              rel="noopener noreferrer"
              class="btn-outline btn-sm w-full justify-center no-underline!"
            >
              <Icon icon="mdi:open-in-new" class="size-3.5" />
              {getLinkLabel(selectedOrg)}
            </a>
          {/if}
        </div>
      </div>
    {/if}
  </div>

  <p class="mt-1.5 text-xs text-stein-400">{orgs.length} Bürgerinitiativen · Marker anklicken für Details</p>
</div>

<style>
  :global(.orgs-map-tip) {
    background: #1c1917;
    border: none;
    border-radius: 3px;
    color: #fafaf9;
    font-size: 0.65rem;
    padding: 2px 6px;
    white-space: nowrap;
  }
  :global(.orgs-map-tip::before) {
    border-top-color: #1c1917 !important;
  }
</style>
