'use client'

import React, { useEffect, useRef, useState } from 'react'
import { motion } from 'framer-motion'
import { WeatherWidget } from './WeatherWidget'
import { NotamPanel } from './NotamPanel'
import './MapView.css'

interface MapViewProps {
  initialLat?: number
  initialLng?: number
  initialZoom?: number
}

type LayerKey = 'anac' | 'ed318' | 'notams' | 'spots'
type Layers = Record<LayerKey, boolean>

const LAYER_LABELS: Record<LayerKey, string> = {
  anac: 'Zonas ANAC (ED-269)',
  ed318: 'Zonas ED-318',
  notams: 'NOTAMs',
  spots: 'Spots',
}

const LAYER_COLORS: Record<LayerKey, string> = {
  anac: '#0096FF',
  ed318: '#8B5CF6',
  notams: '#E03345',
  spots: '#00B894',
}

const ZONE_COLORS: Record<string, string> = {
  FREE: '#00B894',
  CONDITIONAL: '#F5A623',
  FORBIDDEN: '#FF4D5E',
}

const ZONE_LABELS: Record<string, string> = {
  FREE: 'Voo Livre',
  CONDITIONAL: 'Autorização Necessária',
  FORBIDDEN: 'Voo Proibido',
}

function pipPolygon(lat: number, lng: number, coords: number[][][]): boolean {
  const ring = coords[0]
  let inside = false
  for (let i = 0, j = ring.length - 1; i < ring.length; j = i++) {
    const [xi, yi] = ring[i]
    const [xj, yj] = ring[j]
    if ((yi > lat) !== (yj > lat) && lng < ((xj - xi) * (lat - yi)) / (yj - yi) + xi) {
      inside = !inside
    }
  }
  return inside
}

export function MapView({ initialLat = 39.3999, initialLng = -8.2245, initialZoom = 7 }: MapViewProps) {
  const mapContainer = useRef<HTMLDivElement>(null)
  const mapRef = useRef<any>(null)
  const layerGroupsRef = useRef<Record<LayerKey, any>>({ anac: null, ed318: null, notams: null, spots: null })

  const [center, setCenter] = useState({ lat: initialLat, lng: initialLng })
  const [mapLoaded, setMapLoaded] = useState(false)
  const [showNotams, setShowNotams] = useState(false)
  const [showLayersPanel, setShowLayersPanel] = useState(false)
  const [layers, setLayers] = useState<Layers>({ anac: true, ed318: false, notams: false, spots: false })

  // Toggle layer groups on/off when `layers` state changes
  useEffect(() => {
    const map = mapRef.current
    if (!map) return
    ;(Object.keys(layers) as LayerKey[]).forEach((key) => {
      const lg = layerGroupsRef.current[key]
      if (!lg) return
      if (layers[key]) {
        if (!map.hasLayer(lg)) lg.addTo(map)
      } else {
        if (map.hasLayer(lg)) map.removeLayer(lg)
      }
    })
  }, [layers])

  useEffect(() => {
    if (!mapContainer.current || mapRef.current) return

    const initMap = async () => {
      const L = (await import('leaflet')).default
      // @ts-ignore
      await import('leaflet/dist/leaflet.css')

      const map = L.map(mapContainer.current!, {
        center: [initialLat, initialLng],
        zoom: initialZoom,
        zoomControl: false,
      })
      mapRef.current = map

      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/">CARTO</a>',
        subdomains: 'abcd',
        maxZoom: 19,
      }).addTo(map)

      L.control.zoom({ position: 'topright' }).addTo(map)

      // Helper: build a zone GeoJSON layer group
      function buildZoneLayer(geojson: any, layerKey: LayerKey) {
        const allFeatures: GeoJSON.Feature[] = geojson.features ?? []
        const lg = L.layerGroup()

        L.geoJSON(geojson, {
          // prevent default marker-icon.png for any stray Point features
          pointToLayer: () => L.circleMarker([0, 0], { radius: 0, opacity: 0, fillOpacity: 0 }),
          style: (feature) => {
            const status = feature?.properties?.status ?? 'FREE'
            const color = ZONE_COLORS[status] ?? '#6B7280'
            return { color, weight: 2, fillColor: color, fillOpacity: 0.25, opacity: 0.9 }
          },
          onEachFeature: (feature, layer) => {
            const { name } = feature.properties ?? {}
            if (name) layer.bindTooltip(name, { sticky: true, className: 'ov-zone-tooltip' })
            layer.on('click', (e: any) => {
              L.DomEvent.stopPropagation(e)
              const { lat, lng } = e.latlng
              const hits = allFeatures.filter((f) => {
                const g = f.geometry as any
                return g?.type === 'Polygon' && pipPolygon(lat, lng, g.coordinates)
              })
              if (!hits.length) return
              const header = `<div style="font-weight:700;font-size:11px;color:#fff;background:#0A1628;padding:8px 10px;letter-spacing:0.04em;text-transform:uppercase">${hits.length} zona${hits.length !== 1 ? 's' : ''} neste ponto</div>`
              const items = hits.map((f: any) => {
                const { name: n, status, lowerLimit, upperLimit, message, authorityName, authorityUrl, authorityEmail, authorityPhone, schedule } = f.properties
                const color = ZONE_COLORS[status] ?? '#6B7280'
                const label = ZONE_LABELS[status] ?? status
                const lo = lowerLimit ? `${lowerLimit.value} ${lowerLimit.uom}` : '0 M'
                const hi = upperLimit ? `${upperLimit.value} ${upperLimit.uom}` : '—'
                const msgHtml = message ? `<div style="font-size:10px;color:#4A5568;line-height:1.4;margin-top:4px;padding:4px 6px;background:#f7f7f7;border-radius:3px">${message}</div>` : ''
                const schedHtml = schedule ? `<div style="font-size:10px;color:#718096;margin-top:3px">🕐 ${schedule}</div>` : ''
                const authorityHtml = authorityName ? `<div style="font-size:10px;font-weight:600;color:#0A1628;margin-top:5px;padding-top:5px;border-top:1px solid #eee">${authorityName}</div>` : ''
                const contactHtml = (authorityPhone || authorityEmail || authorityUrl) ? `<div style="font-size:10px;color:#718096;margin-top:2px;display:flex;flex-direction:column;gap:2px">${authorityPhone ? `<span>📞 ${authorityPhone}</span>` : ''}${authorityEmail ? `<a href="mailto:${authorityEmail}" style="color:#0096FF;text-decoration:none">✉ ${authorityEmail}</a>` : ''}${authorityUrl ? `<a href="${authorityUrl}" target="_blank" rel="noopener" style="color:#0096FF;text-decoration:none">🌐 ${authorityUrl.replace(/^https?:\/\//, '')}</a>` : ''}</div>` : ''
                const textOnColor = status === 'CONDITIONAL' ? '#5C3D00' : '#fff'
                const bodyBg = status === 'FORBIDDEN' ? '#FFE8EA' : status === 'CONDITIONAL' ? '#FEF3D0' : '#D6F5EE'
                const bodyText = '#0A1628'
                return `<div style="border-bottom:2px solid ${color};overflow:hidden;border-radius:6px;margin-bottom:6px;border:2px solid ${color}">
                  <div style="background:${color};padding:8px 10px">
                    <div style="font-weight:700;font-size:12px;color:${textOnColor};margin-bottom:2px">${n ?? 'Zona ANAC'}</div>
                    <div style="font-size:11px;font-weight:600;color:${textOnColor};opacity:0.9">${label}</div>
                  </div>
                  <div style="background:${bodyBg};padding:8px 10px;color:${bodyText}">
                    <div style="font-size:10px;margin-bottom:3px">Alt: ${lo} – ${hi} AGL</div>
                    ${msgHtml}${schedHtml}${authorityHtml}${contactHtml}
                  </div>
                </div>`
              }).join('')
              L.popup({ maxWidth: 280, className: 'ov-zone-popup' })
                .setLatLng(e.latlng)
                .setContent(`<div style="font-family:sans-serif">${header}${items}</div>`)
                .openOn(map)
            })
          },
        }).addTo(lg)

        layerGroupsRef.current[layerKey] = lg
        if (layers[layerKey]) lg.addTo(map)
      }

      // Load ED-269 (ANAC zones)
      try {
        const res = await fetch('/api/anac/zones')
        if (res.ok) buildZoneLayer(await res.json(), 'anac')
      } catch {}

      // Load ED-318 zones
      try {
        const res = await fetch('/api/anac/ed318')
        if (res.ok) buildZoneLayer(await res.json(), 'ed318')
      } catch {}

      // NOTAMs circles
      try {
        const res = await fetch('/api/notams')
        if (res.ok) {
          const { notams } = await res.json()
          const lg = L.layerGroup()

          function parseNotamCoords(desc: string): { lat: number; lng: number; radiusNm: number } | null {
            const m = (desc ?? '').match(/\/(\d{4}[NS])(\d{5}[EW])(\d{1,4})/)
            if (!m) return null
            const [, latStr, lngStr, rStr] = m
            const lat = (parseInt(latStr.slice(0, 2)) + parseInt(latStr.slice(2, 4)) / 60) * (latStr[4] === 'S' ? -1 : 1)
            const lng = (parseInt(lngStr.slice(0, 3)) + parseInt(lngStr.slice(3, 5)) / 60) * (lngStr[5] === 'W' ? -1 : 1)
            return { lat, lng, radiusNm: parseInt(rStr) }
          }

          notams?.forEach((n: any) => {
            const coords = parseNotamCoords(n.description ?? '')
            if (!coords) return
            const radiusM = coords.radiusNm * 1852
            if (radiusM > 185200) return
            L.circle([coords.lat, coords.lng], {
              radius: Math.max(radiusM, 500),
              color: '#E03345', fillColor: '#E03345', fillOpacity: 0.08,
              weight: 2, dashArray: '6,4',
            })
              .bindPopup(`<div style="font-family:sans-serif;max-width:260px">
                <div style="font-weight:700;font-size:12px;color:#E03345;margin-bottom:4px">⚠️ ${n.notamId}</div>
                <div style="font-size:11px;font-weight:600;color:#0A1628;line-height:1.4;margin-bottom:6px">${(n.title ?? '').replace(n.notamId + ': ', '')}</div>
                ${n.description ? `<div style="font-size:10px;color:#4A5568;line-height:1.5;border-top:1px solid #eee;padding-top:6px">${n.description}</div>` : ''}
              </div>`, { maxWidth: 280 })
              .addTo(lg)
          })

          layerGroupsRef.current.notams = lg
          if (layers.notams) lg.addTo(map)
        }
      } catch {}

      // Spot markers — brand SVG markers
      try {
        const res = await fetch('/api/spots?limit=100')
        if (res.ok) {
          const { spots } = await res.json()
          const lg = L.layerGroup()
          const DIFF_MARKER: Record<string, string> = {
            BEGINNER:     '/brand/markers/ondevoar-marker-livre.svg',
            INTERMEDIATE: '/brand/markers/ondevoar-marker-condicionada.svg',
            ADVANCED:     '/brand/markers/ondevoar-marker-proibida.svg',
          }
          spots?.forEach((spot: { id: string; name: string; lat: number; lng: number; difficulty: string }) => {
            const iconUrl = DIFF_MARKER[spot.difficulty] ?? '/brand/markers/ondevoar-marker-azul.svg'
            const icon = L.icon({ iconUrl, iconSize: [32, 40], iconAnchor: [16, 40], popupAnchor: [0, -42] })
            L.marker([spot.lat, spot.lng], { icon })
              .bindPopup(`<a href="/spots/${spot.id}" style="font-family:sans-serif;font-weight:600;color:#0096FF;text-decoration:none">${spot.name}</a>`)
              .addTo(lg)
          })
          layerGroupsRef.current.spots = lg
          if (layers.spots) lg.addTo(map)
        }
      } catch {}

      map.on('moveend', () => {
        const c = map.getCenter()
        setCenter({ lat: parseFloat(c.lat.toFixed(4)), lng: parseFloat(c.lng.toFixed(4)) })
      })

      setMapLoaded(true)
    }

    initMap()

    return () => {
      if (mapRef.current) {
        ;(mapRef.current as { remove: () => void }).remove()
        mapRef.current = null
      }
    }
  }, [])

  function toggleLayer(key: LayerKey) {
    setLayers((prev) => ({ ...prev, [key]: !prev[key] }))
  }

  return (
    <motion.div
      className="map-container"
      initial={{ opacity: 0 }}
      animate={{ opacity: 1 }}
      transition={{ duration: 0.4 }}
    >
      <div ref={mapContainer} style={{ width: '100%', height: '100%' }} />

      {mapLoaded && (
        <>
          {/* Weather */}
          <div style={{ position: 'absolute', top: 'var(--ov-space-4)', left: 'var(--ov-space-4)', zIndex: 1000 }}>
            <WeatherWidget lat={center.lat} lng={center.lng} />
          </div>

          {/* Layers toggle button */}
          <button
            onClick={() => setShowLayersPanel((v) => !v)}
            aria-label="Gerir layers"
            className={`map-layers-btn${showLayersPanel ? ' active' : ''}`}
          >
            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
              <polygon points="12 2 2 7 12 12 22 7 12 2"/>
              <polyline points="2 17 12 22 22 17"/>
              <polyline points="2 12 12 17 22 12"/>
            </svg>
            Layers
          </button>

          {/* Layers panel */}
          {showLayersPanel && (
            <div className="map-layers-panel" role="dialog" aria-label="Gerir layers do mapa">
              <div className="map-layers-panel__title">Layers</div>
              {(Object.keys(LAYER_LABELS) as LayerKey[]).map((key) => (
                <label key={key} className="map-layers-panel__row">
                  <span className="map-layers-panel__dot" style={{ background: LAYER_COLORS[key] }} />
                  <span className="map-layers-panel__label">{LAYER_LABELS[key]}</span>
                  <input
                    type="checkbox"
                    checked={layers[key]}
                    onChange={() => toggleLayer(key)}
                    className="map-layers-panel__check"
                    aria-label={`${layers[key] ? 'Desactivar' : 'Activar'} layer ${LAYER_LABELS[key]}`}
                  />
                </label>
              ))}
            </div>
          )}

          {/* NOTAM panel button */}
          <button
            onClick={() => setShowNotams((v) => !v)}
            aria-label="Ver NOTAMs"
            className="map-notams-btn"
          >
            ⚠️ NOTAMs
          </button>

          {showNotams && <NotamPanel onClose={() => setShowNotams(false)} />}

          {/* Legend */}
          <div className="map-legend">
            <div className="map-legend-title">Zonas de Voo</div>
            <div className="map-legend-item">
              <span className="map-legend-dot" style={{ background: '#00B894' }} />
              <span><strong>Livre</strong> — voo permitido</span>
            </div>
            <div className="map-legend-item">
              <span className="map-legend-dot" style={{ background: '#F5A623' }} />
              <span><strong>Condicionada</strong> — autorização necessária</span>
            </div>
            <div className="map-legend-item">
              <span className="map-legend-dot" style={{ background: '#FF4D5E' }} />
              <span><strong>Proibida</strong> — voo não permitido</span>
            </div>
            <div className="map-legend-hint">Clique numa zona para detalhes</div>
          </div>
        </>
      )}
    </motion.div>
  )
}
