/* ============================================================
   SKYVIDYA — MAPA DO ATIVO (gleba) · evidência que se enxerga
   MapLibre (satélite/escuro/claro) + deck.gl. Lentes idênticas
   ao mapa macro, timeline 5s (timelapse + eventos + A/B),
   carimbo de fonte por camada, toolbar (medir/anotar/vistoria/
   exportar), inset regional + Pescaria, badge de protocolo,
   estados de exceção. Gramática fractal 01·02·03·04.
   ============================================================ */
const { useState, useEffect, useRef, useCallback, useMemo } = React;

const PARCEL_BASEMAPS = {
  sat:   { label: "Satélite", tiles: ["https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}"], attr: "© Esri · Maxar" },
  dark:  { label: "Escuro",   tiles: ["https://a.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png", "https://b.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png"], attr: "© OSM © CARTO" },
  light: { label: "Claro",    tiles: ["https://a.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png", "https://b.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png"], attr: "© OSM © CARTO" },
};

function parcelStyle(active) {
  const srcs = {}, lyrs = [{ id: "bg", type: "background", paint: { "background-color": "#06070A" } }];
  Object.entries(PARCEL_BASEMAPS).forEach(([k, b]) => {
    srcs[k] = { type: "raster", tiles: b.tiles, tileSize: 256, attribution: b.attr };
    lyrs.push({ id: "r-" + k, type: "raster", source: k, layout: { visibility: k === active ? "visible" : "none" } });
  });
  return { version: 8, sources: srcs, layers: lyrs };
}
function ringBounds(ring) {
  let minX = 180, minY = 90, maxX = -180, maxY = -90;
  ring.forEach(([x, y]) => { minX = Math.min(minX, x); minY = Math.min(minY, y); maxX = Math.max(maxX, x); maxY = Math.max(maxY, y); });
  return [[minX, minY], [maxX, maxY]];
}
const YEARS = [2014,2015,2016,2017,2018,2019,2020,2021,2022,2023];
const EVENT_META = {
  sinistro: { color: "var(--risk-critical)", icon: "alert", label: "Sinistro" },
  enso:     { color: "var(--sv-cyan)",       icon: "drop",  label: "ENSO" },
  desmate:  { color: "var(--sv-coral)",      icon: "scan",  label: "Desmate" },
  decreto:  { color: "var(--sv-warn)",       icon: "file",  label: "Decreto" },
};

/* ---------------- MAP ---------------- */
function ParcelMap({ p, parcel, lens, layers, basemap, onBasemap, year, compare, compareYear, tool, annotations, onAddAnnotation, onPickCell, selectedCell }) {
  const elRef = useRef(null), mapRef = useRef(null), ovRef = useRef(null);
  const [ready, setReady] = useState(false);
  const stateRef = useRef({});
  stateRef.current = { tool, onAddAnnotation, onPickCell, parcel, lens };
  const pc = parcel;

  const buildLayers = useCallback(() => {
    if (!window.deck || !pc) return [];
    const L = [];
    const riskRGB = SKY.levelColor(SKY.levelOf(p.score)).slice(0, 3);
    const dividerLng = pc.center[0];

    // talhão cells colored by active lens
    if (layers.cells && pc.cells.length) {
      L.push(new deck.PolygonLayer({
        id: "cells", data: pc.cells, getPolygon: d => d.pts, filled: true, stroked: true,
        getFillColor: d => {
          if (compare) return SKY.parcelCellColor(d, lens, pc, d.lng < dividerLng ? year : compareYear);
          return SKY.parcelCellColor(d, lens, pc, lens === "ndvi" ? year : null);
        },
        getLineColor: [6, 7, 10, 90], lineWidthMinPixels: 0.5, pickable: true,
        onClick: info => { if (info.object && stateRef.current.onPickCell) stateRef.current.onPickCell(info.object); },
        updateTriggers: { getFillColor: [lens, year, compareYear, compare] },
      }));
    }
    // ESG compliance overlays
    if (lens === "esg") {
      if (pc.appRing) {
        L.push(new deck.PolygonLayer({ id: "app", data: [{ r: pc.appRing }], getPolygon: d => d.r, filled: true, stroked: true,
          getFillColor: [31, 138, 80, 70], getLineColor: [78, 220, 130, 230], lineWidthUnits: "pixels", getLineWidth: 1.5, lineWidthMinPixels: 1.4 }));
      }
      if (pc.desmateRing && layers.desmate) {
        L.push(new deck.PolygonLayer({ id: "desmate", data: [{ r: pc.desmateRing }], getPolygon: d => d.r, filled: true, stroked: true,
          getFillColor: [255, 92, 46, 90], getLineColor: [255, 92, 46, 255], lineWidthUnits: "pixels", getLineWidth: 2.2, lineWidthMinPixels: 2 }));
      }
    }
    // hidrografia
    if (layers.hidro && pc.hydro) {
      L.push(new deck.PathLayer({ id: "hydro", data: [{ path: pc.hydro }], getPath: d => d.path,
        getColor: [78, 210, 210, 230], widthUnits: "pixels", getWidth: 3, capRounded: true, jointRounded: true }));
    }
    // limite CAR
    if (layers.limite) {
      L.push(new deck.PolygonLayer({ id: "limite", data: [{ ring: pc.ringLngLat }], getPolygon: d => d.ring, filled: false, stroked: true,
        getLineColor: [riskRGB[0], riskRGB[1], riskRGB[2], 255], lineWidthUnits: "pixels", getLineWidth: 2.6, lineWidthMinPixels: 2 }));
      L.push(new deck.PolygonLayer({ id: "limite2", data: [{ ring: pc.ringLngLat }], getPolygon: d => d.ring, filled: true, stroked: false,
        getFillColor: [riskRGB[0], riskRGB[1], riskRGB[2], 22] }));
    }
    // embargo (anomalia) — hachura vermelha sobre toda a gleba
    if (lens === "esg" && pc.embargo) {
      L.push(new deck.PolygonLayer({ id: "embargo", data: [{ ring: pc.ringLngLat }], getPolygon: d => d.ring, filled: true, stroked: true,
        getFillColor: [230, 40, 30, 45], getLineColor: [230, 40, 30, 255], lineWidthUnits: "pixels", getLineWidth: 3, lineWidthMinPixels: 2.4 }));
    }
    // glebas reais — centroides por célula H3-L7 (IRB_GLEBAS_BY_H3)
    if (layers.sinistros && pc.realGlebas && pc.realGlebas.length) {
      L.push(new deck.ScatterplotLayer({ id: "glebas-all", data: pc.realGlebas, getPosition: d => [d[0], d[1]],
        getRadius: d => Math.min(80, Math.max(30, d[2] * 0.8)), radiusUnits: "meters", radiusMinPixels: 3, radiusMaxPixels: 10,
        // verde = sem sinistro, coral = com sinistro
        getFillColor: d => d[3] === 1 ? [255, 92, 46, 220] : [78, 210, 210, 180],
        stroked: true, getLineColor: [6, 7, 10, 200], lineWidthMinPixels: 1, pickable: true,
        updateTriggers: {} }));
    }
    // selected cell highlight
    if (selectedCell) {
      L.push(new deck.PolygonLayer({ id: "selcell", data: [selectedCell], getPolygon: d => d.pts, filled: false, stroked: true,
        getLineColor: [246, 244, 238, 255], lineWidthUnits: "pixels", getLineWidth: 2.4, lineWidthMinPixels: 2 }));
    }
    // annotations + vistoria pins
    if (annotations && annotations.length) {
      L.push(new deck.ScatterplotLayer({ id: "annot", data: annotations, getPosition: d => [d.lng, d.lat],
        getRadius: 7, radiusUnits: "pixels", radiusMinPixels: 7,
        getFillColor: d => d.kind === "vistoria" ? [78, 210, 210, 255] : [246, 244, 238, 255],
        stroked: true, getLineColor: [6, 7, 10, 255], lineWidthMinPixels: 2,
        updateTriggers: { getFillColor: [annotations.length] } }));
    }
    return L;
  }, [layers, p.id, p.score, lens, year, compare, compareYear, selectedCell, annotations]);

  useEffect(() => {
    if (!window.maplibregl || !window.deck || !pc) return;
    const map = new maplibregl.Map({
      container: elRef.current, style: parcelStyle(basemap),
      bounds: ringBounds(pc.ringLngLat), fitBoundsOptions: { padding: 50 },
      attributionControl: false, dragRotate: false,
    });
    mapRef.current = map;
    map.addControl(new maplibregl.AttributionControl({ compact: true }), "bottom-right");
    map.on("load", () => {
      const ov = new deck.MapboxOverlay({ interleaved: false, layers: buildLayers() });
      ovRef.current = ov; map.addControl(ov);
      try { map.fitBounds(ringBounds(pc.ringLngLat), { padding: 50, duration: 0 }); } catch (e) {}
      setReady(true);
    });
    // measure / annotate clicks
    map.on("click", (e) => {
      const st = stateRef.current;
      if (st.tool === "anotar") st.onAddAnnotation({ lng: e.lngLat.lng, lat: e.lngLat.lat, kind: "nota" });
      else if (st.tool === "vistoria") st.onAddAnnotation({ lng: e.lngLat.lng, lat: e.lngLat.lat, kind: "vistoria" });
    });
    return () => { try { map.remove(); } catch (e) {} };
  }, []);

  useEffect(() => { if (ovRef.current) ovRef.current.setProps({ layers: buildLayers() }); }, [buildLayers, ready]);
  useEffect(() => {
    const m = mapRef.current; if (!m || !ready) return;
    Object.keys(PARCEL_BASEMAPS).forEach(k => { if (m.getLayer("r-" + k)) m.setLayoutProperty("r-" + k, "visibility", k === basemap ? "visible" : "none"); });
  }, [basemap, ready]);
  useEffect(() => {
    const m = mapRef.current; if (!m) return;
    m.getCanvas().style.cursor = (tool === "anotar" || tool === "vistoria") ? "crosshair" : "";
  }, [tool, ready]);

  return (
    <div className={"parcel-canvas-wrap" + (tool ? " tool-" + tool : "")}>
      <div className="parcel-canvas" ref={elRef} />
      {!ready && <div className="parcel-loading"><span className="led-spin" /><span className="mono">triangulando fontes · sentinel-2</span></div>}
      {compare && <div className="pm-curtain"><span className="pm-curtain-a mono">{year}</span><span className="pm-curtain-b mono">{compareYear}</span></div>}
      {/* chrome — sempre visível (rigor cartográfico) */}
      <div className="pm-proj mono">EPSG:4674 · SIRGAS 2000 · H3 L10</div>
      {pc && <div className="pm-coord"><span className="pm-pip" /><span className="mono">{pc.center[1].toFixed(4)} · {pc.center[0].toFixed(4)}</span></div>}
      <div className="pm-scale"><div className="pm-scale-bar"><i /><i className="alt" /></div><span className="mono">~500 m</span></div>
      <div className="pm-basemap">
        <span className="mono pm-bm-lab">BASE</span>
        {Object.entries(PARCEL_BASEMAPS).map(([k, b]) => (
          <button key={k} className={"pm-bm-btn" + (basemap === k ? " on" : "")} onClick={() => onBasemap(k)}>{b.label}</button>
        ))}
      </div>
    </div>
  );
}

/* ---------------- lens bar ---------------- */
function LensBar({ lens, onLens }) {
  return (
    <div className="pm-lensbar">
      <span className="mono pm-lens-lab">LENTE</span>
      {SKY.PARCEL_LENSES.map(L => (
        <button key={L.id} className={"pm-lens" + (lens === L.id ? " on" : "")} onClick={() => onLens(L.id)}>{L.label}</button>
      ))}
    </div>
  );
}

/* ---------------- timeline scrubber ---------------- */
function Timeline({ parcel, year, setYear, compare, setCompare, compareYear, setCompareYear }) {
  const [playing, setPlaying] = useState(false);
  const timer = useRef(null);
  const series = parcel.ndviSeries;
  const W = 100; // percentages
  useEffect(() => {
    if (!playing) { clearInterval(timer.current); return; }
    timer.current = setInterval(() => {
      setYear(y => { const i = YEARS.indexOf(y); return i >= YEARS.length - 1 ? (setPlaying(false), YEARS[YEARS.length - 1]) : YEARS[i + 1]; });
    }, 750);
    return () => clearInterval(timer.current);
  }, [playing]);
  const yi = YEARS.indexOf(year);
  const cyi = YEARS.indexOf(compareYear);
  const minV = 0.16, maxV = 0.9;
  const sparkPts = series.map((s, i) => `${(i / (series.length - 1)) * W},${(1 - (s.ndvi - minV) / (maxV - minV)) * 34 + 3}`).join(" ");

  return (
    <div className="pm-timeline">
      <button className="pm-play" onClick={() => setPlaying(p => !p)} title={playing ? "pausar" : "timelapse"}>
        <Icon name={playing ? "x" : "arrowR"} size={13} />
      </button>
      <div className="pm-tl-track">
        <svg className="pm-spark" viewBox={`0 0 ${W} 40`} preserveAspectRatio="none">
          <polyline points={sparkPts} fill="none" stroke="var(--sv-cyan)" strokeWidth="0.8" vectorEffect="non-scaling-stroke" opacity="0.7" />
          <line x1={(yi / (YEARS.length - 1)) * W} x2={(yi / (YEARS.length - 1)) * W} y1="0" y2="40" stroke="var(--sv-coral)" strokeWidth="0.6" vectorEffect="non-scaling-stroke" />
          {compare && <line x1={(cyi / (YEARS.length - 1)) * W} x2={(cyi / (YEARS.length - 1)) * W} y1="0" y2="40" stroke="var(--fg)" strokeWidth="0.6" strokeDasharray="2 2" vectorEffect="non-scaling-stroke" />}
        </svg>
        {/* event markers */}
        <div className="pm-events">
          {parcel.events.map((e, i) => {
            const m = EVENT_META[e.type]; const x = (YEARS.indexOf(e.year) / (YEARS.length - 1)) * 100;
            return <button key={i} className="pm-ev" style={{ left: x + "%", color: m.color }} title={`${e.year} · ${e.label}`}
              onClick={() => setYear(e.year)}><span className="pm-ev-dot" style={{ background: m.color }} /></button>;
          })}
        </div>
        <input type="range" className="pm-tl-range" min="0" max={YEARS.length - 1} value={yi} onChange={(e) => setYear(YEARS[+e.target.value])} />
        <div className="pm-years mono">{YEARS.map(y => <span key={y} className={y === year ? "on" : ""}>{`'${String(y).slice(2)}`}</span>)}</div>
      </div>
      <div className="pm-tl-right">
        <span className="mono pm-ndvi-now">NDVI {(series[yi] || {}).ndvi} · {year}</span>
        <button className={"pm-cmp" + (compare ? " on" : "")} onClick={() => setCompare(c => !c)}>
          <Icon name="layers" size={11} /> A/B
        </button>
        {compare && (
          <select className="pm-cmp-sel mono" value={compareYear} onChange={(e) => setCompareYear(+e.target.value)}>
            {YEARS.map(y => <option key={y} value={y}>vs {y}</option>)}
          </select>
        )}
      </div>
    </div>
  );
}

/* ---------------- layers panel (com carimbo de fonte) ---------------- */
function LayerPanel({ lens, layers, setLayers, sources, p }) {
  const defs = [
    { id: "cells", label: lens === "ndvi" ? "Talhões · NDVI" : lens === "uso" ? "Uso do solo" : "Células · " + (SKY.PARCEL_LENSES.find(l => l.id === lens) || {}).label, src: "ndvi" },
    { id: "limite", label: "Limite da gleba (CAR)", src: "limite" },
    { id: "hidro", label: "Hidrografia", src: "hidro" },
    { id: "sinistros", label: "Sinistros (pontos)", src: "sinistros", note: p.sinistros5s + "×" },
  ];
  if (lens === "esg") defs.splice(3, 0, { id: "desmate", label: "APP/RL · alerta desmate", src: "desmate" });
  return (
    <div className="pi-layers geo-panel">
      <div className="mp-head"><Icon name="layers" size={13} color="var(--sv-cyan)" /><span>Camadas da gleba</span></div>
      <div className="layer-list">
        {defs.map(l => {
          const s = sources[l.src];
          return (
            <div key={l.id} className={"pm-lr tip-wrap" + (layers[l.id] !== false ? " on" : "")}>
              <button className={"ltg" + (layers[l.id] !== false ? " on" : "")} role="switch" aria-checked={layers[l.id] !== false}
                onClick={() => setLayers(st => ({ ...st, [l.id]: !(st[l.id] !== false) }))}><span className="ptg-sw" /></button>
              <span className="pm-ll">{l.label}{l.note && <em> · {l.note}</em>}</span>
              {s && <span className="layer-src"><Icon name="info" size={11} /><span className="tip layer-tip">{s.label}<br /><b className="mono">{s.fonte} · {s.org}</b><br /><span className="mono">cena {s.scene} · ingest {s.ingest}</span></span></span>}
            </div>
          );
        })}
      </div>
      <LegendFor lens={lens} />
    </div>
  );
}
function LegendFor({ lens }) {
  if (lens === "ndvi") return (<div className="pm-legend"><span className="eyebrow">NDVI · vigor vegetativo</span><div className="pm-ramp" /><div className="pm-ramp-lab mono"><span>0.2</span><span>0.9</span></div></div>);
  if (lens === "uso") return (<div className="pm-legend"><span className="eyebrow">Uso do solo</span><div className="pm-cats">{SKY.USO_CLASSES.map(u => <span key={u.id} className="pm-cat"><i style={{ background: `rgb(${u.rgb.join(",")})` }} />{u.label}</span>)}</div></div>);
  if (lens === "esg") return (<div className="pm-legend"><span className="eyebrow">Risco ESG · overlays</span><div className="pm-cats"><span className="pm-cat"><i style={{ background: "rgb(31,138,80)" }} />APP / Reserva Legal</span><span className="pm-cat"><i style={{ background: "rgb(255,92,46)" }} />Alerta PRODES/DETER</span><span className="pm-cat"><i style={{ background: "rgb(230,40,30)" }} />Embargo IBAMA</span></div></div>);
  const scale = [["critical", "Crítico"], ["high", "Alto"], ["medium", "Médio"], ["low", "Baixo"]];
  return (<div className="pm-legend"><span className="eyebrow">{lens === "sinist" ? "Sinistralidade" : "Score agroclimático"}</span><div className="pm-cats">{scale.map(([lv, nm]) => <span key={lv} className="pm-cat"><i style={{ background: `rgb(${SKY.levelColor(lv).slice(0, 3).join(",")})` }} />{nm}</span>)}</div></div>);
}

/* ---------------- region inset ---------------- */
function RegionInset({ p, parcel }) {
  const inset = useMemo(() => SKY.regionInset(p), [p.id]);
  return (
    <div className="region-inset">
      <svg viewBox="0 0 158 100" width="100%" style={{ display: "block" }}>
        {inset.cells.map((c, i) => (
          <polygon key={i} points={c.pts} fill={`rgb(${SKY.levelColor(SKY.levelOf(c.score)).slice(0, 3).join(",")})`} fillOpacity="0.5" stroke="var(--bg-void)" strokeWidth="0.5" />
        ))}
        {/* gleba destacada no centro */}
        <circle cx="79" cy="50" r="7" fill="none" stroke="var(--fg)" strokeWidth="1.6" />
        <circle cx="79" cy="50" r="2.4" fill="var(--sv-coral)" />
      </svg>
      <span className="mono ri-cap">CONTEXTO H3-6 · {p.regiao.toUpperCase()}</span>
    </div>
  );
}

function parcelRec(p) {
  if (p.anomalia) return `Anomalia Proagro: ${p.sinistros5s} sinistros em 5s sem produtividade reportada (ND). Bloquear subscrição e exigir vistoria presencial antes de qualquer operação.`;
  if (p.tier === "A") return `Gleba Nível A${p.regiao !== "Oeste SC" ? " dentro de zona regional inferior" : ""}. ${p.irrigado ? "Irrigação confirmada via NDVI estável. " : ""}Score ${p.score}. Franquia de 20% (vs. padrão regional 35%).`;
  if (p.tier === "B") return `Nível B · score ${p.score}. Aceitar com gatilho elevado (${p.sinistros5s >= 5 ? 55 : 40}%) e franquia padrão. Monitorar NDVI na próxima safra.`;
  return `Nível C · score ${p.score}, ${p.sinistros5s} sinistros em 5s. Recusar ou condicionar a termo especial com vistoria.`;
}

/* ---------------- evidence modal ---------------- */
function EvidenceModal({ p, parcel, lens, year, onClose }) {
  const hash = useMemo(() => (Math.abs([...(p.id + lens + year)].reduce((a, c) => (a * 31 + c.charCodeAt(0)) >>> 0, 7)).toString(16).slice(0, 10).toUpperCase()), [p.id, lens, year]);
  return (
    <div className="cb-overlay" onClick={onClose}>
      <div className="up-panel ev-panel fade-up" onClick={e => e.stopPropagation()}>
        <div className="ev-h"><Icon name="download" size={14} color="var(--sv-coral)" /><b>Exportar evidência</b><button className="hp-close" onClick={onClose}><Icon name="x" size={14} /></button></div>
        <p className="up-body">Snapshot georreferenciado do estado atual do mapa — anexo automático da trilha de decisão do Protocolo e do dossiê <span className="mono">/verify/{p.id}</span>.</p>
        <div className="ev-meta">
          {[["Ativo", p.id], ["Lente", (SKY.PARCEL_LENSES.find(l => l.id === lens) || {}).label], ["Data da cena", year + " · Sentinel-2"], ["Datum", "EPSG:4674 · SIRGAS 2000"], ["Área (CAR)", parcel.areaHa + " ha"], ["Hash de integridade", "0x" + hash]].map(([k, v]) => (
            <div className="ev-row" key={k}><span className="mono">{k}</span><b>{v}</b></div>
          ))}
        </div>
        <div className="row gap8" style={{ marginTop: 14 }}>
          <button className="btn btn-primary" onClick={onClose}><Icon name="download" size={13} /> PDF georreferenciado</button>
          <button className="btn" onClick={onClose}>GeoTIFF / GeoJSON</button>
        </div>
      </div>
    </div>
  );
}

/* ---------------- INSPECTOR ---------------- */
function PropertyInspector({ p, onClose, chat }) {
  const pc = window.h3 ? SKY.buildParcel(p, window.h3) : null;
  const [basemap, setBasemap] = useState("sat");
  const [lens, setLens] = useState("ndvi");
  const [layers, setLayers] = useState({ cells: true, limite: true, hidro: true, sinistros: true, desmate: true });
  const [year, setYear] = useState(2023);
  const [compare, setCompare] = useState(false);
  const [compareYear, setCompareYear] = useState(2022);
  const [tool, setTool] = useState(null);
  const [annotations, setAnnotations] = useState([]);
  const [selectedCell, setSelectedCell] = useState(null);
  const [expanded, setExpanded] = useState(false);
  const [evidence, setEvidence] = useState(false);
  const [vistoria, setVistoria] = useState(false);

  const sources = useMemo(() => SKY.parcelLayerSources(p), [p.id]);
  const badge = useMemo(() => SKY.protocolBadge(p), [p.id]);
  const regScore = { "Oeste PR": 68, "Oeste SC": 74, "NW RS": 61, "Noroeste RS": 61, "Passo Fundo": 43 }[p.regiao] || 60;
  const scoreColor = SKY.scoreColor(p.score);
  const years = [14,15,16,17,18,19,20,21,22,23];
  const tl = years.map((y, i) => { const seed = (p.id.charCodeAt(5) + i * 7) % 5; return p.sinistros5s > 0 && (seed === 0 || (p.anomalia && i % 2 === 0)) ? 1 : 0; });

  useEffect(() => { const onKey = (e) => { if (e.key === "Escape") { if (selectedCell) setSelectedCell(null); else onClose(); } }; window.addEventListener("keydown", onKey); return () => window.removeEventListener("keydown", onKey); }, [selectedCell]);

  function addAnnotation(a) { setAnnotations(s => [...s, a]); if (a.kind === "vistoria") setVistoria(true); }
  function toggleTool(t) { setTool(cur => cur === t ? null : t); if (t === "exportar") { setTool(null); setEvidence(true); } if (t === "vistoria") setVistoria(true); }

  const TOOLS = [
    { id: "medir", icon: "target", label: "Medir" },
    { id: "anotar", icon: "plus", label: "Anotar" },
    { id: "vistoria", icon: "scan", label: "Vistoria" },
    { id: "exportar", icon: "download", label: "Exportar" },
  ];

  // exception banner
  let exception = null;
  if (p.anomalia) exception = { tone: "bad", icon: "alert", text: "Divergência cadastral: uso real diverge do CAR declarado · vistoria recomendada" };
  else if (!p.produtividade) exception = { tone: "warn", icon: "drop", text: "Cobertura de nuvem na última cena — exibindo última cena válida (" + year + ")" };

  return (
    <div className="prop-inspector-overlay" onMouseDown={(e) => { if (e.target === e.currentTarget) onClose(); }}>
      <div className={"prop-inspector fade-up" + (expanded ? " expanded" : "")}>
        {/* header + breadcrumb */}
        <div className="pi-head">
          <div className="pi-head-l">
            <nav className="pi-crumb mono">
              <span>Carteira</span><Icon name="chevR" size={10} />
              <span>{p.municipio}</span><Icon name="chevR" size={10} />
              <b>{p.id}</b>
              {selectedCell && <><Icon name="chevR" size={10} /><span className="cyan">célula {selectedCell.h3.slice(-5)}</span></>}
            </nav>
            <h3 className="mono">{p.id}</h3>
            <span className="pi-muni">{p.municipio} · {p.uf} <span className="soft">· {p.cultura} · {p.irrigado ? "irrigado" : "sequeiro"}</span></span>
          </div>
          <div className="pi-head-r">
            <span className="pi-tier"><TierBadge tier={p.tier} /></span>
            <div className="pi-score"><span className="pis-val tnum" style={{ color: scoreColor }}>{p.score}</span><span className="pis-lab mono">/100 · score</span></div>
            <button className="hp-close" onClick={() => setExpanded(e => !e)} title={expanded ? "restaurar" : "expandir"}><Icon name={expanded ? "x" : "share"} size={15} /></button>
            <button className="hp-close" onClick={onClose}><Icon name="x" size={16} /></button>
          </div>
        </div>

        <div className="pi-body">
          {/* MAP column */}
          <div className="pi-map">
            <LensBar lens={lens} onLens={setLens} />
            <div className="pi-maparea">
              {pc ? <ParcelMap p={p} parcel={pc} lens={lens} layers={layers} basemap={basemap} onBasemap={setBasemap}
                year={year} compare={compare} compareYear={compareYear} tool={tool}
                annotations={annotations} onAddAnnotation={addAnnotation} onPickCell={setSelectedCell} selectedCell={selectedCell} />
                : <div className="parcel-canvas-wrap"><div className="parcel-loading"><span className="led-spin" /><span className="mono">carregando geometria</span></div></div>}

              {exception && <div className={"pm-exception " + exception.tone}><Icon name={exception.icon} size={13} /> {exception.text}</div>}

              <LayerPanel lens={lens} layers={layers} setLayers={setLayers} sources={sources} p={p} />

              {/* toolbar */}
              <div className="pm-toolbar">
                {TOOLS.map(t => (
                  <button key={t.id} className={"pm-tool" + (tool === t.id ? " on" : "")} onClick={() => toggleTool(t.id)} title={t.label}>
                    <Icon name={t.icon} size={14} /><span>{t.label}</span>
                  </button>
                ))}
              </div>
              {tool === "medir" && pc && (
                <div className="pm-measure mono">ÁREA {pc.areaHa} ha · PERÍMETRO ~{Math.round(Math.sqrt(pc.areaHa * 10000) * 4 / 100) / 10} km · {pc.talhoes} talhões</div>
              )}
              {(tool === "anotar" || tool === "vistoria") && <div className="pm-tool-hint mono">CLIQUE NO MAPA PARA {tool === "anotar" ? "ANOTAR" : "MARCAR VISTORIA"}</div>}
            </div>

            {/* timeline */}
            {pc && <Timeline parcel={pc} year={year} setYear={setYear} compare={compare} setCompare={setCompare} compareYear={compareYear} setCompareYear={setCompareYear} />}
          </div>

          {/* INSIGHTS column — gramática fractal 01·02·03·04 */}
          <div className="pi-side">
            {selectedCell && (
              <div className="pi-sec pi-cellcard">
                <div className="pi-sec-h mono">célula H3 · {selectedCell.h3.slice(-6)}<button className="cell-x" onClick={() => setSelectedCell(null)}><Icon name="x" size={11} /></button></div>
                <div className="cell-grid">
                  <div><span>NDVI</span><b className="tnum">{selectedCell.ndvi}</b></div>
                  <div><span>ESG</span><b className="tnum">{selectedCell.esg}</b></div>
                  <div><span>Agro</span><b className="tnum">{selectedCell.agro}</b></div>
                  <div><span>Uso</span><b>{(SKY.USO_CLASSES.find(u => u.id === selectedCell.uso) || {}).label}</b></div>
                </div>
              </div>
            )}

            <div className="pi-sec">
              <div className="pi-sec-h mono">01 · leitura da gleba</div>
              <div className="pi-stats">
                <div className="pi-stat"><span className="ps-lab">Área (CAR)</span><span className="ps-val tnum">{pc ? pc.areaHa : "—"}<small> ha</small></span></div>
                <div className="pi-stat"><span className="ps-lab">Talhões</span><span className="ps-val tnum">{pc ? pc.talhoes : "—"}</span></div>
                <div className="pi-stat"><span className="ps-lab">NDVI médio</span><span className="ps-val tnum" style={{ color: pc && pc.ndviMean >= 0.55 ? "var(--risk-low)" : "var(--sv-warn)" }}>{pc ? pc.ndviMean : "—"}</span></div>
                <div className="pi-stat"><span className="ps-lab">Uniformidade</span><span className="ps-val tnum">{pc ? pc.uniformity : "—"}<small>%</small></span></div>
                <div className="pi-stat"><span className="ps-lab">Área frágil</span><span className="ps-val tnum" style={{ color: pc && pc.riskPct > 30 ? "var(--risk-critical)" : "var(--fg)" }}>{pc ? pc.riskPct : "—"}<small>%</small></span></div>
                <div className="pi-stat"><span className="ps-lab">Solo</span><span className="ps-val ps-sm">{pc ? pc.solo : "—"}</span></div>
              </div>
            </div>

            <div className="pi-sec">
              <div className="pi-sec-h mono">02 · score vs. média regional</div>
              <div className="pi-vs-grid">
                <div className="pi-vs-bars">
                  <div className="pd-bars">
                    <div className="pdb"><span>Gleba</span><i style={{ width: p.score + "%", background: scoreColor }} /><b className="tnum">{p.score}</b></div>
                    <div className="pdb"><span>{p.regiao}</span><i style={{ width: regScore + "%", background: "var(--fg-mute)" }} /><b className="tnum">{regScore}</b></div>
                  </div>
                  {p.tier === "A" && p.score - regScore > 12 && (
                    <div className="pi-flag good"><Icon name="gem" size={12} /> Top Lead — {p.score - regScore} pts acima da região</div>
                  )}
                  {p.anomalia && <div className="pi-flag bad"><Icon name="alert" size={12} /> Anomalia — produtividade ND</div>}
                </div>
                {pc && <RegionInset p={p} parcel={pc} />}
              </div>
            </div>

            <div className="pi-sec">
              <div className="pi-sec-h mono">03 · histórico · sinistros 5s</div>
              <div className="sin-timeline">
                {tl.map((s, i) => (<button key={i} className="sin-yr" onClick={() => setYear(2014 + i)}><span className={"sin-dot" + (s ? (p.anomalia ? " fraud" : " hit") : "") + (2014 + i === year ? " now" : "")} /><em className="mono">'{years[i]}</em></button>))}
              </div>
              <div className="kv" style={{ marginTop: 10 }}><span>Total acionamentos</span><b className="tnum">{p.sinistros5s}</b></div>
              <div className="kv"><span>Produtividade</span><b className="tnum">{p.produtividade ? p.produtividade + " sc/ha" : "ND"}</b></div>
            </div>

            {/* protocol badge */}
            <div className="pi-protocol" onClick={() => chat.askFree("Mostre a regra do protocolo " + badge.nome + " v" + badge.versao + " que classificou o ativo " + p.id)}>
              <div className="pp-l"><span className="mono">PROTOCOLO VIGENTE</span><b>{badge.nome} v{badge.versao}</b></div>
              <span className={"pp-tier act-" + badge.acao}>{badge.label}</span>
            </div>

            <div className={"pi-rec" + (p.anomalia ? " fraud" : "")}>
              <div className="pdr-head"><Icon name="sparkles" size={13} color={p.anomalia ? "var(--risk-critical)" : "var(--sv-cyan)"} /> 04 · recomendação prescritiva</div>
              <p>{parcelRec(p)}</p>
              <div className="row gap8" style={{ marginTop: 10 }}>
                <button className="btn btn-primary" style={{ flex: 1, justifyContent: "center" }}
                  onClick={() => chat.askGeoHex({ h3: (pc && pc.h3cell) || p.id, region: p.municipio + " · " + p.id, uf: p.uf,
                    score: p.score, level: SKY.levelOf(p.score), fraude: !!p.anomalia,
                    sicor: 400, sinistros: p.sinistros5s * 2, decretos: Math.round(p.sinistros5s / 3),
                    ndvi: pc ? pc.ndviMean : 0.5, tierA: p.tier === "A" ? 1 : 0, cultura: p.cultura, solo: pc ? pc.solo : "—",
                    comp: { esg: 70, sinist: 100 - p.sinistros5s * 6 }, lisa: { k: p.tier === "A" ? "HL" : "ns", label: p.tier === "A" ? "Alto-Baixo" : "ns" }, dataVintage: p.produtividade ? "2020–2025 · georref." : "pré-2013 · inferido", dataQ: p.produtividade ? 92 : 60 })}>
                  <Icon name="sparkles" size={12} /> Analisar com IA
                </button>
                <button className="btn btn-cyan" onClick={() => setEvidence(true)} title="Exportar evidência"><Icon name="download" size={13} /></button>
              </div>
            </div>
          </div>
        </div>
      </div>

      {evidence && pc && <EvidenceModal p={p} parcel={pc} lens={lens} year={year} onClose={() => setEvidence(false)} />}
      {vistoria && (
        <div className="cb-overlay" onClick={() => setVistoria(false)}>
          <div className="up-panel vist-panel fade-up" onClick={e => e.stopPropagation()}>
            <div className="ev-h"><Icon name="scan" size={14} color="var(--sv-cyan)" /><b>Vistoria de campo</b><button className="hp-close" onClick={() => setVistoria(false)}><Icon name="x" size={14} /></button></div>
            <p className="up-body">Workflow "vistoria para score &lt; 40" aterrissa aqui. Checklist georreferenciado · modo offline (PWA) com GPS "dentro da gleba".</p>
            <div className="vist-check">
              {["Confirmar limite CAR em campo", "Fotografar área de menor NDVI", "Verificar uso real vs. declarado", "Registrar coordenada GPS da inspeção"].map((c, i) => (
                <label key={i} className="vist-item"><span className="lcheck" /><span>{c}</span></label>
              ))}
            </div>
            <button className="btn btn-primary" style={{ width: "100%", justifyContent: "center", marginTop: 12 }} onClick={() => setVistoria(false)}><Icon name="check" size={13} /> Agendar vistoria</button>
          </div>
        </div>
      )}
    </div>
  );
}

Object.assign(window, { ParcelMap, PropertyInspector });
