"use client";

/**
 * PticaMapInner — the rich dark cockpit map (client-only; loaded via
 * dynamic(ssr:false) from PticaMap). Prototype parity (ptica-redesign/app.js):
 *
 *  - Two base layers, toggled by the «Спутник | Схема» segmented control: Esri
 *    World Imagery (default, `.baseSat` → darker --map-filter-sat) and CartoDB
 *    dark vector tiles. The parcel polygon reads clearly over both.
 *  - REAL data layers, reusing the existing analysis-map components so logic is
 *    not duplicated:
 *      · parcel polygon (cyan, geom_geojson)
 *      · POI markers from score_breakdown — bucketed ЖК / Школы·Детсады /
 *        Парки·Метро like the prototype legend (CircleMarker, colored)
 *      · competitors / pipeline (MarketLayers — ЖК + будущие проекты)
 *      · ЗОУИТ охранные зоны (ZouitLayer)
 *      · connection points + colored polylines to the parcel (ConnectionPoints-
 *        Layer + per-category lines from the centroid)
 *      · custom POI (CustomPoiLayer + add/edit/delete via useCustomPois)
 *  - The map-overlay legend rows TOGGLE each layer; the «Точки подключения
 *    ресурсов» list is driven by real connection-points data (nearest distance
 *    per resource category).
 *  - Isochrones: the only real source (useIsochrones) is an on-demand ORS
 *    mutation, not part of /analyze — per the task we DO NOT fake it; the legend
 *    row stays «скоро».
 *  - The «3D-масса застройки» legend row + map tool open the future3d drawer.
 */

import { useEffect, useMemo, useRef, useState } from "react";
import {
  MapContainer,
  TileLayer,
  GeoJSON,
  CircleMarker,
  Polyline,
  Popup,
  Tooltip,
  useMap,
  useMapEvents,
} from "react-leaflet";
import type { Geometry, Position } from "geojson";
import "leaflet/dist/leaflet.css";

import styles from "@/app/site-finder/analysis/[cad]/ptica/ptica.module.css";
import { EKB_CENTER } from "@/components/site-finder/ptica/ptica-adapt";
import type { ParcelAnalysis } from "@/types/site-finder";
import type { ConnectionPointsResponse } from "@/types/nspd";
import type { CustomPoi } from "@/types/customPoi";
import {
  MarketLayers,
  MARKET_COLORS,
} from "@/components/site-finder/MarketLayers";
import {
  ConnectionPointsLayer,
  CP_CATEGORY_STYLES,
  CP_ALL_CATEGORIES,
  classifyStructure,
  groupStructuresByCategory,
  type CpCategory,
} from "@/components/site-finder/ConnectionPointsLayer";
import {
  ZouitLayer,
  ZOUIT_ALL_SEVERITIES,
  groupZouitBySeverity,
  type ZouitSeverity,
} from "@/components/site-finder/ZouitLayer";
import { CustomPoiLayer } from "@/components/site-finder/CustomPoiLayer";
import { CustomPoiAddModal } from "@/components/site-finder/CustomPoiAddModal";
import { CustomPoiEditModal } from "@/components/site-finder/CustomPoiEditModal";
import {
  useAddCustomPoi,
  useUpdateCustomPoi,
  useDeleteCustomPoi,
} from "@/hooks/useCustomPois";
import type { DrawerKey } from "@/components/site-finder/ptica/drawers/drawer-keys";

// ── POI legend buckets (prototype: ЖК / Школы·Детсады / Парки·Метро) ───────────

type PoiBucket = "edu" | "greenmetro";

interface PoiBucketStyle {
  color: string;
  label: string;
  radius: number;
}

// token-hex (map exception per ui-tokens.md) — match prototype poiColor()
const POI_BUCKET_STYLES: Record<PoiBucket, PoiBucketStyle> = {
  edu: { color: "#3fa77d", label: "Школы · Дет.сады", radius: 6 }, // --res-poi
  greenmetro: { color: "#6aa15f", label: "Парки · Метро", radius: 6 },
};

const EDU_CATEGORIES = new Set(["school", "kindergarten"]);
const GREENMETRO_CATEGORIES = new Set([
  "park",
  "metro_stop",
  "tram_stop",
  "bus_stop",
]);

function poiBucket(category: string): PoiBucket | null {
  if (EDU_CATEGORIES.has(category)) return "edu";
  if (GREENMETRO_CATEGORIES.has(category)) return "greenmetro";
  return null;
}

// ── Narrowing: unknown → GeoJSON Geometry ─────────────────────────────────────

const GEOMETRY_TYPES = new Set([
  "Point",
  "MultiPoint",
  "LineString",
  "MultiLineString",
  "Polygon",
  "MultiPolygon",
  "GeometryCollection",
]);

function asGeometry(value: unknown): Geometry | null {
  if (value == null || typeof value !== "object") return null;
  if (!("type" in value)) return null;
  const type = (value as { type: unknown }).type;
  if (typeof type !== "string" || !GEOMETRY_TYPES.has(type)) return null;
  return value as Geometry;
}

// ── Centroid (bounding-box center — sufficient for connection-line origin) ─────

function flattenCoords(geom: Geometry): Position[] {
  switch (geom.type) {
    case "Point":
      return [geom.coordinates];
    case "MultiPoint":
    case "LineString":
      return geom.coordinates;
    case "MultiLineString":
    case "Polygon":
      return geom.coordinates.flat();
    case "MultiPolygon":
      return geom.coordinates.flat(2);
    case "GeometryCollection":
      return geom.geometries.flatMap(flattenCoords);
    default:
      return [];
  }
}

function geomCenter(geom: Geometry): [number, number] {
  const coords = flattenCoords(geom);
  if (!coords.length) return EKB_CENTER;
  let minLat = Infinity;
  let maxLat = -Infinity;
  let minLon = Infinity;
  let maxLon = -Infinity;
  for (const [lon, lat] of coords) {
    if (lat < minLat) minLat = lat;
    if (lat > maxLat) maxLat = lat;
    if (lon < minLon) minLon = lon;
    if (lon > maxLon) maxLon = lon;
  }
  return [(minLat + maxLat) / 2, (minLon + maxLon) / 2];
}

// Pull [lat, lon] out of an EngineeringStructure point geometry (GeoJSON
// [lon, lat]). Non-points / missing coords → null (skip in lines).
function structureLatLon(
  geom: Record<string, unknown>,
): [number, number] | null {
  if (geom.type !== "Point") return null;
  const coords = geom.coordinates as number[] | undefined;
  if (!coords || coords.length < 2) return null;
  return [coords[1], coords[0]];
}

function formatMeters(m: number): string {
  if (m >= 1000) return `${(m / 1000).toFixed(2)} км`;
  return `${Math.round(m)} м`;
}

// ── Layer keys ────────────────────────────────────────────────────────────────

type LayerKey =
  | "parcel"
  | "competitors" // ЖК
  | "pipeline" // будущие проекты
  | "edu"
  | "greenmetro"
  | "connections"
  | "zouit"
  | "custompoi";

// ── Map controllers (must live inside MapContainer) ───────────────────────────

function FitToGeometry({ geom }: { geom: Geometry | null }) {
  const map = useMap();
  useEffect(() => {
    if (!geom) return;
    const coords = flattenCoords(geom);
    if (coords.length < 2) return;
    let minLat = Infinity;
    let maxLat = -Infinity;
    let minLon = Infinity;
    let maxLon = -Infinity;
    for (const [lon, lat] of coords) {
      if (lat < minLat) minLat = lat;
      if (lat > maxLat) maxLat = lat;
      if (lon < minLon) minLon = lon;
      if (lon > maxLon) maxLon = lon;
    }
    map.fitBounds(
      [
        [minLat, minLon],
        [maxLat, maxLon],
      ],
      { padding: [48, 48], maxZoom: 16, animate: false },
    );
    map.setZoom(Math.max(map.getZoom() - 1, 13), { animate: false });
  }, [map, geom]);
  return null;
}

function MapClickHandler({
  editMode,
  onMapClick,
}: {
  editMode: boolean;
  onMapClick: (lat: number, lon: number) => void;
}) {
  useMapEvents({
    click(e) {
      if (editMode) onMapClick(e.latlng.lat, e.latlng.lng);
    },
  });
  return null;
}

// ── Props ─────────────────────────────────────────────────────────────────────

interface Props {
  analysis: ParcelAnalysis;
  cad: string;
  connectionPoints?: ConnectionPointsResponse;
  customPois?: CustomPoi[];
  onOpenDrawer?: (key: DrawerKey) => void;
}

export default function PticaMapInner({
  analysis,
  cad,
  connectionPoints,
  customPois,
  onOpenDrawer,
}: Props) {
  // Fix Leaflet default icon paths broken by webpack bundler (mirror SiteMap).
  useEffect(() => {
    void import("leaflet").then((L) => {
      // @ts-expect-error — _getIconUrl is internal Leaflet property
      delete L.Icon.Default.prototype._getIconUrl;
      L.Icon.Default.mergeOptions({
        iconRetinaUrl:
          "https://unpkg.com/leaflet@1.9.4/dist/images/marker-icon-2x.png",
        iconUrl: "https://unpkg.com/leaflet@1.9.4/dist/images/marker-icon.png",
        shadowUrl:
          "https://unpkg.com/leaflet@1.9.4/dist/images/marker-shadow.png",
      });
    });
  }, []);

  const geom = useMemo(
    () => asGeometry(analysis.geom_geojson),
    [analysis.geom_geojson],
  );
  const center = geom ? geomCenter(geom) : EKB_CENTER;

  // ── Base layer (satellite default — matches prototype + header) ──────────────
  const [base, setBase] = useState<"sat" | "vec">("sat");

  // ── Layer visibility (parcel always on; isochrones is «скоро», not wired) ────
  const [visible, setVisible] = useState<Set<LayerKey>>(
    () =>
      new Set<LayerKey>([
        "parcel",
        "competitors",
        "pipeline",
        "edu",
        "greenmetro",
        "connections",
        "zouit",
        "custompoi",
      ]),
  );
  function toggleLayer(key: LayerKey) {
    setVisible((prev) => {
      const next = new Set(prev);
      if (next.has(key)) next.delete(key);
      else next.add(key);
      return next;
    });
  }

  // ── Custom POI add/edit state + mutations ────────────────────────────────────
  const [addMode, setAddMode] = useState(false);
  const [pendingCoords, setPendingCoords] = useState<{
    lat: number;
    lon: number;
  } | null>(null);
  const [editingPoi, setEditingPoi] = useState<CustomPoi | null>(null);

  const addMutation = useAddCustomPoi(cad);
  const updateMutation = useUpdateCustomPoi(cad);
  const deleteMutation = useDeleteCustomPoi(cad);

  // ESC cancels add mode
  const addModeRef = useRef(addMode);
  addModeRef.current = addMode;
  useEffect(() => {
    function onKeyDown(e: KeyboardEvent) {
      if (e.key === "Escape" && addModeRef.current) {
        setAddMode(false);
        setPendingCoords(null);
      }
    }
    window.addEventListener("keydown", onKeyDown);
    return () => window.removeEventListener("keydown", onKeyDown);
  }, []);

  function handleMapClick(lat: number, lon: number) {
    setPendingCoords({ lat, lon });
    setAddMode(false);
  }

  // ── POI markers from score_breakdown, bucketed ───────────────────────────────
  const poiByBucket = useMemo(() => {
    const buckets: Record<
      PoiBucket,
      { lat: number; lon: number; name: string | null; distance_m: number }[]
    > = {
      edu: [],
      greenmetro: [],
    };
    for (const [cat, pois] of Object.entries(analysis.score_breakdown)) {
      const bucket = poiBucket(cat);
      if (!bucket) continue;
      for (const p of pois) {
        if (p.lat === 0 && p.lon === 0) continue;
        buckets[bucket].push({
          lat: p.lat,
          lon: p.lon,
          name: p.name,
          distance_m: p.distance_m,
        });
      }
    }
    return buckets;
  }, [analysis.score_breakdown]);

  // ── Market data (competitors = ЖК, pipeline = будущие проекты) ───────────────
  const competitorList = analysis.competitors ?? [];
  const pipelineList = analysis.pipeline_24mo?.top_objects ?? [];
  const competitorCount = competitorList.filter(
    (c) => typeof c.lat === "number" && typeof c.lon === "number",
  ).length;
  const pipelineCount = pipelineList.filter(
    (p) => typeof p.lat === "number" && typeof p.lon === "number",
  ).length;

  // ── Connection points (grouped by resource category) ─────────────────────────
  const cpGrouped = useMemo(
    () =>
      connectionPoints
        ? groupStructuresByCategory(connectionPoints.engineering_structures)
        : new Map<CpCategory, never[]>(),
    [connectionPoints],
  );
  const cpCount = connectionPoints?.engineering_structures.length ?? 0;

  // Nearest distance per category — drives the «Точки подключения» list.
  const cpNearest = useMemo(() => {
    const nearest = new Map<CpCategory, number>();
    if (!connectionPoints) return nearest;
    for (const s of connectionPoints.engineering_structures) {
      const cat = classifyStructure(s);
      const cur = nearest.get(cat);
      if (cur === undefined || s.distance_to_boundary_m < cur) {
        nearest.set(cat, s.distance_to_boundary_m);
      }
    }
    return nearest;
  }, [connectionPoints]);

  // Connection polylines from the parcel centroid to each structure point.
  const connectionLines = useMemo(() => {
    if (!connectionPoints || !geom) return [];
    const origin = geomCenter(geom);
    const lines: {
      from: [number, number];
      to: [number, number];
      color: string;
    }[] = [];
    for (const s of connectionPoints.engineering_structures) {
      const latLon = structureLatLon(s.geometry_geojson);
      if (!latLon) continue;
      const cat = classifyStructure(s);
      lines.push({
        from: origin,
        to: latLon,
        color: CP_CATEGORY_STYLES[cat].color,
      });
    }
    return lines;
  }, [connectionPoints, geom]);

  // ── ЗОУИТ overlaps grouped by severity ───────────────────────────────────────
  const zouitGrouped = useMemo(
    () => groupZouitBySeverity(analysis.nspd_zouit_overlaps ?? []),
    [analysis.nspd_zouit_overlaps],
  );
  const zouitCount = ZOUIT_ALL_SEVERITIES.reduce(
    (sum, sev) => sum + (zouitGrouped.get(sev)?.length ?? 0),
    0,
  );
  const allZouitVisible: Set<ZouitSeverity> = useMemo(
    () => new Set(ZOUIT_ALL_SEVERITIES),
    [],
  );

  const customPoiList = customPois ?? [];

  return (
    <div
      className={`${styles.mapMount} ${base === "sat" ? styles.baseSat : ""}`}
    >
      <MapContainer
        center={center}
        zoom={geom ? 15 : 11}
        zoomControl={false}
        scrollWheelZoom
        style={{ cursor: addMode ? "crosshair" : "grab" }}
      >
        <FitToGeometry geom={geom} />
        <MapClickHandler editMode={addMode} onMapClick={handleMapClick} />

        {/* Base layers — only one mounted at a time (key forces tile swap). */}
        {base === "sat" ? (
          <TileLayer
            key="sat"
            attribution="&copy; Esri · Maxar"
            url="https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}"
            maxZoom={19}
          />
        ) : (
          <TileLayer
            key="vec"
            attribution='&copy; <a href="https://carto.com/attributions">CARTO</a> · &copy; <a href="https://www.openstreetmap.org/copyright">OSM</a>'
            url="https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png"
            maxZoom={19}
          />
        )}

        {/* ЗОУИТ охранные зоны — background fill (under markers). */}
        {visible.has("zouit") && zouitCount > 0 && (
          <ZouitLayer
            grouped={zouitGrouped}
            visibleSeverities={allZouitVisible}
          />
        )}

        {/* Competitors (ЖК) + pipeline (будущие проекты). */}
        {(visible.has("competitors") || visible.has("pipeline")) && (
          <MarketLayers
            competitors={competitorList}
            pipelineObjects={pipelineList}
            riskZones={[]}
            opportunityParcels={[]}
            redLines={[]}
            showCompetitors={visible.has("competitors")}
            showPipeline={visible.has("pipeline")}
            showRiskZones={false}
            showOpportunity={false}
            showRedLines={false}
          />
        )}

        {/* POI markers (Школы·Детсады / Парки·Метро). */}
        {(["edu", "greenmetro"] as PoiBucket[]).flatMap((bucket) => {
          if (!visible.has(bucket)) return [];
          const style = POI_BUCKET_STYLES[bucket];
          return poiByBucket[bucket].map((poi, idx) => (
            <CircleMarker
              key={`${bucket}-${idx}`}
              center={[poi.lat, poi.lon]}
              radius={style.radius}
              pathOptions={{
                color: style.color,
                fillColor: style.color,
                fillOpacity: 0.85,
                weight: 1.5,
              }}
            >
              <Tooltip direction="top">
                {poi.name ?? style.label} · {formatMeters(poi.distance_m)}
              </Tooltip>
            </CircleMarker>
          ));
        })}

        {/* Connection points + polylines to the parcel centroid. */}
        {visible.has("connections") && connectionPoints && (
          <>
            {connectionLines.map((line, idx) => (
              <Polyline
                key={`cp-line-${idx}`}
                positions={[line.from, line.to]}
                pathOptions={{
                  color: line.color,
                  weight: 2.2,
                  opacity: 0.85,
                  dashArray: "4 6",
                }}
              />
            ))}
            <ConnectionPointsLayer
              grouped={cpGrouped}
              visibleCategories={new Set(CP_ALL_CATEGORIES)}
            />
          </>
        )}

        {/* Parcel polygon — cyan, on top of fills so it always reads. */}
        {visible.has("parcel") && geom && (
          <GeoJSON
            key={analysis.cad_num}
            data={geom}
            style={{
              // = --accent-cyan-strong (Leaflet styles can't read CSS vars)
              color: "#8ed3ff",
              weight: 2.5,
              fillColor: "#8ed3ff",
              fillOpacity: 0.15,
            }}
          />
        )}

        {/* Custom POI — topmost; add/edit/delete wired to useCustomPois. */}
        {visible.has("custompoi") && customPoiList.length > 0 && (
          <CustomPoiLayer
            pois={customPoiList}
            onEdit={(poi) => setEditingPoi(poi)}
            onDelete={(id) => deleteMutation.mutate(id)}
          />
        )}
      </MapContainer>

      {/* ── Legend / layer-toggle overlay ────────────────────────────────────── */}
      <div className={styles.mapOverlay}>
        <h4>
          <span className={styles.live} />
          {base === "sat" ? "Спутник · свежий снимок" : "Схема · тёмная карта"}
        </h4>

        <div className={styles.baseToggle}>
          <button
            type="button"
            className={base === "sat" ? styles.baseToggleActive : ""}
            onClick={() => setBase("sat")}
          >
            Спутник
          </button>
          <button
            type="button"
            className={base === "vec" ? styles.baseToggleActive : ""}
            onClick={() => setBase("vec")}
          >
            Схема
          </button>
        </div>

        <div className={styles.layerList}>
          <LegendRow
            color="#8ed3ff"
            label="Участок"
            count={geom ? 1 : 0}
            on={visible.has("parcel")}
            onToggle={() => toggleLayer("parcel")}
          />
          <LegendRow
            color={MARKET_COLORS.competitor}
            label="ЖК"
            count={competitorCount}
            on={visible.has("competitors")}
            onToggle={() => toggleLayer("competitors")}
          />
          <LegendRow
            color={MARKET_COLORS.pipeline}
            label="Будущие проекты"
            count={pipelineCount}
            on={visible.has("pipeline")}
            onToggle={() => toggleLayer("pipeline")}
          />
          <LegendRow
            color={POI_BUCKET_STYLES.edu.color}
            label="Школы · Дет.сады"
            count={poiByBucket.edu.length}
            on={visible.has("edu")}
            onToggle={() => toggleLayer("edu")}
          />
          <LegendRow
            color={POI_BUCKET_STYLES.greenmetro.color}
            label="Парки · Метро"
            count={poiByBucket.greenmetro.length}
            on={visible.has("greenmetro")}
            onToggle={() => toggleLayer("greenmetro")}
          />
          {zouitCount > 0 && (
            <LegendRow
              color="#d2655b"
              label="ЗОУИТ"
              count={zouitCount}
              on={visible.has("zouit")}
              onToggle={() => toggleLayer("zouit")}
            />
          )}
          <LegendRow
            color="#7fd0ee"
            label="Точки подключения"
            count={cpCount}
            on={visible.has("connections")}
            onToggle={() => toggleLayer("connections")}
          />
          {/* Изохроны — реальный источник (ORS) пока вне /analyze: «скоро». */}
          <div className={`${styles.layerRow} ${styles.layerRowSoon}`}>
            <span className={styles.swatch} />
            <span>Изохроны доступности</span>
            <span className={styles.cnt}>скоро</span>
          </div>
          <LegendRow
            color="#e0a93b"
            label="Кастомные POI"
            count={customPoiList.length}
            on={visible.has("custompoi")}
            onToggle={() => toggleLayer("custompoi")}
          />
          {onOpenDrawer && (
            <button
              type="button"
              className={`${styles.layerRow} ${styles.layerRow3d}`}
              onClick={() => onOpenDrawer("future3d")}
              title="Открыть 3D-массу застройки"
            >
              <span className={`${styles.swatch} ${styles.swatch3d}`} />
              <span>3D-масса застройки</span>
              <span className={styles.openTag}>3D</span>
            </button>
          )}
        </div>

        {cpCount > 0 && (
          <>
            <hr className={styles.overlayDivider} />
            <div className={styles.overlaySub}>Точки подключения ресурсов</div>
            {CP_ALL_CATEGORIES.filter((c) => cpNearest.has(c)).map((catKey) => {
              const dist = cpNearest.get(catKey);
              if (dist === undefined) return null;
              const style = CP_CATEGORY_STYLES[catKey];
              return (
                <div key={catKey} className={styles.resRow}>
                  <span
                    className={styles.dot}
                    style={{ background: style.color }}
                  />
                  <span>{style.label}</span>
                  <b>{formatMeters(dist)}</b>
                </div>
              );
            })}
          </>
        )}
      </div>

      {/* ── Map tools (add-POI · 3D) ─────────────────────────────────────────── */}
      <div className={styles.mapTools}>
        <button
          type="button"
          className={`${styles.tool} ${addMode ? styles.toolActive : ""}`}
          title={addMode ? "Кликните на карте" : "Добавить POI"}
          aria-label="Добавить пользовательскую точку"
          onClick={() => {
            setAddMode((v) => !v);
            setPendingCoords(null);
          }}
        >
          <svg viewBox="0 0 24 24" fill="none">
            <path
              d="M12 21s7-6.2 7-11a7 7 0 10-14 0c0 4.8 7 11 7 11z"
              stroke="currentColor"
              strokeWidth="1.6"
              strokeLinejoin="round"
            />
            <path
              d="M12 7v6M9 10h6"
              stroke="currentColor"
              strokeWidth="1.6"
              strokeLinecap="round"
            />
          </svg>
        </button>
        {onOpenDrawer && (
          <button
            type="button"
            className={styles.tool}
            title="3D-масса застройки"
            aria-label="Открыть 3D-массу застройки"
            onClick={() => onOpenDrawer("future3d")}
          >
            <svg viewBox="0 0 24 24" fill="none">
              <path
                d="M12 3l8 4.5v9L12 21l-8-4.5v-9L12 3z"
                stroke="currentColor"
                strokeWidth="1.4"
                strokeLinejoin="round"
              />
            </svg>
          </button>
        )}
      </div>

      {addMode && (
        <div className={styles.mapHint}>Кликните на карте для точки</div>
      )}

      {/* Add / edit modals (reuse the analysis-map custom-POI flow). */}
      {pendingCoords && (
        <CustomPoiAddModal
          lat={pendingCoords.lat}
          lon={pendingCoords.lon}
          parcelCad={cad}
          isLoading={addMutation.isPending}
          onSubmit={(payload) => {
            addMutation.mutate(payload, {
              onSuccess: () => setPendingCoords(null),
            });
          }}
          onCancel={() => setPendingCoords(null)}
        />
      )}
      {editingPoi && (
        <CustomPoiEditModal
          poi={editingPoi}
          isLoading={updateMutation.isPending}
          onSubmit={(updateData) => {
            updateMutation.mutate(
              { id: editingPoi.id, data: updateData },
              { onSuccess: () => setEditingPoi(null) },
            );
          }}
          onCancel={() => setEditingPoi(null)}
        />
      )}
    </div>
  );
}

// ── Legend row (toggle button) ─────────────────────────────────────────────────

function LegendRow({
  color,
  label,
  count,
  on,
  onToggle,
}: {
  color: string;
  label: string;
  count: number;
  on: boolean;
  onToggle: () => void;
}) {
  return (
    <button
      type="button"
      className={`${styles.layerRow} ${on ? "" : styles.layerRowOff}`}
      onClick={onToggle}
      aria-pressed={on}
    >
      <span className={styles.swatch} style={{ background: color }} />
      <span>{label}</span>
      <span className={styles.cnt}>{count}</span>
    </button>
  );
}
