// Map used by /rover-locations/map — plots every "good" rover-location
// as a green circle marker with a popup linking to the detail page.

import { updateGridOverlay } from "./maidenhead_grid"

interface RoverPoint {
  id: string
  lat: number
  lon: number
  grid: string
  notes: string | null
}

interface RoverLocationsMapHook extends ViewHook {
  map: L.Map
  gridLayer: L.LayerGroup
  gridVisible: boolean
  mounted(this: RoverLocationsMapHook): void
}

function escapeHtml(str: string): string {
  return str.replace(/[&<>"']/g, ch => {
    switch (ch) {
      case "&": return "&amp;"
      case "<": return "&lt;"
      case ">": return "&gt;"
      case "\"": return "&quot;"
      case "'": return "&#39;"
      default: return ch
    }
  })
}

export const RoverLocationsMap = {
  mounted(this: RoverLocationsMapHook) {
    const points: RoverPoint[] = JSON.parse(this.el.dataset.points || "[]")
    const defaultCenter: [number, number] = [32.897, -97.038]

    const osm = L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
      maxZoom: 19,
      attribution: "&copy; OpenStreetMap contributors"
    })
    const satellite = L.tileLayer(
      "https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}",
      { maxZoom: 21, maxNativeZoom: 19 }
    )

    const map = L.map(this.el, {
      zoomControl: true,
      scrollWheelZoom: true,
      attributionControl: true,
      layers: [osm]
    }).setView(defaultCenter, 6)
    this.map = map

    L.control.layers(
      { "OSM": osm, "Satellite": satellite },
      {},
      { position: "topright", collapsed: false }
    ).addTo(map)

    // Maidenhead grid overlay + toggle.
    this.gridLayer = L.layerGroup().addTo(map)
    this.gridVisible = true
    updateGridOverlay(map, this.gridLayer)
    map.on("moveend", () => {
      if (this.gridVisible) updateGridOverlay(map, this.gridLayer)
    })

    const GridToggle = L.Control.extend({
      options: { position: "topright" as const },
      onAdd: () => {
        const btn = L.DomUtil.create("button", "leaflet-bar leaflet-control")
        btn.innerHTML = "Grid"
        btn.title = "Toggle Maidenhead grid"
        btn.style.cssText =
          "background:#fff;padding:4px 8px;font-size:12px;cursor:pointer;font-weight:600;"
        L.DomEvent.disableClickPropagation(btn)
        btn.onclick = () => {
          this.gridVisible = !this.gridVisible
          if (this.gridVisible) {
            this.gridLayer.addTo(map)
            updateGridOverlay(map, this.gridLayer)
            btn.style.opacity = "1"
          } else {
            this.gridLayer.remove()
            btn.style.opacity = "0.5"
          }
        }
        return btn
      }
    })
    new GridToggle().addTo(map)

    const bounds: [number, number][] = []

    for (const p of points) {
      if (!Number.isFinite(p.lat) || !Number.isFinite(p.lon)) continue

      const popupHtml =
        `<div style="font-size:12px;line-height:1.5;min-width:160px;">` +
        `<strong>${escapeHtml(p.grid)}</strong><br/>` +
        `${p.lat.toFixed(5)}, ${p.lon.toFixed(5)}<br/>` +
        (p.notes ? `<div style="margin-top:4px;white-space:pre-line;">${escapeHtml(p.notes)}</div>` : "") +
        `<a href="/rover-locations/${p.id}" style="color:#3b82f6;">View details &rarr;</a>` +
        `</div>`

      L.circleMarker([p.lat, p.lon], {
        radius: 7,
        color: "#15803d",
        fillColor: "#22c55e",
        fillOpacity: 0.9,
        weight: 2
      })
        .bindPopup(popupHtml, { closeButton: true })
        .bindTooltip(p.grid, { direction: "top", offset: [0, -8] })
        .addTo(map)

      bounds.push([p.lat, p.lon])
    }

    if (bounds.length > 0) {
      map.fitBounds(L.latLngBounds(bounds), { padding: [40, 40], maxZoom: 10 })
    }

    setTimeout(() => map.invalidateSize(), 50)
  }
}
