// PFI Map — React component that preserves all logic from the original artifact

const PFIMap = ({ onRequestAudit }) => {
  const svgRef = React.useRef(null);
  const tooltipRef = React.useRef(null);
  const legendRef = React.useRef(null);
  const [activeSector, setActiveSector] = React.useState(null);
  const [activeFilter, setActiveFilter] = React.useState('all');
  const [totals, setTotals] = React.useState({});
  const [ordered, setOrdered] = React.useState([]);
  const [grand, setGrand] = React.useState(0);
  const allCellsRef = React.useRef([]);
  const regionTotalsRef = React.useRef({});

  // Build the SVG once
  React.useEffect(() => {
    const svg = svgRef.current;
    if (!svg) return;
    // wipe
    while (svg.firstChild) svg.removeChild(svg.firstChild);

    const NS = 'http://www.w3.org/2000/svg';
    const defs = document.createElementNS(NS, 'defs');
    svg.appendChild(defs);
    const clip = document.createElementNS(NS, 'clipPath');
    clip.setAttribute('id', 'ukclip');
    const clipPath = document.createElementNS(NS, 'path');
    clipPath.setAttribute('d', UK_PATH_D);
    clip.appendChild(clipPath);
    defs.appendChild(clip);

    const land = document.createElementNS(NS, 'path');
    land.setAttribute('d', UK_PATH_D);
    land.setAttribute('fill', '#E4ECEA');
    land.setAttribute('stroke', '#2E3B3B');
    land.setAttribute('stroke-width', '0.6');
    land.setAttribute('stroke-linejoin', 'round');
    svg.appendChild(land);

    const gridGroup = document.createElementNS(NS, 'g');
    gridGroup.setAttribute('clip-path', 'url(#ukclip)');
    svg.appendChild(gridGroup);

    const CELL = 4, W = 200, H = 200;
    function regionAt(x, y) {
      let best = null, bestD = Infinity;
      for (const [name, c] of Object.entries(REGION_CENTROIDS)) {
        const d = Math.hypot(x - c.x, y - c.y);
        if (d < bestD) { bestD = d; best = name; }
      }
      return best;
    }

    const regionCells = {};
    for (const r of Object.keys(REGION_CENTROIDS)) regionCells[r] = [];
    for (let y = 0; y <= H; y += CELL) {
      for (let x = 0; x <= W; x += CELL) {
        regionCells[regionAt(x, y)].push([x, y]);
      }
    }

    for (const [region, cells] of Object.entries(regionCells)) {
      const counts = DATA[region] || {};
      const entries = Object.entries(counts).sort((a, b) => b[1] - a[1]);
      const tot = entries.reduce((s, [, c]) => s + c, 0);
      if (!tot || !cells.length) continue;
      const c = REGION_CENTROIDS[region];
      cells.sort((a, b) => Math.hypot(a[0]-c.x, a[1]-c.y) - Math.hypot(b[0]-c.x, b[1]-c.y));
      const byCount = [...entries];
      const bagSorted = [];
      for (const [sector, count] of byCount) {
        const n = Math.round(cells.length * count / tot);
        for (let i = 0; i < n; i++) bagSorted.push(sector);
      }
      while (bagSorted.length < cells.length) bagSorted.push(byCount[0][0]);
      bagSorted.length = cells.length;
      for (let i = 0; i < cells.length; i++) {
        const sector = bagSorted[i];
        const color = SECTOR_COLORS[sector] || '#909497';
        const [x, y] = cells[i];
        const cellGroup = document.createElementNS(NS, 'g');
        cellGroup.setAttribute('class', 'map-cell');
        cellGroup.setAttribute('data-region', region);
        cellGroup.setAttribute('data-sector', sector);
        const l1 = document.createElementNS(NS, 'line');
        l1.setAttribute('x1', x - CELL/2); l1.setAttribute('x2', x + CELL/2);
        l1.setAttribute('y1', y); l1.setAttribute('y2', y);
        l1.setAttribute('stroke', color); l1.setAttribute('stroke-width', 1.1);
        l1.setAttribute('stroke-linecap', 'square');
        cellGroup.appendChild(l1);
        const l2 = document.createElementNS(NS, 'line');
        l2.setAttribute('x1', x); l2.setAttribute('x2', x);
        l2.setAttribute('y1', y - CELL/2); l2.setAttribute('y2', y + CELL/2);
        l2.setAttribute('stroke', color); l2.setAttribute('stroke-width', 1.1);
        l2.setAttribute('stroke-linecap', 'square');
        cellGroup.appendChild(l2);
        const hit = document.createElementNS(NS, 'rect');
        hit.setAttribute('x', x - CELL/2); hit.setAttribute('y', y - CELL/2);
        hit.setAttribute('width', CELL); hit.setAttribute('height', CELL);
        hit.setAttribute('fill', 'transparent'); hit.setAttribute('pointer-events', 'all');
        cellGroup.appendChild(hit);
        gridGroup.appendChild(cellGroup);
      }
    }

    const outline = document.createElementNS(NS, 'path');
    outline.setAttribute('d', UK_PATH_D);
    outline.setAttribute('fill', 'none');
    outline.setAttribute('stroke', '#2E3B3B');
    outline.setAttribute('stroke-width', '0.7');
    outline.setAttribute('stroke-linejoin', 'round');
    outline.setAttribute('pointer-events', 'none');
    svg.appendChild(outline);

    // Region totals
    const rt = {};
    for (const [region, counts] of Object.entries(DATA)) {
      rt[region] = Object.values(counts).reduce((s, n) => s + n, 0);
    }
    regionTotalsRef.current = rt;

    // Totals per sector for legend
    const t = {}; let g = 0;
    for (const r of Object.values(DATA)) {
      for (const [s, c] of Object.entries(r)) { t[s] = (t[s] || 0) + c; g += c; }
    }
    const ord = Object.keys(SECTOR_COLORS).filter(s => t[s]).sort((a, b) => t[b] - t[a]);
    setTotals(t); setOrdered(ord); setGrand(g);

    allCellsRef.current = Array.from(gridGroup.querySelectorAll('.map-cell'));
  }, []);

  // Apply cell state whenever sector or filter changes
  React.useEffect(() => {
    const cells = allCellsRef.current;
    if (activeSector) {
      for (const c of cells) c.style.opacity = c.getAttribute('data-sector') === activeSector ? '1' : '0.15';
      return;
    }
    const group = FILTER_GROUPS[activeFilter];
    if (!group) { for (const c of cells) c.style.opacity = '1'; return; }
    for (const c of cells) c.style.opacity = group.includes(c.getAttribute('data-sector')) ? '1' : '0.15';
  }, [activeSector, activeFilter]);

  // Hover logic
  React.useEffect(() => {
    const svg = svgRef.current;
    const tooltip = tooltipRef.current;
    if (!svg || !tooltip) return;
    let hovered = null;

    function show(region, ev) {
      tooltip.querySelector('.tt-region').textContent = REGION_LABEL(region);
      tooltip.querySelector('.tt-count').textContent = regionTotalsRef.current[region];
      tooltip.classList.add('visible');
      position(ev);
    }
    function position(ev) {
      const pad = 14;
      const ttW = tooltip.offsetWidth, ttH = tooltip.offsetHeight;
      let x = ev.clientX + pad, y = ev.clientY + pad;
      if (x + ttW > window.innerWidth - 8) x = ev.clientX - ttW - pad;
      if (y + ttH > window.innerHeight - 8) y = ev.clientY - ttH - pad;
      tooltip.style.left = x + 'px'; tooltip.style.top = y + 'px';
    }
    function onMove(ev) {
      const target = ev.target.closest('.map-cell');
      if (!target) return;
      const region = target.getAttribute('data-region');
      if (region !== hovered) {
        hovered = region;
        if (!activeSector && activeFilter === 'all') {
          for (const c of allCellsRef.current) {
            c.style.opacity = c.getAttribute('data-region') === region ? '1' : '0.2';
          }
        }
        show(region, ev);
      } else { position(ev); }
    }
    function onLeave() {
      hovered = null;
      tooltip.classList.remove('visible');
      // reapply state
      if (activeSector) {
        for (const c of allCellsRef.current) c.style.opacity = c.getAttribute('data-sector') === activeSector ? '1' : '0.15';
      } else {
        const group = FILTER_GROUPS[activeFilter];
        if (!group) for (const c of allCellsRef.current) c.style.opacity = '1';
        else for (const c of allCellsRef.current) c.style.opacity = group.includes(c.getAttribute('data-sector')) ? '1' : '0.15';
      }
    }
    svg.addEventListener('mousemove', onMove);
    svg.addEventListener('mouseleave', onLeave);
    return () => { svg.removeEventListener('mousemove', onMove); svg.removeEventListener('mouseleave', onLeave); };
  }, [activeSector, activeFilter]);

  // Escape resets
  React.useEffect(() => {
    const onKey = (ev) => {
      if (ev.key === 'Escape') { setActiveSector(null); setActiveFilter('all'); }
    };
    document.addEventListener('keydown', onKey);
    return () => document.removeEventListener('keydown', onKey);
  }, []);

  const diag = activeSector ? SECTOR_DIAGNOSTIC[activeSector] : null;

  return (
    <div style={{
      display: 'grid',
      gridTemplateColumns: 'minmax(320px, 1fr) 360px',
      gap: 48,
      alignItems: 'start',
    }} className="mob-stack">
      {/* Left: Map + filters + legend */}
      <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 16 }}>
        <svg
          ref={svgRef}
          viewBox="0 0 200 200"
          style={{
            width: 'clamp(320px, 48vw, 480px)',
            height: 'clamp(320px, 48vw, 480px)',
            background: 'var(--paper)',
            display: 'block',
            shapeRendering: 'crispEdges',
          }}
          aria-label="UK PFI contract density map"
        />
        {/* Filters */}
        <div role="group" aria-label="Sector category filter" style={{
          display: 'flex', gap: 6, flexWrap: 'wrap', justifyContent: 'center',
          marginTop: 4, width: '100%', maxWidth: 480,
        }}>
          {[
            ['all', 'All sectors'],
            ['education', 'Education'],
            ['healthcare', 'Healthcare'],
            ['infrastructure', 'Infrastructure'],
          ].map(([k, label]) => {
            const active = activeFilter === k;
            return (
              <button
                key={k}
                type="button"
                onClick={() => { setActiveSector(null); setActiveFilter(k); }}
                style={{
                  fontFamily: 'var(--ff-body)', fontSize: 10, fontWeight: 500,
                  letterSpacing: '0.06em',
                  color: active ? 'var(--paper)' : 'var(--slate)',
                  background: active ? 'var(--canton)' : 'transparent',
                  border: `1px solid ${active ? 'var(--canton)' : 'var(--stone)'}`,
                  padding: '6px 12px', borderRadius: 3, cursor: 'pointer',
                  transition: 'all 140ms var(--ease-out)',
                }}
              >{label}</button>
            );
          })}
        </div>
        {/* Legend */}
        <div ref={legendRef} role="list" style={{
          display: 'grid', gridTemplateColumns: 'repeat(3, minmax(0, 1fr))',
          gap: '2px 14px', fontSize: 9, color: 'var(--slate)',
          width: '100%', maxWidth: 480,
        }}>
          {ordered.map((s) => {
            const selected = activeSector === s;
            return (
              <button
                key={s}
                type="button"
                role="listitem"
                aria-label={`Filter map to ${s}. ${totals[s]} contracts.`}
                onClick={() => setActiveSector(selected ? null : s)}
                style={{
                  display: 'flex', alignItems: 'center', gap: 4, whiteSpace: 'nowrap',
                  background: selected ? 'var(--stone-light)' : 'transparent',
                  border: 'none', padding: '3px 4px', cursor: 'pointer',
                  fontFamily: 'inherit', fontSize: 'inherit', textAlign: 'left',
                  borderRadius: 2, color: 'var(--slate)',
                }}
              >
                <span style={{ width: 8, height: 8, borderRadius: 1, background: SECTOR_COLORS[s], flex: '0 0 8px' }} />
                <span style={{
                  overflow: 'hidden', textOverflow: 'ellipsis',
                  color: selected ? 'var(--teal)' : undefined,
                  fontWeight: selected ? 600 : 400,
                }}>{s}</span>
                <span style={{ marginLeft: 'auto', paddingLeft: 8, fontVariantNumeric: 'tabular-nums', color: 'var(--charcoal)', fontWeight: 600 }}>{totals[s]}</span>
              </button>
            );
          })}
        </div>
      </div>

      {/* Right: Diagnostic panel */}
      <aside
        aria-live="polite"
        style={{
          background: 'var(--paper)',
          border: `1px solid ${activeSector ? 'var(--canton)' : 'var(--stone)'}`,
          borderRadius: 3, padding: '28px 28px 24px',
          position: 'sticky', top: 96, minHeight: 320,
          display: 'flex', flexDirection: 'column',
          transition: 'border-color 240ms var(--ease-out)',
        }}
      >
        <div style={{ fontFamily: 'var(--ff-body)', fontSize: 10, fontWeight: 500, letterSpacing: '0.18em', textTransform: 'uppercase', color: 'var(--canton)', marginBottom: 14 }}>
          Sector diagnostic
        </div>
        {!activeSector && (
          <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
            <p style={{ fontFamily: 'var(--ff-display)', fontSize: 19, lineHeight: 1.25, color: 'var(--slate)', fontWeight: 400, letterSpacing: '-0.005em', margin: 0 }}>
              {grand} PFI contracts. <Em>Each one a payment mechanism being read by someone.</Em>
            </p>
            <p style={{ fontFamily: 'var(--ff-body)', fontSize: 13, lineHeight: 1.65, color: 'var(--charcoal)', fontWeight: 300, margin: 0 }}>
              Hover a region to see its contract density. Click any sector in the legend to read what a Payment Mechanism Audit examines in that part of the market.
            </p>
            <p style={{ fontFamily: 'var(--ff-body)', fontSize: 11, color: '#7F8A88', letterSpacing: '0.04em', paddingTop: 10, borderTop: '1px solid var(--stone-light)', marginTop: 4 }}>
              Click a sector swatch to read the diagnostic. Press Esc to reset.
            </p>
          </div>
        )}
        {activeSector && (
          <div style={{ display: 'flex', flexDirection: 'column', gap: 14, flex: 1 }}>
            <h3 style={{ fontFamily: 'var(--ff-display)', fontSize: 20, color: 'var(--slate)', fontWeight: 400, lineHeight: 1.2, letterSpacing: '-0.005em', margin: 0 }}>
              {activeSector}
            </h3>
            <p style={{ fontFamily: 'var(--ff-display)', fontStyle: 'italic', fontSize: 36, color: 'var(--canton)', lineHeight: 1, margin: 0 }}>
              {totals[activeSector]}
              <span style={{ fontFamily: 'var(--ff-body)', fontSize: 10, fontStyle: 'normal', letterSpacing: '0.14em', textTransform: 'uppercase', color: '#7F8A88', marginLeft: 8, fontWeight: 500 }}>
                contracts
              </span>
            </p>
            <p style={{ fontFamily: 'var(--ff-body)', fontSize: 13, lineHeight: 1.65, color: 'var(--charcoal)', fontWeight: 300, margin: 0 }}>
              {diag}
            </p>
            <button
              type="button"
              onClick={onRequestAudit}
              style={{
                display: 'inline-flex', alignItems: 'center', gap: 8,
                fontFamily: 'var(--ff-body)', fontSize: 12, fontWeight: 500, letterSpacing: '0.04em',
                color: 'var(--teal)', background: 'transparent', border: 'none',
                borderBottom: '1px solid var(--canton)', padding: '4px 0 3px',
                marginTop: 'auto', cursor: 'pointer', alignSelf: 'flex-start',
                transition: 'color 140ms var(--ease-out)',
              }}
            >
              Request a Payment Mechanism Audit →
            </button>
            <button
              type="button"
              onClick={() => setActiveSector(null)}
              style={{
                fontFamily: 'var(--ff-body)', fontSize: 10, fontWeight: 500, letterSpacing: '0.08em',
                textTransform: 'uppercase', color: '#7F8A88',
                background: 'transparent', border: 'none', cursor: 'pointer',
                padding: 0, alignSelf: 'flex-start', marginTop: 4,
              }}
            >
              ← Reset view
            </button>
          </div>
        )}
      </aside>

      {/* Tooltip */}
      <div
        ref={tooltipRef}
        role="status" aria-live="polite"
        style={{
          position: 'fixed', pointerEvents: 'none',
          background: 'var(--teal)', padding: '8px 10px', borderRadius: 2,
          opacity: 0, transition: 'opacity 120ms var(--ease-out)',
          zIndex: 60, whiteSpace: 'nowrap',
        }}
        className="pfi-tooltip"
      >
        <span className="tt-region" style={{
          display: 'block', fontFamily: 'var(--ff-body)', fontSize: 9,
          textTransform: 'uppercase', letterSpacing: '0.14em',
          color: '#7FA69F', marginBottom: 3,
        }} />
        <span style={{ display: 'block', fontFamily: 'var(--ff-display)', fontSize: 14, color: 'var(--paper)', lineHeight: 1 }}>
          <span className="tt-count" />
          <span style={{ fontFamily: 'var(--ff-body)', fontSize: 9, color: 'rgba(245,245,243,0.55)', fontWeight: 300, marginLeft: 4 }}>contracts</span>
        </span>
      </div>
      <style>{`.pfi-tooltip.visible { opacity: 1 !important; }`}</style>
    </div>
  );
};

Object.assign(window, { PFIMap });
