"use client";

/**
 * ConceptResultMap — renders one variant's building placement: the parcel
 * polygon (outline) + the generated buildings FeatureCollection (filled), over
 * an OSM base. Re-uses the react-leaflet + GeoJSON pattern from SiteMap.
 * Lazy-mounted (ssr:false) by the parent — Leaflet touches `window`.
 */

import { useEffect, useMemo } from "react";
import { MapContainer, TileLayer, GeoJSON, useMap } from "react-leaflet";
import type { FeatureCollection, Polygon, Position } from "geojson";
import L from "leaflet";

import "leaflet/dist/leaflet.css";

// ── Bounds helper ─────────────────────────────────────────────────────────────

function ringBounds(rings: Position[][]): L.LatLngBoundsExpression | null {
  let minLat = Infinity;
  let maxLat = -Infinity;
  let minLon = Infinity;
  let maxLon = -Infinity;
  for (const ring of rings) {
    for (const [lon, lat] of ring) {
      if (lat < minLat) minLat = lat;
      if (lat > maxLat) maxLat = lat;
      if (lon < minLon) minLon = lon;
      if (lon > maxLon) maxLon = lon;
    }
  }
  if (!Number.isFinite(minLat)) return null;
  return [
    [minLat, minLon],
    [maxLat, maxLon],
  ];
}

interface FitBoundsProps {
  bounds: L.LatLngBoundsExpression | null;
}

// react-leaflet does not auto-fit to data; do it imperatively once mounted.
function FitBounds({ bounds }: FitBoundsProps) {
  const map = useMap();
  useEffect(() => {
    if (bounds) {
      map.fitBounds(bounds, { padding: [24, 24] });
    }
  }, [map, bounds]);
  return null;
}

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

interface Props {
  parcel: Polygon;
  buildings: FeatureCollection;
  /** Keying makes react-leaflet remount the buildings layer on variant switch. */
  variantKey: string;
  height?: number;
}

export function ConceptResultMap({
  parcel,
  buildings,
  variantKey,
  height = 360,
}: Props) {
  // Memoize so FitBounds only re-fits when the parcel geometry actually
  // changes — recomputing inline returns a new array each render, which would
  // make the fitBounds effect fire on every re-render and discard manual zoom/pan.
  const bounds = useMemo(
    () => ringBounds(parcel.coordinates as Position[][]),
    [parcel.coordinates],
  );
  const hasBuildings = buildings.features.length > 0;

  return (
    <div
      style={{
        border: "1px solid var(--border-card)",
        borderRadius: 12,
        overflow: "hidden",
        height,
        position: "relative",
      }}
    >
      <MapContainer
        center={[56.8389, 60.6057]}
        zoom={15}
        style={{ width: "100%", height: "100%" }}
        scrollWheelZoom
      >
        <TileLayer
          attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OSM</a>'
          url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
        />

        {/* Parcel boundary — outline only so buildings read on top. */}
        <GeoJSON
          key={`parcel-${variantKey}`}
          data={parcel}
          style={{
            color: "#D1D5DB",
            weight: 2,
            dashArray: "6 4",
            fillOpacity: 0,
          }}
        />

        {/* Generated buildings — filled blocks. */}
        {hasBuildings && (
          <GeoJSON
            key={`buildings-${variantKey}`}
            data={buildings}
            style={{
              color: "#1d4ed8",
              weight: 1.5,
              fillColor: "#1d4ed8",
              fillOpacity: 0.55,
            }}
          />
        )}

        <FitBounds bounds={bounds} />
      </MapContainer>

      {!hasBuildings && (
        <div
          style={{
            position: "absolute",
            bottom: 12,
            left: 12,
            right: 12,
            zIndex: 1000,
            background: "var(--bg-card)",
            border: "1px solid var(--border-card)",
            borderRadius: 8,
            padding: "8px 12px",
            fontSize: 12,
            color: "var(--fg-secondary)",
          }}
        >
          Движок ещё не вернул геометрию зданий для этого варианта.
        </div>
      )}
    </div>
  );
}
