// MapView — MapLibre GL with custom DOM markers.
// We render markers as React-controlled DOM nodes attached via maplibregl.Marker
// so hover/active states sync with the listing list.

const { useEffect, useRef, useState, useMemo } = React;

const MAP_STYLES = {
  warm: {
    version: 8,
    sources: {
      "osm": {
        type: "raster",
        tiles: ["https://tile.openstreetmap.org/{z}/{x}/{y}.png"],
        tileSize: 256,
        attribution: "© OpenStreetMap contributors",
        maxzoom: 19,
      },
    },
    layers: [
      { id: "bg", type: "background", paint: { "background-color": "#FAF7F2" } },
      {
        id: "osm",
        type: "raster",
        source: "osm",
        paint: { "raster-opacity": 0.55, "raster-saturation": -0.7, "raster-contrast": -0.1, "raster-brightness-min": 0.15 },
      },
    ],
  },
  muted: {
    version: 8,
    sources: {
      "osm": {
        type: "raster",
        tiles: ["https://tile.openstreetmap.org/{z}/{x}/{y}.png"],
        tileSize: 256,
        attribution: "© OpenStreetMap contributors",
        maxzoom: 19,
      },
    },
    layers: [
      { id: "bg", type: "background", paint: { "background-color": "#EEE9E0" } },
      {
        id: "osm",
        type: "raster",
        source: "osm",
        paint: { "raster-opacity": 0.35, "raster-saturation": -1, "raster-contrast": 0.1, "raster-brightness-min": 0.2 },
      },
    ],
  },
  stylized: null, // handled separately as SVG
};

function MapView({ listings, activeId, hoverId, onMarkerClick, onMarkerHover, mapStyle, accent }) {
  const containerRef = useRef(null);
  const mapRef = useRef(null);
  const markersRef = useRef({});
  const [ready, setReady] = useState(false);

  // Init map
  useEffect(() => {
    if (mapStyle === "stylized") return; // handled by SVG fallback
    if (!containerRef.current || mapRef.current) return;

    const map = new maplibregl.Map({
      container: containerRef.current,
      style: MAP_STYLES[mapStyle] || MAP_STYLES.warm,
      center: [37.62, 55.752],
      zoom: 10.5,
      attributionControl: false,
      cooperativeGestures: false,
    });
    map.addControl(new maplibregl.NavigationControl({ showCompass: false }), "top-right");
    map.on("load", () => setReady(true));
    mapRef.current = map;

    return () => {
      map.remove();
      mapRef.current = null;
      markersRef.current = {};
      setReady(false);
    };
  }, [mapStyle]);

  // Manage markers
  useEffect(() => {
    const map = mapRef.current;
    if (!map || !ready) return;

    // Remove old
    Object.values(markersRef.current).forEach((m) => m.remove());
    markersRef.current = {};

    listings.forEach((l) => {
      const el = document.createElement("button");
      el.className = "map-marker";
      el.dataset.id = l.id;
      el.innerHTML = `
        <span class="map-marker-pin">
          <span class="map-marker-price">${formatPriceShort(l.price)}</span>
        </span>
        <span class="map-marker-stem"></span>
      `;
      el.addEventListener("click", (e) => {
        e.stopPropagation();
        onMarkerClick && onMarkerClick(l.id);
      });
      el.addEventListener("mouseenter", () => onMarkerHover && onMarkerHover(l.id));
      el.addEventListener("mouseleave", () => onMarkerHover && onMarkerHover(null));

      const marker = new maplibregl.Marker({ element: el, anchor: "bottom" })
        .setLngLat([l.lon, l.lat])
        .addTo(map);
      markersRef.current[l.id] = { marker, el };
    });

    // Fit bounds
    if (listings.length > 0) {
      const bounds = new maplibregl.LngLatBounds();
      listings.forEach((l) => bounds.extend([l.lon, l.lat]));
      map.fitBounds(bounds, {
        padding: { top: 80, bottom: 80, left: 80, right: 80 },
        maxZoom: 14,
        duration: 800,
      });
    } else {
      map.flyTo({ center: [37.62, 55.752], zoom: 10.5, duration: 800 });
    }
  }, [listings, ready]);

  // Sync active/hover state on existing markers
  useEffect(() => {
    Object.entries(markersRef.current).forEach(([id, { el }]) => {
      el.classList.toggle("is-active", id === activeId);
      el.classList.toggle("is-hover", id === hoverId);
    });
  }, [activeId, hoverId, listings]);

  // Stylized SVG fallback
  if (mapStyle === "stylized") {
    return (
      <StylizedMap
        listings={listings}
        activeId={activeId}
        hoverId={hoverId}
        onMarkerClick={onMarkerClick}
        onMarkerHover={onMarkerHover}
      />
    );
  }

  return <div ref={containerRef} className="map-container" />;
}

function formatPriceShort(rub) {
  const mln = rub / 1_000_000;
  return mln.toFixed(mln < 10 ? 1 : 0).replace(".", ",") + " млн";
}

// --- Stylized SVG map (no tiles) -------------------------------------------

function StylizedMap({ listings, activeId, hoverId, onMarkerClick, onMarkerHover }) {
  // Project lon/lat to SVG coords using a fixed Moscow-area window.
  const W = 800, H = 600;
  const lonMin = 37.45, lonMax = 37.78, latMin = 55.65, latMax = 55.83;
  const project = (lon, lat) => ({
    x: ((lon - lonMin) / (lonMax - lonMin)) * W,
    y: H - ((lat - latMin) / (latMax - latMin)) * H,
  });

  return (
    <div className="map-container map-stylized">
      <svg viewBox={`0 0 ${W} ${H}`} preserveAspectRatio="xMidYMid slice" width="100%" height="100%">
        <defs>
          <pattern id="dot-grid" width="24" height="24" patternUnits="userSpaceOnUse">
            <circle cx="2" cy="2" r="0.7" fill="rgba(26,26,26,0.08)" />
          </pattern>
        </defs>
        <rect width={W} height={H} fill="#F2EDE4" />
        <rect width={W} height={H} fill="url(#dot-grid)" />
        {/* Moscow river — abstract curved band */}
        <path
          d="M -20 380 C 120 320, 220 460, 360 380 S 600 280, 820 360 L 820 600 L -20 600 Z"
          fill="rgba(167,196,212,0.45)"
        />
        <path
          d="M -20 380 C 120 320, 220 460, 360 380 S 600 280, 820 360"
          stroke="rgba(120,148,168,0.55)"
          strokeWidth="1.5"
          fill="none"
        />
        {/* Garden Ring (abstract) */}
        <circle cx={400} cy={300} r={110} fill="none" stroke="rgba(26,26,26,0.12)" strokeWidth="1.5" strokeDasharray="3 5" />
        <circle cx={400} cy={300} r={200} fill="none" stroke="rgba(26,26,26,0.08)" strokeWidth="1.5" strokeDasharray="3 5" />
        {/* Park blobs */}
        <ellipse cx={170} cy={180} rx={58} ry={42} fill="rgba(140,168,120,0.35)" />
        <ellipse cx={620} cy={140} rx={70} ry={48} fill="rgba(140,168,120,0.35)" />
        <ellipse cx={460} cy={460} rx={84} ry={52} fill="rgba(140,168,120,0.35)" />
        <text x={170} y={184} textAnchor="middle" fontSize="11" fill="rgba(80,108,72,0.75)" fontWeight="500">Сокольники</text>
        <text x={620} y={144} textAnchor="middle" fontSize="11" fill="rgba(80,108,72,0.75)" fontWeight="500">Лосиный остров</text>
        <text x={460} y={464} textAnchor="middle" fontSize="11" fill="rgba(80,108,72,0.75)" fontWeight="500">Парк Горького</text>
        {/* Center label */}
        <text x={400} y={304} textAnchor="middle" fontSize="13" fill="rgba(26,26,26,0.32)" fontWeight="600" letterSpacing="0.08em">КРЕМЛЬ</text>
      </svg>

      <div className="stylized-markers">
        {listings.map((l) => {
          const { x, y } = project(l.lon, l.lat);
          const isActive = l.id === activeId;
          const isHover = l.id === hoverId;
          return (
            <button
              key={l.id}
              className={`map-marker ${isActive ? "is-active" : ""} ${isHover ? "is-hover" : ""}`}
              style={{ left: `${(x / W) * 100}%`, top: `${(y / H) * 100}%` }}
              onClick={() => onMarkerClick && onMarkerClick(l.id)}
              onMouseEnter={() => onMarkerHover && onMarkerHover(l.id)}
              onMouseLeave={() => onMarkerHover && onMarkerHover(null)}
            >
              <span className="map-marker-pin">
                <span className="map-marker-price">{formatPriceShort(l.price)}</span>
              </span>
              <span className="map-marker-stem"></span>
            </button>
          );
        })}
      </div>
    </div>
  );
}

Object.assign(window, { MapView });
