"use client";

import React, { useEffect, useRef, useState } from "react";
import L from "leaflet";
import "leaflet/dist/leaflet.css";

export interface MapWaypoint {
  id?: string;
  latitude: number;
  longitude: number;
  caption: string;
  tagCategory?: string;
  imageUrl?: string;
  gpsSource?: string;
  sequenceOrder: number;
  includeInTrace?: boolean;
}

interface GeoTraceMapProps {
  waypoints: MapWaypoint[];
  traceMode: "POLYGON" | "POLYLINE";
  editable?: boolean;
  height?: string;
  onMapClickAddPoint?: (lat: number, lng: number) => void;
  onWaypointDragEnd?: (index: number, lat: number, lng: number) => void;
  defaultCenter?: [number, number];
  defaultZoom?: number;
}

export default function GeoTraceMap({
  waypoints,
  traceMode,
  editable = false,
  height = "440px",
  onMapClickAddPoint,
  onWaypointDragEnd,
  defaultCenter = [-1.2844, 37.2411], // Tala / Kamuthanga, Machakos
  defaultZoom = 15,
}: GeoTraceMapProps) {
  const mapContainerRef = useRef<HTMLDivElement | null>(null);
  const mapInstanceRef = useRef<L.Map | null>(null);
  const layerGroupRef = useRef<L.LayerGroup | null>(null);
  const tileLayerRef = useRef<L.TileLayer | null>(null);
  const [mapStyle, setMapStyle] = useState<"SATELLITE" | "STREET">("SATELLITE");

  // Initialize map once
  useEffect(() => {
    if (!mapContainerRef.current || mapInstanceRef.current) return;

    const map = L.map(mapContainerRef.current, {
      center: defaultCenter,
      zoom: defaultZoom,
      scrollWheelZoom: true,
    });

    const satelliteTile = L.tileLayer(
      "https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}",
      {
        attribution: "Tiles &copy; Esri &mdash; Source: Esri, Maxar, Earthstar Geographics",
        maxZoom: 19,
      }
    );
    satelliteTile.addTo(map);
    tileLayerRef.current = satelliteTile;

    const layerGroup = L.layerGroup().addTo(map);
    layerGroupRef.current = mapInstanceRef.current ? null : layerGroup;
    mapInstanceRef.current = map;

    return () => {
      map.remove();
      mapInstanceRef.current = null;
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  // Handle click on map to add waypoint when editable
  useEffect(() => {
    const map = mapInstanceRef.current;
    if (!map) return;

    const handleClick = (e: L.LeafletMouseEvent) => {
      if (editable && onMapClickAddPoint) {
        onMapClickAddPoint(
          Number(e.latlng.lat.toFixed(6)),
          Number(e.latlng.lng.toFixed(6))
        );
      }
    };

    map.on("click", handleClick);
    return () => {
      map.off("click", handleClick);
    };
  }, [editable, onMapClickAddPoint]);

  // Switch between Satellite and Street view
  useEffect(() => {
    const map = mapInstanceRef.current;
    if (!map) return;

    if (tileLayerRef.current) {
      map.removeLayer(tileLayerRef.current);
    }

    if (mapStyle === "SATELLITE") {
      tileLayerRef.current = L.tileLayer(
        "https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}",
        {
          attribution: "Tiles &copy; Esri Satellite",
          maxZoom: 19,
        }
      ).addTo(map);
    } else {
      tileLayerRef.current = L.tileLayer(
        "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
        {
          attribution: "&copy; OpenStreetMap contributors",
          maxZoom: 19,
        }
      ).addTo(map);
    }
  }, [mapStyle]);

  // Render waypoints and traced Polygon / Polyline
  useEffect(() => {
    const map = mapInstanceRef.current;
    const group = layerGroupRef.current;
    if (!map || !group) return;

    group.clearLayers();

    const ordered = [...waypoints]
      .filter(
        (w) =>
          typeof w.latitude === "number" &&
          typeof w.longitude === "number" &&
          !Number.isNaN(w.latitude) &&
          !Number.isNaN(w.longitude)
      )
      .sort((a, b) => (a.sequenceOrder ?? 0) - (b.sequenceOrder ?? 0));

    const tracePoints = ordered
      .filter((w) => w.includeInTrace !== false)
      .map((w) => [w.latitude, w.longitude] as [number, number]);

    // Draw Polygon or Polyline
    if (tracePoints.length >= 3 && traceMode === "POLYGON") {
      L.polygon(tracePoints, {
        color: "#F5B800",
        weight: 3,
        fillColor: "#F5B800",
        fillOpacity: 0.28,
      }).addTo(group);
    } else if (tracePoints.length >= 2) {
      L.polyline(tracePoints, {
        color: "#F5B800",
        weight: 4,
        dashArray: traceMode === "POLYLINE" ? "8, 6" : undefined,
      }).addTo(group);
    }

    // Draw custom numbered markers
    waypoints.forEach((wp, idx) => {
      if (
        typeof wp.latitude !== "number" ||
        typeof wp.longitude !== "number" ||
        Number.isNaN(wp.latitude) ||
        Number.isNaN(wp.longitude)
      ) {
        return;
      }

      const activeInTrace = wp.includeInTrace !== false;
      const customIcon = L.divIcon({
        className: "davally-map-pin",
        html: `
          <div style="
            width: 32px;
            height: 32px;
            border-radius: 50% 50% 50% 4px;
            transform: rotate(-45deg);
            background: ${activeInTrace ? "#F5B800" : "#64748b"};
            border: 2px solid #141715;
            box-shadow: 0 3px 8px rgba(0,0,0,0.45);
            display: flex;
            align-items: center;
            justify-content: center;
          ">
            <span style="
              transform: rotate(45deg);
              font-weight: 800;
              font-size: 12px;
              color: #141715;
              font-family: sans-serif;
            ">${wp.sequenceOrder || idx + 1}</span>
          </div>
        `,
        iconSize: [32, 32],
        iconAnchor: [16, 32],
        popupAnchor: [0, -30],
      });

      const marker = L.marker([wp.latitude, wp.longitude], {
        icon: customIcon,
        draggable: editable,
      });

      const popupHtml = `
        <div style="min-width:210px;font-family:sans-serif;">
          <div style="font-size:10px;font-weight:700;text-transform:uppercase;color:#b45309;margin-bottom:3px;">
            Waypoint #${wp.sequenceOrder || idx + 1} • ${wp.tagCategory || "GPS Pin"}
          </div>
          <div style="font-size:13px;font-weight:700;color:#0f172a;margin-bottom:6px;">
            ${wp.caption || "Geo-located point"}
          </div>
          ${
            wp.imageUrl
              ? `<img src="${wp.imageUrl}" alt="${wp.caption}" style="width:100%;height:110px;object-fit:cover;border-radius:6px;margin-bottom:6px;border:1px solid #e2e8f0;" />`
              : ""
          }
          <div style="font-size:11px;font-family:monospace;background:#f8fafc;padding:4px 6px;border-radius:4px;color:#334155;">
            Lat: ${wp.latitude.toFixed(6)}<br/>Lng: ${wp.longitude.toFixed(6)}
          </div>
          ${
            wp.gpsSource
              ? `<div style="font-size:10px;color:#64748b;margin-top:4px;">Source: ${wp.gpsSource}</div>`
              : ""
          }
        </div>
      `;

      marker.bindPopup(popupHtml);

      if (editable && onWaypointDragEnd) {
        marker.on("dragend", () => {
          const pos = marker.getLatLng();
          onWaypointDragEnd(
            idx,
            Number(pos.lat.toFixed(6)),
            Number(pos.lng.toFixed(6))
          );
        });
      }

      marker.addTo(group);
    });

    if (ordered.length > 0) {
      const bounds = L.latLngBounds(
        ordered.map((w) => [w.latitude, w.longitude] as [number, number])
      );
      map.fitBounds(bounds, { padding: [45, 45], maxZoom: 17 });
    }
  }, [waypoints, traceMode, editable, onWaypointDragEnd]);

  const handleFitBounds = () => {
    const map = mapInstanceRef.current;
    if (!map || waypoints.length === 0) return;
    const bounds = L.latLngBounds(
      waypoints.map((w) => [w.latitude, w.longitude] as [number, number])
    );
    map.fitBounds(bounds, { padding: [45, 45], maxZoom: 17 });
  };

  return (
    <div className="relative rounded-xl overflow-hidden border border-slate-200 shadow-sm bg-slate-900">
      {/* Top Floating Controls */}
      <div className="absolute top-3 right-3 z-[400] flex items-center gap-1.5 bg-hive-900/90 backdrop-blur-md p-1.5 rounded-lg border border-slate-700 shadow-lg">
        <button
          type="button"
          onClick={() => setMapStyle("SATELLITE")}
          className={`px-2.5 py-1 rounded text-xs font-semibold transition ${
            mapStyle === "SATELLITE"
              ? "bg-honey-500 text-hive-950"
              : "text-slate-200 hover:bg-slate-800"
          }`}
        >
          Satellite GIS
        </button>
        <button
          type="button"
          onClick={() => setMapStyle("STREET")}
          className={`px-2.5 py-1 rounded text-xs font-semibold transition ${
            mapStyle === "STREET"
              ? "bg-honey-500 text-hive-950"
              : "text-slate-200 hover:bg-slate-800"
          }`}
        >
          Street Map
        </button>
        {waypoints.length > 0 && (
          <button
            type="button"
            onClick={handleFitBounds}
            className="px-2.5 py-1 rounded text-xs font-semibold text-honey-400 hover:bg-slate-800 border-l border-slate-700 ml-1"
            title="Center on traced GPS pins"
          >
            Center Trace
          </button>
        )}
      </div>

      {editable && (
        <div className="absolute bottom-3 left-3 z-[400] bg-hive-900/90 backdrop-blur-md text-xs text-slate-200 px-3 py-1.5 rounded-lg border border-honey-500/40 shadow">
          <span className="text-honey-400 font-bold">Interactive GIS Mode:</span>{" "}
          Click anywhere on map to drop a waypoint or drag numbered pins (#1, #2...) to refine boundary.
        </div>
      )}

      <div ref={mapContainerRef} style={{ height, width: "100%" }} />
    </div>
  );
}
