"use client";

/**
 * ConceptDrawMap — Leaflet draw-polygon input for the parcel boundary.
 *
 * Uses the imperative `L.Draw.Polygon` handler (leaflet-draw) inside a
 * `useMap()` child rather than the react-leaflet-draw wrapper (not a repo dep).
 * The drawn ring is emitted upward as a GeoJSON Polygon (WGS84) for
 * ConceptInput.parcel_geojson. Re-using the react-leaflet + OSM TileLayer
 * pattern from EntryMap / SiteMap. Lazy-mounted (ssr:false) by the page —
 * Leaflet touches `window`.
 */

import { useEffect, useRef, useState } from "react";
import { MapContainer, TileLayer, GeoJSON, useMap } from "react-leaflet";
import L from "leaflet";
import "leaflet-draw";
import type { Polygon } from "geojson";
import { Pencil, Trash2 } from "lucide-react";

import "leaflet/dist/leaflet.css";
import "leaflet-draw/dist/leaflet.draw.css";

// Yekaterinburg center — matches EntryMap default view.
const EKB_CENTER: [number, number] = [56.8389, 60.6057];
const DEFAULT_ZOOM = 13;

// ── Draw handler child (must live inside MapContainer for useMap) ─────────────

interface DrawLayerProps {
  /** Drawing requested by the parent toolbar (toggled on each click). */
  drawTick: number;
  /** Clear requested by the parent toolbar. */
  clearTick: number;
  onPolygon: (polygon: Polygon) => void;
  onCleared: () => void;
}

function DrawLayer({
  drawTick,
  clearTick,
  onPolygon,
  onCleared,
}: DrawLayerProps) {
  const map = useMap();
  const groupRef = useRef<L.FeatureGroup | null>(null);
  const handlerRef = useRef<L.Draw.Polygon | null>(null);

  // One FeatureGroup holds the single drawn polygon; wire the CREATED event.
  useEffect(() => {
    const group = new L.FeatureGroup();
    group.addTo(map);
    groupRef.current = group;

    const onCreated = (e: L.LeafletEvent) => {
      const { layer } = e as L.DrawEvents.Created;
      // Don't add the layer to the FeatureGroup: the polygon is controlled by
      // the parent via the `polygon` prop, which renders it as a <GeoJSON>.
      // Adding it here would draw a second overlapping copy of the same ring.
      const gj = (layer as L.Polygon).toGeoJSON();
      if (gj.type === "Feature" && gj.geometry.type === "Polygon") {
        onPolygon(gj.geometry);
      }
    };

    map.on(L.Draw.Event.CREATED, onCreated);
    return () => {
      map.off(L.Draw.Event.CREATED, onCreated);
      group.remove();
    };
    // map identity is stable for the MapContainer lifetime; onPolygon is stable.
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  // Start the polygon draw handler when the parent toolbar bumps drawTick.
  useEffect(() => {
    if (drawTick === 0) return;
    handlerRef.current?.disable();
    const handler = new L.Draw.Polygon(map as L.DrawMap, {
      allowIntersection: false,
      showArea: false,
      shapeOptions: {
        color: "#1d4ed8",
        weight: 2.5,
        fillColor: "#3b82f6",
        fillOpacity: 0.2,
      },
    });
    handlerRef.current = handler;
    handler.enable();
    return () => {
      handler.disable();
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [drawTick]);

  // Clear the drawn polygon when the parent toolbar bumps clearTick.
  useEffect(() => {
    if (clearTick === 0) return;
    handlerRef.current?.disable();
    groupRef.current?.clearLayers();
    onCleared();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [clearTick]);

  return null;
}

// ── Component ─────────────────────────────────────────────────────────────────

interface Props {
  /** Externally provided polygon (e.g. resolved from a cadastre number). */
  polygon: Polygon | null;
  onChange: (polygon: Polygon | null) => void;
  height?: number;
}

export function ConceptDrawMap({ polygon, onChange, height = 420 }: Props) {
  // Tick counters bumped by the toolbar buttons drive the DrawLayer effects
  // (start-draw / clear) without exposing a Leaflet ref to the parent.
  const [drawTick, setDrawTick] = useState(0);
  const [clearTick, setClearTick] = useState(0);

  function handleDraw() {
    setDrawTick((t) => t + 1);
  }

  function handleClear() {
    setClearTick((t) => t + 1);
    onChange(null);
  }

  return (
    <div style={{ position: "relative", width: "100%", height }}>
      <MapContainer
        center={EKB_CENTER}
        zoom={DEFAULT_ZOOM}
        style={{ width: "100%", height: "100%", borderRadius: 12 }}
        scrollWheelZoom
      >
        <TileLayer
          attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>'
          url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
        />
        {/* Externally supplied polygon (cadastre → geom). Keyed on the ring so
            react-leaflet remounts the layer when the geometry changes. */}
        {polygon && (
          <GeoJSON
            key={JSON.stringify(polygon.coordinates[0]?.[0] ?? [])}
            data={polygon}
            style={{
              color: "#1d4ed8",
              weight: 2.5,
              fillColor: "#3b82f6",
              fillOpacity: 0.2,
            }}
          />
        )}
        <DrawLayer
          drawTick={drawTick}
          clearTick={clearTick}
          onPolygon={onChange}
          onCleared={() => {}}
        />
      </MapContainer>

      {/* Toolbar — primary draw + clear; overlays the map top-left. */}
      <div
        style={{
          position: "absolute",
          top: 12,
          left: 12,
          zIndex: 1000,
          display: "flex",
          gap: 8,
        }}
      >
        <button
          type="button"
          onClick={handleDraw}
          aria-label="Нарисовать полигон участка"
          style={{
            display: "inline-flex",
            alignItems: "center",
            gap: 6,
            padding: "6px 12px",
            height: 32,
            background: "var(--accent)",
            color: "#fff",
            border: "none",
            borderRadius: 6,
            fontSize: 13,
            fontWeight: 500,
            cursor: "pointer",
          }}
        >
          <Pencil size={14} strokeWidth={1.5} />
          Нарисовать участок
        </button>
        {polygon && (
          <button
            type="button"
            onClick={handleClear}
            aria-label="Очистить полигон"
            style={{
              display: "inline-flex",
              alignItems: "center",
              gap: 6,
              padding: "6px 12px",
              height: 32,
              background: "var(--bg-card)",
              color: "var(--fg-secondary)",
              border: "1px solid var(--border-card)",
              borderRadius: 6,
              fontSize: 13,
              fontWeight: 500,
              cursor: "pointer",
            }}
          >
            <Trash2 size={14} strokeWidth={1.5} />
            Очистить
          </button>
        )}
      </div>
    </div>
  );
}
