/* ============================================================
   Map Workspace — toolbar, search, layers, basemap, results panel
   ============================================================ */

const TOOLS = [
  { id: 'draw',  mode: 'draw',  glyph: PCI.drawPoly, tip: 'Draw polygon' },
  { id: 'edit',  mode: 'edit',  glyph: PCI.editPoly, tip: 'Edit polygon' },
  { id: 'address', mode: 'address', glyph: PCI.address, tip: 'Drop / enter address' },
  { id: 'measure-distance', mode: 'measure-distance', glyph: PCI.ruler, tip: 'Measure distance' },
  { id: 'measure-area', mode: 'measure-area', glyph: PCI.area, tip: 'Measure area' },
];

const Toolbar = ({ tool, onTool, onClear }) => (
  <div className="pc-toolbar">
    {TOOLS.map((t, i) => (
      <React.Fragment key={t.id}>
        {(i === 3) && <span className="pc-tool-sep" />}
        <span className="pc-tool-wrap">
          <button className={`pc-tool ${tool === t.id ? 'is-active' : ''} ${t.id.startsWith('measure') ? 'measure' : ''}`}
                  onClick={() => onTool(t.id)} aria-label={t.tip}>{t.glyph}</button>
          <span className="pc-tool-tip">{t.tip}</span>
        </span>
      </React.Fragment>
    ))}
    <span className="pc-tool-sep" />
    <span className="pc-tool-wrap">
      <button className="pc-tool" onClick={onClear} aria-label="Clear">{PCI.close}</button>
      <span className="pc-tool-tip">Clear</span>
    </span>
  </div>
);

const SearchBox = ({ value, onChange, results, onPick, inputRef }) => (
  <div className="pc-search">
    <div className="pc-search-box">
      {PCI.search}
      <input ref={inputRef} value={value} onChange={e => onChange(e.target.value)}
             placeholder="Search an address or locality…" />
    </div>
    {results.length > 0 && (
      <div className="pc-search-results">
        {results.map((r, i) => (
          <div className="pc-search-item" key={i} onClick={() => onPick(r)}>
            {PCI.pin}<span>{r.label}</span><span className="sub">{r.sub}</span>
          </div>
        ))}
      </div>
    )}
  </div>
);

/** Nearby-grid map legend. Lives top-right of the map, below the Layers button. */
const GridLegend = ({ overlay }) => {
  const lineCount = overlay?.lines?.features?.length || 0;
  const subCount = overlay?.substations?.features?.length || 0;
  return (
    <div className="pc-grid-legend">
      <div className="pc-grid-legend-head">Nearby grid (5 km)</div>
      <div className="pc-grid-legend-sub">{lineCount} lines · {subCount} substations</div>
      <div className="pc-grid-legend-rows">
        <div className="row"><span className="ln tx" /><span>≥110 kV (transmission)</span></div>
        <div className="row"><span className="ln s66" /><span>50–66 kV</span></div>
        <div className="row"><span className="ln s33" /><span>33 kV</span></div>
        <div className="row"><span className="ln s22" /><span>22 kV</span></div>
        <div className="row"><span className="ln s11" /><span>11 kV</span></div>
        <div className="row"><span className="sub-dot tx" /><span>Transmission sub</span></div>
        <div className="row"><span className="sub-dot dx" /><span>Subtransmission sub</span></div>
        <div className="row"><span className="ln buffer" /><span>1 / 2.5 / 5 km buffer</span></div>
      </div>
    </div>
  );
};

const LayerPanel = ({ layers, onToggle }) => (
  <div className="pc-layers">
    <h4>Overlay layers</h4>
    <p className="hint">More layers will activate as their data sources come online. The nearby-grid overlay is toggled from the Grid section in the report panel.</p>
    {layers.map(l => (
      <div className={`pc-layer-row ${l.on ? 'on' : ''} ${l.stub ? 'is-stub' : ''}`} key={l.id}
           onClick={() => { if (!l.stub) onToggle(l.id); }}
           aria-disabled={l.stub}>
        <span className="sw" style={{ background: l.color }} />
        <span className="lbl">{l.label}</span>
        {l.stub && <span className="stub">data pending</span>}
        <span className="pc-toggle" />
      </div>
    ))}
  </div>
);

const MapWorkspace = ({ toast, sites, activeSite, panelState, loadingStep, loadingError, clickThrough,
                        onDrawComplete, onPinDrop, onSiteClickMap, onEditComplete, onEditChange,
                        gridOverlayOn, gridOverlay, gridSectionToggle,
                        focalPoint, focalLabel, revertNonce,
                        onCloseReport, onExport, onOpenAssessor, panelW, setPanelW }) => {
  const mapDivRef = React.useRef(null);
  const mapRef = React.useRef(null);
  const inputRef = React.useRef(null);
  const handlers = React.useRef({});
  handlers.current = { onDrawComplete, onPinDrop, onSiteClickMap, onEditComplete, onEditChange };

  const [tool, setTool] = React.useState(null);
  const [basemap, setBasemap] = React.useState('aerial');
  const [layers, setLayers] = React.useState(() => window.PC_LAYERS.map(l => ({ ...l })));
  const [layerOpen, setLayerOpen] = React.useState(false);
  const [query, setQuery] = React.useState('');
  const [measure, setMeasure] = React.useState(null);
  const [draftCount, setDraftCount] = React.useState(0);
  const [ready, setReady] = React.useState(false);
  const draggingRef = React.useRef(false);

  // draggable panel divider
  React.useEffect(() => {
    const onMove = e => {
      if (!draggingRef.current) return;
      const w = window.innerWidth - e.clientX;
      const max = Math.min(820, window.innerWidth - 480);
      setPanelW(Math.max(380, Math.min(max, w)));
    };
    const onUp = () => {
      if (draggingRef.current) { draggingRef.current = false; document.body.style.userSelect = ''; document.body.style.cursor = ''; }
    };
    window.addEventListener('mousemove', onMove);
    window.addEventListener('mouseup', onUp);
    return () => { window.removeEventListener('mousemove', onMove); window.removeEventListener('mouseup', onUp); };
  }, []);
  React.useEffect(() => { mapRef.current && mapRef.current.resize(); }, [panelW]);

  // init map once
  React.useEffect(() => {
    const m = new window.PCMap(mapDivRef.current, {
      onReady: () => { setReady(true); layers.forEach(l => m.setLayer(l.id, l.on)); m.setSites(sites); },
      onDrawComplete: info => { handlers.current.onDrawComplete(info); setTool(null); m.setMode(null); },
      onPinDrop: p => { handlers.current.onPinDrop && handlers.current.onPinDrop(p); setTool(null); m.setMode(null); },
      onSiteClick: id => handlers.current.onSiteClickMap(id),
      onEditComplete: info => { handlers.current.onEditComplete && handlers.current.onEditComplete(info); },
      onEditChange: info => { handlers.current.onEditChange && handlers.current.onEditChange(info); },
      onMeasure: r => setMeasure(r),
    });
    mapRef.current = m;
    window.__pcmap = m;
    return () => { /* keep alive for session */ };
  }, []);

  // push site list changes into the map
  React.useEffect(() => {
    if (ready && mapRef.current) mapRef.current.setSites(sites);
  }, [sites, ready]);

  // push grid overlay into the map (toggle controlled in App)
  React.useEffect(() => {
    if (!ready || !mapRef.current) return;
    if (gridOverlayOn && gridOverlay) mapRef.current.setGridOverlay(gridOverlay);
    else mapRef.current.clearGridOverlay();
  }, [gridOverlayOn, gridOverlay, ready]);

  // keep the focal pin in sync with the focal point (site centroid OR dropped pin)
  React.useEffect(() => {
    if (!ready || !mapRef.current) return;
    if (focalPoint) mapRef.current.setPin(focalPoint, focalLabel);
    else mapRef.current.clearPin();
  }, [focalPoint && focalPoint[0], focalPoint && focalPoint[1], focalLabel, ready]);

  // reflect active site on the map. Re-runs on revertNonce bump so Discard
  // can throw away in-flight edits by re-showing the *stored* geometry.
  React.useEffect(() => {
    if (ready && activeSite && mapRef.current) mapRef.current.showSite(activeSite, true);
    if (ready && !activeSite && mapRef.current) mapRef.current.clearDraft();
  }, [activeSite, ready, revertNonce]);

  // resize when panel toggles
  React.useEffect(() => { const t = setTimeout(() => mapRef.current && mapRef.current.resize(), 260); return () => clearTimeout(t); }, [panelState, activeSite]);

  const pickTool = id => {
    const next = tool === id ? null : id;
    setTool(next);
    const m = mapRef.current; if (!m) return;
    if (id === 'address') { inputRef.current && inputRef.current.focus(); }
    if (next === null) { m.setMode(null); return; }
    m.setMode(TOOLS.find(t => t.id === id).mode);
    if (next && next !== 'edit' && next !== 'address') setMeasure(null);
  };

  const clearAll = () => { mapRef.current && mapRef.current.clearDraft(); setTool(null); mapRef.current && mapRef.current.setMode(null); setMeasure(null); setDraftCount(0); };

  const toggleLayer = id => {
    setLayers(ls => ls.map(l => {
      if (l.id !== id) return l;
      const on = !l.on; mapRef.current && mapRef.current.setLayer(id, on); return { ...l, on };
    }));
  };

  const setBm = b => { setBasemap(b); mapRef.current && mapRef.current.setBasemap(b); };

  const results = React.useMemo(() => {
    const q = query.trim().toLowerCase();
    if (!q) return [];
    return window.PC_GAZETTEER.filter(g => g.label.toLowerCase().includes(q)).slice(0, 6);
  }, [query]);

  const pickResult = r => {
    setQuery('');
    if (mapRef.current) {
      mapRef.current.flyTo(r.center, r.zoom);
      mapRef.current.setPin(r.center, r.label);
      handlers.current.onPinDrop && handlers.current.onPinDrop(r.center, r.label);
    }
  };

  const hasPanel = panelState !== 'hidden';

  return (
    <div className={`pc-workspace ${hasPanel ? 'has-panel' : 'no-panel'}`}
         style={hasPanel ? { gridTemplateColumns: `1fr ${panelW}px` } : undefined}>
      <div className="pc-mapwrap">
        <div className="pc-map" ref={mapDivRef} />

        <Toolbar tool={tool} onTool={pickTool} onClear={clearAll} />
        <SearchBox value={query} onChange={setQuery} results={results} onPick={pickResult} inputRef={inputRef} />

        <div className="pc-mapctrls">
          <button className={`pc-mapbtn ${layerOpen ? 'is-active' : ''}`} onClick={() => setLayerOpen(o => !o)}>{PCI.layers}Layers</button>
          {layerOpen && <LayerPanel layers={layers} onToggle={toggleLayer} />}
        </div>

        <div className="pc-basemap">
          <button className={basemap === 'aerial' ? 'is-active' : ''} onClick={() => setBm('aerial')}>Aerial</button>
          <button className={basemap === 'topo' ? 'is-active' : ''} onClick={() => setBm('topo')}>Topo</button>
        </div>

        {tool === 'draw' && (
          <div className="pc-draw-hint">Click to add points · click the <b>first point</b> or double-click to finish</div>
        )}
        {tool === 'address' && (
          <div className="pc-draw-hint">Click the map to drop a pin · then use <b>Draw polygon</b> to assess a boundary around it</div>
        )}
        {tool === 'edit' && !toast && (
          <div className="pc-draw-hint">Drag any <b>vertex</b> to reshape the boundary</div>
        )}
        {measure && (
          <div className="pc-measure-readout">
            <span>{measure.type === 'area' ? 'Area' : 'Distance'}</span>
            <span className="num">{measure.text}</span>
          </div>
        )}
        {gridOverlayOn && gridOverlay && <GridLegend overlay={gridOverlay} />}
        {/* Toast is inside .pc-mapwrap so its left:50%/translateX(-50%)
            centres it on the *map* (not the entire pc-main, which would
            shift it under the sidebar when the report panel is open). */}
        <Toast msg={toast} />
      </div>

      {hasPanel && (
        <div className="pc-panel">
          <div className="pc-panel-resize" title="Drag to resize"
               onMouseDown={e => { draggingRef.current = true; document.body.style.userSelect = 'none'; document.body.style.cursor = 'col-resize'; e.preventDefault(); }}>
            <span className="grip" />
          </div>
          {panelState === 'empty' && <EmptyPanel />}
          {panelState === 'loading' && <LoadingPanel step={loadingStep} />}
          {panelState === 'error' && <ErrorPanel error={loadingError} onClose={onCloseReport} />}
          {panelState === 'report' && activeSite && (
            <ReportPanel site={activeSite} onClose={onCloseReport} onExport={onExport}
                         onOpenAssessor={onOpenAssessor} clickable={clickThrough}
                         gridSectionToggle={gridSectionToggle} />
          )}
        </div>
      )}
    </div>
  );
};

window.MapWorkspace = MapWorkspace;
