import { useEffect, useRef } from 'react';
import L from 'leaflet';
import 'leaflet/dist/leaflet.css';
import { gridToLatLon, gridSquareBounds, greatCirclePoints, pathBetween } from '@/lib/maidenhead';

// MainMap — Log4OM-style dual map for the Main tab:
//  • Left: a world map with the great-circle path drawn from the operator to
//    the contacted station, plus distance + short/long-path azimuth.
//  • Right: a street map zoomed onto the contacted station's grid locator.
// Built on Leaflet + free OSM/Carto tiles (no API key). Endpoints use
// circleMarkers / divIcons so we don't depend on Leaflet's image assets.

interface Props {
  fromGrid: string;   // operator grid (active profile)
  toGrid: string;     // contacted-station grid
  fromLabel?: string; // operator callsign
  toLabel?: string;   // DX callsign
}

const CARTO_LIGHT = 'https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png';
const OSM = 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
const CARTO_ATTR = '&copy; OpenStreetMap &copy; CARTO';
const OSM_ATTR = '&copy; OpenStreetMap contributors';

function dot(color: string): L.DivIcon {
  return L.divIcon({
    className: '',
    html: `<span style="display:block;width:12px;height:12px;border-radius:50%;background:${color};border:2px solid #fff;box-shadow:0 0 0 1px rgba(0,0,0,.4)"></span>`,
    iconSize: [12, 12],
    iconAnchor: [6, 6],
  });
}

export function MainMap({ fromGrid, toGrid, fromLabel, toLabel }: Props) {
  const worldRef = useRef<HTMLDivElement>(null);
  const locatorRef = useRef<HTMLDivElement>(null);
  const worldMap = useRef<L.Map | null>(null);
  const locatorMap = useRef<L.Map | null>(null);
  // Layers we add/remove as the QSO changes (kept separate from the basemap).
  const worldOverlay = useRef<L.LayerGroup | null>(null);
  const locatorOverlay = useRef<L.LayerGroup | null>(null);

  // One-time map creation.
  useEffect(() => {
    if (worldRef.current && !worldMap.current) {
      const m = L.map(worldRef.current, { zoomControl: true, attributionControl: true, worldCopyJump: true })
        .setView([20, 0], 1);
      L.tileLayer(CARTO_LIGHT, { attribution: CARTO_ATTR, subdomains: 'abcd', maxZoom: 19 }).addTo(m);
      worldOverlay.current = L.layerGroup().addTo(m);
      worldMap.current = m;
    }
    if (locatorRef.current && !locatorMap.current) {
      const m = L.map(locatorRef.current, { zoomControl: true, attributionControl: true })
        .setView([20, 0], 2);
      L.tileLayer(OSM, { attribution: OSM_ATTR, maxZoom: 19 }).addTo(m);
      locatorOverlay.current = L.layerGroup().addTo(m);
      locatorMap.current = m;
    }
    // The Main tab may have just become visible — fix tile sizing.
    const t = window.setTimeout(() => {
      worldMap.current?.invalidateSize();
      locatorMap.current?.invalidateSize();
    }, 80);
    return () => window.clearTimeout(t);
  }, []);

  // Redraw overlays whenever the operator/DX grids change.
  useEffect(() => {
    const wm = worldMap.current, lm = locatorMap.current;
    const wo = worldOverlay.current, lo = locatorOverlay.current;
    if (!wm || !lm || !wo || !lo) return;
    wo.clearLayers();
    lo.clearLayers();

    const from = gridToLatLon(fromGrid);
    const to = gridToLatLon(toGrid);

    // ── Left: world + great-circle arc ──
    if (from) L.marker([from.lat, from.lon], { icon: dot('#059669'), title: fromLabel || 'Home' }).addTo(wo);
    if (to) {
      L.marker([to.lat, to.lon], { icon: dot('#dc2626'), title: toLabel || 'DX' })
        .bindTooltip(toLabel || toGrid, { permanent: false, direction: 'top' }).addTo(wo);
    }
    if (from && to) {
      const pts = greatCirclePoints(from.lat, from.lon, to.lat, to.lon, 96);
      L.polyline(pts as L.LatLngExpression[], { color: '#dc2626', weight: 2, opacity: 0.9 }).addTo(wo);
      const bounds = L.latLngBounds([[from.lat, from.lon], [to.lat, to.lon]]);
      // Include the arc so high-latitude curves aren't clipped.
      pts.forEach((p) => bounds.extend(p as L.LatLngExpression));
      wm.fitBounds(bounds, { padding: [30, 30], maxZoom: 6 });
    } else if (to) {
      wm.setView([to.lat, to.lon], 3);
    } else if (from) {
      wm.setView([from.lat, from.lon], 3);
    }

    // ── Right: street map on the DX locator ──
    if (to) {
      L.marker([to.lat, to.lon], { icon: dot('#dc2626'), title: toLabel || 'DX' })
        .bindTooltip(`${toLabel ? toLabel + ' · ' : ''}${toGrid.toUpperCase()}`, { permanent: false, direction: 'top' })
        .addTo(lo);
      const b = gridSquareBounds(toGrid);
      if (b) {
        L.rectangle([[b.south, b.west], [b.north, b.east]], { color: '#dc2626', weight: 1, fillOpacity: 0.06 }).addTo(lo);
      }
      lm.setView([to.lat, to.lon], toGrid.trim().length >= 6 ? 9 : 7);
    } else if (from) {
      lm.setView([from.lat, from.lon], 5);
    }
    setTimeout(() => { wm.invalidateSize(); lm.invalidateSize(); }, 0);
  }, [fromGrid, toGrid, fromLabel, toLabel]);

  const path = pathBetween(fromGrid, toGrid);

  return (
    <div className="flex flex-col h-full min-h-0 gap-2 p-2">
      <div className="grid grid-cols-2 gap-2 flex-1 min-h-0">
        <div className="relative isolate rounded-lg overflow-hidden border border-border">
          <div ref={worldRef} className="absolute inset-0" />
          {path && (
            <div className="absolute bottom-1 left-1 z-[500] rounded-md bg-card/90 backdrop-blur px-2 py-1 text-[11px] font-mono shadow border border-border pointer-events-none">
              <div><span className="text-muted-foreground">Dist</span> {Math.round(path.distanceShort).toLocaleString()} km
                <span className="text-muted-foreground"> · LP</span> {Math.round(path.distanceLong).toLocaleString()} km</div>
              <div><span className="text-muted-foreground">Az SP</span> {Math.round(path.bearingShort)}°
                <span className="text-muted-foreground"> · LP</span> {Math.round(path.bearingLong)}°</div>
            </div>
          )}
        </div>
        <div className="relative isolate rounded-lg overflow-hidden border border-border">
          <div ref={locatorRef} className="absolute inset-0" />
          {!gridToLatLon(toGrid) && (
            <div className="absolute inset-0 z-[500] flex items-center justify-center text-xs text-muted-foreground bg-card/60 pointer-events-none">
              Enter a grid or look up the callsign to center the map.
            </div>
          )}
        </div>
      </div>
    </div>
  );
}
