"use client";

import { useCallback, useEffect, useRef, useState } from "react";
import {
  MapContainer,
  TileLayer,
  CircleMarker,
  Tooltip,
  Popup,
  useMapEvents,
} from "react-leaflet";
import type { Map as LeafletMap } from "leaflet";
import { ArrowRight } from "lucide-react";
import "leaflet/dist/leaflet.css";

import type {
  ParcelBboxItem,
  BboxCoords,
  ParcelBboxFilters,
} from "@/lib/site-finder-api";
import { useParcelsBboxQuery } from "@/lib/site-finder-api";
import { STATUS_COLORS, STATUS_LABELS } from "./ParcelLegend";

// ── Bbox change listener ───────────────────────────────────────────────────────

interface BboxListenerProps {
  onBboxChange: (bbox: BboxCoords) => void;
}

function BboxListener({ onBboxChange }: BboxListenerProps) {
  const map = useMapEvents({
    moveend() {
      const bounds = map.getBounds();
      onBboxChange({
        minLat: bounds.getSouth(),
        minLon: bounds.getWest(),
        maxLat: bounds.getNorth(),
        maxLon: bounds.getEast(),
      });
    },
    zoomend() {
      const bounds = map.getBounds();
      onBboxChange({
        minLat: bounds.getSouth(),
        minLon: bounds.getWest(),
        maxLat: bounds.getNorth(),
        maxLon: bounds.getEast(),
      });
    },
  });

  // Emit initial bbox on mount
  useEffect(() => {
    const bounds = map.getBounds();
    onBboxChange({
      minLat: bounds.getSouth(),
      minLon: bounds.getWest(),
      maxLat: bounds.getNorth(),
      maxLon: bounds.getEast(),
    });
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  return null;
}

// ── Parcel markers ─────────────────────────────────────────────────────────────

interface ParcelMarkersProps {
  parcels: ParcelBboxItem[];
  selectedCad: string | null;
  /** Open the full analysis page for a parcel (primary action). */
  onOpen: (parcel: ParcelBboxItem) => void;
  /** Open the side drawer with a parcel preview (secondary action). */
  onSelect: (parcel: ParcelBboxItem) => void;
}

function ParcelMarkers({
  parcels,
  selectedCad,
  onOpen,
  onSelect,
}: ParcelMarkersProps) {
  return (
    <>
      {parcels.map((parcel) => {
        const color = STATUS_COLORS[parcel.status] ?? "#73767E";
        const statusLabel = STATUS_LABELS[parcel.status] ?? parcel.status;
        const isSelected = parcel.cad_num === selectedCad;
        return (
          <CircleMarker
            key={parcel.cad_num}
            center={[parcel.lat, parcel.lon]}
            radius={isSelected ? 10 : 7}
            pathOptions={{
              color: isSelected ? "#0F172A" : color,
              fillColor: color,
              fillOpacity: 0.85,
              weight: isSelected ? 2.5 : 1.5,
            }}
            // Leaflet renders interactive vector markers with a pointer cursor
            // and keeps them keyboard-focusable; click opens the Popup below.
          >
            {/* Hover hint — quick identity without committing to the analyze POST */}
            <Tooltip direction="top" offset={[0, -8]} opacity={0.95}>
              <div style={{ fontSize: 12 }}>
                <div style={{ fontWeight: 600 }}>{parcel.cad_num}</div>
                <div style={{ color: "var(--fg-secondary)" }}>
                  {parcel.area_ha != null ? parcel.area_ha.toFixed(2) : "—"} га · {statusLabel}
                </div>
                <div style={{ color: "var(--fg-tertiary)", marginTop: 2 }}>
                  Нажмите, чтобы открыть анализ
                </div>
              </div>
            </Tooltip>

            {/* Click target — interactive popup with the primary navigate action */}
            <Popup>
              <div style={{ fontSize: 12, minWidth: 168 }}>
                <div
                  style={{
                    fontWeight: 600,
                    color: "var(--fg-primary)",
                    fontVariantNumeric: "tabular-nums",
                  }}
                >
                  {parcel.cad_num}
                </div>
                <div
                  style={{ color: "var(--fg-secondary)", marginBottom: 8 }}
                >
                  {parcel.area_ha != null ? parcel.area_ha.toFixed(2) : "—"} га · {statusLabel}
                </div>
                <button
                  type="button"
                  onClick={() => onOpen(parcel)}
                  aria-label={`Открыть анализ участка ${parcel.cad_num}`}
                  style={{
                    display: "flex",
                    alignItems: "center",
                    justifyContent: "center",
                    gap: 6,
                    width: "100%",
                    background: "var(--accent)",
                    color: "#fff",
                    border: "none",
                    borderRadius: 6,
                    padding: "6px 12px",
                    fontSize: 13,
                    fontWeight: 500,
                    cursor: "pointer",
                  }}
                >
                  Открыть анализ
                  <ArrowRight size={14} strokeWidth={1.5} />
                </button>
                <button
                  type="button"
                  onClick={() => onSelect(parcel)}
                  style={{
                    display: "block",
                    width: "100%",
                    background: "none",
                    border: "none",
                    color: "var(--fg-secondary)",
                    padding: "6px 12px 0",
                    fontSize: 12,
                    cursor: "pointer",
                    textAlign: "center",
                  }}
                >
                  Подробнее в карточке
                </button>
              </div>
            </Popup>
          </CircleMarker>
        );
      })}
    </>
  );
}

// ── EntryMap ───────────────────────────────────────────────────────────────────

// Yekaterinburg center
const EKB_CENTER: [number, number] = [56.8389, 60.6057];
const DEFAULT_ZOOM = 12;

interface EntryMapProps {
  filters: ParcelBboxFilters;
  selectedCad: string | null;
  /** Primary action: navigate to the analysis page for a parcel. */
  onParcelOpen: (parcel: ParcelBboxItem) => void;
  /** Secondary action: open the preview drawer for a parcel. */
  onParcelSelect: (parcel: ParcelBboxItem) => void;
  onParcelDeselect: () => void;
  /** Called whenever the map viewport changes — allows parent to read bbox for filter counters */
  onBboxChange?: (bbox: BboxCoords) => void;
}

export function EntryMap({
  filters,
  selectedCad,
  onParcelOpen,
  onParcelSelect,
  onParcelDeselect,
  onBboxChange,
}: EntryMapProps) {
  const [bbox, setBbox] = useState<BboxCoords | null>(null);
  const mapRef = useRef<LeafletMap | null>(null);

  const { data: parcels, isFetching } = useParcelsBboxQuery(bbox, filters);

  const handleBboxChange = useCallback(
    (newBbox: BboxCoords) => {
      setBbox(newBbox);
      onBboxChange?.(newBbox);
    },
    [onBboxChange],
  );

  return (
    <div style={{ position: "relative", width: "100%", height: "100%" }}>
      <MapContainer
        center={EKB_CENTER}
        zoom={DEFAULT_ZOOM}
        style={{ width: "100%", height: "100%", borderRadius: 12 }}
        ref={mapRef}
        // Click on map backdrop deselects parcel
        // handled via eventHandlers on markers + backdrop div
      >
        <TileLayer
          attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>'
          url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
        />
        <BboxListener onBboxChange={handleBboxChange} />
        {parcels && parcels.length > 0 && (
          <ParcelMarkers
            parcels={parcels}
            selectedCad={selectedCad}
            onOpen={onParcelOpen}
            onSelect={onParcelSelect}
          />
        )}
      </MapContainer>

      {/* Deselect on map click — overlay to capture clicks outside markers.
          zIndex must stay below ParcelDrawer (z20, sibling in .gd-map-shell):
          neither this root nor .gd-map-shell creates a stacking context, so a
          higher zIndex here would paint over the drawer and swallow its clicks
          (X / "Открыть анализ" / ПКК link). z10 keeps the overlay above the
          Leaflet map content but under the drawer card. */}
      {selectedCad && (
        <div
          style={{ position: "absolute", inset: 0, zIndex: 10 }}
          onClick={onParcelDeselect}
          aria-hidden="true"
        />
      )}

      {/* Fetching indicator */}
      {isFetching && (
        <div
          style={{
            position: "absolute",
            top: 12,
            left: "50%",
            transform: "translateX(-50%)",
            zIndex: 1000,
            background: "var(--bg-card)",
            border: "1px solid var(--border-card)",
            borderRadius: 20,
            padding: "4px 14px",
            fontSize: 12,
            color: "var(--fg-secondary)",
          }}
        >
          Загрузка участков...
        </div>
      )}

      {/* Empty state */}
      {!isFetching && parcels && parcels.length === 0 && (
        <div
          style={{
            position: "absolute",
            top: "50%",
            left: "50%",
            transform: "translate(-50%, -50%)",
            zIndex: 1000,
            background: "var(--bg-card)",
            border: "1px solid var(--border-card)",
            borderRadius: 12,
            padding: "16px 24px",
            fontSize: 13,
            color: "var(--fg-secondary)",
            textAlign: "center",
          }}
        >
          Нет участков в текущем виде. Измените фильтры или область карты.
        </div>
      )}
    </div>
  );
}
