// Data & Systems Readiness — sortable / filterable table + side panel.

const { useState: useStateD, useMemo: useMemoD, useEffect: useEffectD, useRef: useRefD } = React;

// Logo registry — local files in assets/logos/
// All logos are rendered as a uniform dark grey (≈ rgb(42,44,48)) via CSS filter.
// See CLAUDE.md "System Logos" section for the process to add new logos.
const LOGO_MAP = {
  // ── Marlow Property Partners ──────────────────────────────────────────────
  'Salesforce':                  'assets/logos/si-salesforce.svg',
  'Yardi Voyager':               'assets/logos/yardi-mark.svg',
  'Bill.com':                    'assets/logos/bill.svg',
  'QuickBooks':                  'assets/logos/si-quickbooks.svg',
  'ARGUS Enterprise':            'assets/logos/argus.svg',
  'Dropbox':                     'assets/logos/si-dropbox.svg',
  'Master Pipeline Spreadsheet': 'assets/logos/si-microsoftexcel.svg',
  'Outlook':                     'assets/logos/si-microsoftoutlook.svg',
  'Zoom':                        'assets/logos/si-zoom.svg',
  'CoStar':                      'assets/logos/costar-mark.svg',
  'Confluence':                  'assets/logos/si-confluence.svg',
  'SurveyMonkey':                'assets/logos/si-surveymonkey.svg',
  'Mailchimp':                   'assets/logos/si-mailchimp.svg',
  'LinkedIn Sales Navigator':    'assets/logos/si-linkedin.svg',
  'Shared Drive':                'assets/logos/si-microsoftsharepoint.svg',
  // ── Calder Built Group ────────────────────────────────────────────────────
  'HubSpot':                     'assets/logos/si-hubspot.svg',
  'NetSuite':                    'assets/logos/netsuite.svg',
  'QuickBooks Online':           'assets/logos/si-quickbooks.svg',
  'Procore':                     'assets/logos/procore-mark.svg',
  'Corecon':                     'assets/logos/si-sage.svg',
  'Excel Workbooks':             'assets/logos/si-microsoftexcel.svg',
  'Bluebeam Revu':               'assets/logos/bluebeam-mark.svg',
  'Sage 300':                    'assets/logos/si-sage.svg',
  // ── Crestwood Dental Group ────────────────────────────────────────────────
  'Dentrix Ascend':              'assets/logos/dentrix-ascend.svg',
  'Weave':                       'assets/logos/weave.svg',
  'monday.com':                  'assets/logos/si-monday.svg',
  'WordPress':                   'assets/logos/si-wordpress.svg',
  'Workbooks':                   'assets/logos/workbooks.svg',
  'Google Business Profile':     'assets/logos/si-googlemybusiness.svg',
  'Carestream Dental':           'assets/logos/carestream.png',
  // ── Shared spreadsheet names ──────────────────────────────────────────────
  'Insurance Fee Schedule Workbook': 'assets/logos/si-microsoftexcel.svg',
  'Staff Schedule & PTO Workbook':   'assets/logos/si-microsoftexcel.svg',
  'Supply Inventory & Order Tracker':'assets/logos/si-microsoftexcel.svg',
};

function SoftwareLogo({ name, size = 20 }) {
  const src = LOGO_MAP[name];
  if (!src) return null;
  return (
    <img
      src={src}
      alt={name}
      width={size}
      height={size}
      style={{
        width: size, height: size,
        objectFit: 'contain', flexShrink: 0, display: 'block',
        filter: 'brightness(0) opacity(0.83)',
      }}
      onError={e => { e.currentTarget.style.display = 'none'; }}
    />
  );
}

window.SoftwareLogo = SoftwareLogo;

function GovernanceChip({ status }) {
  const color = status === 'Approved' ? '#1a8f59' : status === 'Needs setup' ? '#b07a18' : '#a73a3a';
  const bg    = status === 'Approved' ? 'rgba(26,143,89,0.08)' : status === 'Needs setup' ? 'rgba(176,122,24,0.08)' : 'rgba(167,58,58,0.08)';
  return (
    <span style={{display:'inline-flex', alignItems:'center', gap:5, padding:'2px 8px', borderRadius:20, background:bg, color, fontSize:11.5, fontWeight:500}}>
      <span style={{width:5, height:5, borderRadius:'50%', background:color, flexShrink:0}}></span>
      {status}
    </span>
  );
}

function DataStructureTag({ value }) {
  const color = value === 'Structured' ? '#1a8f59' : value === 'Semi-structured' ? '#b07a18' : '#5e6068';
  return <span style={{color, fontWeight:500, fontSize:12.5}}>{value}</span>;
}

// --- Data catalog (drill-in: record types + details captured) ---------------

const CAT_SENSITIVITY = {
  'Business':  { c: '#2e5dff', label: 'Business data' },
  'Personal':  { c: '#a06d10', label: 'Personal info' },
  'Financial': { c: '#1a8f59', label: 'Financial' },
  'Public':    { c: '#5e6068', label: 'Public / licensed' },
};

const CAT_TAG_COLOR = {
  'Key detail':    '#2e5dff',
  'AI-ready':      '#1a8f59',
  'Personal info': '#a06d10',
  'Financial':     '#0f7a6b',
  'Free text':     '#6b6e76',
  'Often blank':   '#a73a3a',
  'Identifier':    '#2e5dff',
};

function CatSensitivity({ level }) {
  const s = CAT_SENSITIVITY[level] || CAT_SENSITIVITY['Business'];
  return (
    <span className="cat-sens">
      <span className="cat-sens-dot" style={{ background: s.c }}></span>
      {s.label}
    </span>
  );
}

function CatFieldTag({ label }) {
  const c = CAT_TAG_COLOR[label] || '#6b6e76';
  return (
    <span className="cat-tag" style={{ color: c, borderColor: c + '40', background: c + '0f' }}>{label}</span>
  );
}

function CatFieldRow({ field }) {
  return (
    <div className="cat-field">
      <div className="cat-field-main">
        <div className="cat-field-name">{field.name}</div>
        <div className="cat-field-desc">{field.desc}</div>
      </div>
      <div className="cat-field-side">
        {field.example && <span className="cat-eg"><span className="cat-eg-l">e.g.</span>{field.example}</span>}
        <div className="cat-field-tags">
          <span className="cat-type">{field.type}</span>
          {(field.tags || []).map(t => <CatFieldTag key={t} label={t} />)}
        </div>
      </div>
    </div>
  );
}

// Trust-signal helpers — derived from the audit so nothing is hand-faked.
const QUALITY_BY_TIER = {
  'Ready Now':   { label: 'Good',       c: '#1a8f59' },
  'Needs Prep':  { label: 'Needs prep', c: '#b07a18' },
  'Longer-Term': { label: 'Limited',    c: '#7a7d85' },
};
const FRESH_RANK = { 'Live': 6, 'Daily': 5, 'Weekly': 4, 'Monthly': 3, 'Quarterly': 2, 'Per deal': 1, 'As needed': 1, 'Ad hoc': 1, 'Yearly': 1, 'High volume': 6 };
const SENS_RANK  = { 'Personal': 3, 'Financial': 2, 'Business': 1, 'Public': 0 };

function freshnessOf(objects) {
  let best = null, bestRank = -1;
  objects.forEach(o => {
    const r = FRESH_RANK[o.updated] != null ? FRESH_RANK[o.updated] : 0;
    if (r > bestRank) { bestRank = r; best = o.updated; }
  });
  const c = bestRank >= 5 ? '#1a8f59' : bestRank >= 3 ? '#b07a18' : '#7a7d85';
  return { label: best || '—', c };
}
function topSensitivity(objects) {
  let best = null, bestRank = -1;
  objects.forEach(o => {
    const r = SENS_RANK[o.sensitivity] != null ? SENS_RANK[o.sensitivity] : 0;
    if (r > bestRank) { bestRank = r; best = o.sensitivity; }
  });
  const meta = CAT_SENSITIVITY[best] || CAT_SENSITIVITY['Business'];
  return { label: meta.label, c: meta.c };
}
function keyFieldsOf(objects) {
  const kf = [];
  objects.forEach(o => (o.fields || []).forEach(f => {
    if ((f.tags || []).some(t => t === 'Key detail' || t === 'AI-ready') && !kf.includes(f.name)) kf.push(f.name);
  }));
  if (kf.length < 3 && objects[0]) (objects[0].fields || []).forEach(f => { if (!kf.includes(f.name)) kf.push(f.name); });
  return kf.slice(0, 7);
}
function powersOf(objects) {
  const pw = [];
  objects.forEach(o => (o.feeds || []).forEach(f => { if (!pw.includes(f)) pw.push(f); }));
  return pw;
}

const FRESH_NOTE = {
  'Live':        'Updates in real time as records change.',
  'High volume': 'High-volume real-time updates.',
  'Daily':       'Records refresh once per day.',
  'Weekly':      'Updated once per week.',
  'Monthly':     'Refreshed at the end of each month.',
  'Quarterly':   'Updated every quarter.',
  'Per deal':    'Updated when a deal or engagement progresses.',
  'Per send':    'Updated each time a campaign is sent.',
  'Per visit':   'Refreshed with each patient or client visit.',
  'As needed':   'No regular cadence — updated when required.',
  'Ad hoc':      'No scheduled updates; refreshed manually.',
  'Yearly':      'Annual update cycle.',
};

const GOV_STYLE = {
  'Approved':       { c: '#1a8f59', bg: 'rgba(26,143,89,0.08)',  label: 'Approved' },
  'Needs setup':    { c: '#b07a18', bg: 'rgba(176,122,24,0.08)', label: 'Needs setup' },
  'Governance gap': { c: '#a73a3a', bg: 'rgba(167,58,58,0.08)',  label: 'Governance gap' },
};

const STRUCT_COLOR = {
  'Structured':      '#1a8f59',
  'Semi-structured': '#b07a18',
  'Unstructured':    '#5e6068',
};

const ACCESS_LABEL = {
  'Cloud':   'Cloud-hosted',
  'On-prem': 'On-premise only',
  'Hybrid':  'Cloud + on-premise',
  'Files':   'File-based (local)',
  'Hybrid':  'Cloud + on-premise',
};

function DataFactSignal({ label, value, dot, note }) {
  return (
    <div className="dfs-sig">
      <div className="dfs-sig-l">{label}</div>
      <div className="dfs-sig-v">{dot && <span className="dfs-dot" style={{ background: dot }}></span>}{value}</div>
      {note && <div className="dfs-sig-note">{note}</div>}
    </div>
  );
}

function DfsSysTraits({ system }) {
  const gov = GOV_STYLE[system.governance];
  const structColor = STRUCT_COLOR[system.dataStructure] || '#5e6068';
  const accessLabel = ACCESS_LABEL[system.location] || system.location;
  return (
    <div className="dfs-traits">
      <div className="dfs-trait">
        <div className="dfs-trait-l">Format</div>
        <div className="dfs-trait-v">{system.format || '—'}</div>
      </div>
      <div className="dfs-trait">
        <div className="dfs-trait-l">Accessibility</div>
        <div className="dfs-trait-v">{accessLabel || '—'}</div>
      </div>
      {system.dataStructure && (
        <div className="dfs-trait">
          <div className="dfs-trait-l">Data structure</div>
          <div className="dfs-trait-v" style={{ color: structColor, fontWeight: 500 }}>{system.dataStructure}</div>
        </div>
      )}
      {gov && (
        <div className="dfs-trait">
          <div className="dfs-trait-l">Governance</div>
          <div className="dfs-trait-v">
            <span style={{ display: 'inline-flex', alignItems: 'center', gap: 5, color: gov.c, background: gov.bg, borderRadius: 20, padding: '2px 9px', fontSize: 12, fontWeight: 500 }}>
              <span style={{ width: 5, height: 5, borderRadius: '50%', background: gov.c, flexShrink: 0 }}></span>
              {gov.label}
            </span>
          </div>
        </div>
      )}
    </div>
  );
}

// System fact sheet — plain-language system profile that drills into a record type.
function DataCatalogOverlay({ system, catalog, initialObject, onClose }) {
  const objects = (catalog && catalog.objects) || [];
  const [sel, setSel] = useStateD(() => {
    if (initialObject) {
      const i = objects.findIndex(o => o.name === initialObject);
      return i >= 0 ? i : null;
    }
    return null;
  });

  useEffectD(() => {
    const onKey = (e) => { if (e.key === 'Escape') onClose(); };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [onClose]);

  const quality = QUALITY_BY_TIER[system.tier] || QUALITY_BY_TIER['Needs Prep'];
  const fresh = freshnessOf(objects);
  const sens = topSensitivity(objects);
  const keyFields = keyFieldsOf(objects);
  const powers = powersOf(objects);

  const active = sel != null ? objects[sel] : null;
  const feeds = (active && active.feeds) || [];

  return ReactDOM.createPortal((
    <div className="cat-overlay-root">
      <div className="cat-backdrop" onClick={onClose}></div>
      <div className="cat-overlay" role="dialog" aria-label={system.name + ' system fact sheet'}>
        <div className="cat-head">
          <div className="cat-head-left">
            <button className="cat-back" onClick={onClose}><IconChevronLeft size={15}/>Back to audit</button>
            <div className="cat-head-title">
              {LOGO_MAP[system.name] && (
                <img src={LOGO_MAP[system.name]} alt={system.name} width={26} height={26}
                  style={{ objectFit: 'contain', filter: 'brightness(0) opacity(0.83)' }}
                  onError={e => { e.currentTarget.style.display = 'none'; }} />
              )}
              <div>
                <div className="kicker">System fact sheet · {system.category}</div>
                <h2 className="cat-h2">{system.name}</h2>
              </div>
            </div>
          </div>
          <button className="icon-btn" onClick={onClose}><IconX size={18}/></button>
        </div>

        <div className="dfs-scroll">
          {objects.length === 0 ? (
            <div className="cat-empty">
              <div className="cat-empty-icon"><IconDatabase size={26}/></div>
              <div className="cat-empty-h">No structured records to browse</div>
              <p className="cat-empty-p">{(catalog && catalog.note) || 'This system stores loose documents rather than structured records, so there is nothing to catalog field by field.'}</p>
            </div>
          ) : active ? (
            <div className="dfs-detail">
              <button className="cat-back" style={{ marginBottom: 16 }} onClick={() => setSel(null)}><IconChevronLeft size={14}/>Back to {system.name} overview</button>
              <div className="dfs-detail-head">
                <div>
                  <h3 className="cat-obj-h">{active.name}</h3>
                  <p className="cat-obj-desc">{active.blurb}</p>
                </div>
                <div className="dfs-detail-stats">
                  <div style={{ fontSize: 11.5, color: 'var(--ink-3)' }}>{active.records} records · {active.updated}</div>
                  <div style={{ marginTop: 7 }}><CatSensitivity level={active.sensitivity}/></div>
                </div>
              </div>
              {feeds.length > 0 && (
                <div className="cat-feeds">
                  <span className="cat-feeds-l">Used in these workflows</span>
                  <div className="cat-feeds-chips">{feeds.map(f => <span key={f} className="cat-feed-chip">{f}</span>)}</div>
                </div>
              )}
              <div className="cat-fields-label">Details captured <span>{(active.fields || []).length}</span></div>
              <div className="cat-fields">
                {(active.fields || []).map(f => <CatFieldRow key={f.name} field={f} />)}
              </div>
            </div>
          ) : (
            <div className="dfs">
              <p className="dfs-summary">{catalog && catalog.summary}</p>
              <div className="dfs-signals">
                <DataFactSignal label="Data quality" value={quality.label} dot={quality.c}/>
                <DataFactSignal label="Freshness" value={fresh.label} dot={fresh.c} note={FRESH_NOTE[fresh.label]}/>
                <DataFactSignal label="Owned by" value={system.owner}/>
                <DataFactSignal label="Sensitivity" value={sens.label} dot={sens.c}/>
              </div>
              <DfsSysTraits system={system}/>
              <div className="dfs-cols">
                <div>
                  <div className="dfs-block-l">What it holds <span className="dfs-block-note">· open one to see its details</span></div>
                  <div className="dfs-rt">
                    {objects.map((o, i) => (
                      <button key={o.name} className="dfs-rt-row" onClick={() => setSel(i)}>
                        <div><div className="dfs-rt-n">{o.name}</div><div className="dfs-rt-b">{o.blurb}</div></div>
                        <div className="dfs-rt-right"><span className="dfs-rt-c">{o.records}</span><span className="dfs-rt-chev"><IconArrowRight size={13}/></span></div>
                      </button>
                    ))}
                  </div>
                </div>
                <div>
                  <div className="dfs-block-l">Key information captured</div>
                  <div className="dfs-pills">{keyFields.map(f => <span className="dfs-pill" key={f}>{f}</span>)}</div>
                  {powers.length > 0 && (
                    <>
                      <div className="dfs-block-l" style={{ marginTop: 22 }}>What it powers</div>
                      <div className="dfs-powers">{powers.map(p => <span className="cat-feed-chip" key={p}>{p}</span>)}</div>
                    </>
                  )}
                </div>
              </div>
            </div>
          )}
        </div>
      </div>
    </div>
  ), document.body);
}

function DataDeptColumn({ dept, items, showLogos, onSelect }) {
  const readyNow = items.filter(s => s.tier === 'Ready Now').length;
  const pct = items.length ? Math.round((readyNow / items.length) * 100) : 0;
  return (
    <div className="inv-col">
      <div className="inv-col-head">
        <div className="inv-col-title">{dept}</div>
        <div className="inv-col-meta">
          <span>{items.length} {items.length === 1 ? 'system' : 'systems'}</span>
        </div>
        <div className="inv-col-bar">
          <div className="inv-col-bar-fill" style={{width: pct + '%'}}></div>
        </div>
        <div className="inv-col-pct">{readyNow} of {items.length} ready now</div>
      </div>
      <div className="inv-col-body">
        {items.map((s, i) => <DataSystemCard key={s.name} source={s} showLogos={showLogos} onSelect={onSelect} delay={i * 40}/>)}
      </div>
    </div>
  );
}

function DataSystemCard({ source: s, showLogos, onSelect, delay = 0 }) {
  const bandKey = s.tier === 'Ready Now' ? 'ready' : s.tier === 'Needs Prep' ? 'near' : 'disc';
  return (
    <button
      className={'inv-card inv-card--' + bandKey}
      data-sys={s.name}
      style={{animationDelay: delay + 'ms', width: '100%', textAlign: 'left'}}
      onClick={() => onSelect && onSelect(s)}
    >
      <div className="inv-card-top">
        <div style={{display:'flex', alignItems:'center', gap:6}}>
          {showLogos && <SoftwareLogo name={s.name} size={14}/>}
          <span className="inv-card-name">{s.name}</span>
        </div>
      </div>
      <div className="inv-card-meta">
        <span>{s.category}</span>
        <span className="dot-sep">·</span>
        <span className="inv-card-status">{s.format}</span>
      </div>
      <TierPill tier={s.tier}/>
    </button>
  );
}

function DataInventoryBoard({ sources, onSelect }) {
  // Group key: dept if available (newer data files), else category (legacy)
  const keyOf = s => s.dept || s.category;
  // Order columns to follow the workflow department order, then append extras
  const wfDeptOrder = Array.from(new Set((window.WORKFLOWS || []).map(w => w.dept)));
  const dataDepts   = Array.from(new Set(sources.map(keyOf).filter(Boolean)));
  const deptOrder   = [
    ...wfDeptOrder.filter(d => dataDepts.includes(d)),
    ...dataDepts.filter(d => !wfDeptOrder.includes(d)),
  ];
  const byDept = {};
  deptOrder.forEach(d => { byDept[d] = []; });
  sources.forEach(s => { const k = keyOf(s); if (k && byDept[k]) byDept[k].push(s); });

  const total = sources.length;
  const readyNow = sources.filter(s => s.tier === 'Ready Now').length;
  const needsPrep = sources.filter(s => s.tier === 'Needs Prep').length;
  const longerTerm = sources.filter(s => s.tier === 'Longer-Term').length;
  const overallPct = total ? Math.round((readyNow / total) * 100) : 0;

  const showLogos = window.REPORT_CONFIG && window.REPORT_CONFIG.dataReadiness
    ? window.REPORT_CONFIG.dataReadiness.showLogos !== false
    : true;

  const scrollRef = useRefD(null);
  const gridRef   = useRefD(null);
  const [scrollInfo, setScrollInfo] = useStateD({ left: 0, scrollWidth: 1, clientWidth: 1 });
  const [showFlows, setShowFlows]   = useStateD(false);
  const [flowPos, setFlowPos]       = useStateD({});
  const [flowSize, setFlowSize]     = useStateD({ w: 0, h: 0 });
  const [hovNode, setHovNode]       = useStateD(null);

  useEffectD(() => {
    const el = scrollRef.current;
    if (!el) return;
    const update = () => setScrollInfo({ left: el.scrollLeft, scrollWidth: el.scrollWidth, clientWidth: el.clientWidth });
    update();
    el.addEventListener('scroll', update, { passive: true });
    const ro = new ResizeObserver(update);
    ro.observe(el);
    return () => { el.removeEventListener('scroll', update); ro.disconnect(); };
  }, []);

  // Measure card positions whenever showFlows turns on or sources change
  useEffectD(() => {
    if (!showFlows || !gridRef.current) return;
    const grid = gridRef.current;
    const t = setTimeout(() => {
      const base = grid.getBoundingClientRect();
      const pos = {};
      grid.querySelectorAll('[data-sys]').forEach(el => {
        const r = el.getBoundingClientRect();
        pos[el.getAttribute('data-sys')] = {
          cx: r.left - base.left + r.width / 2,
          cy: r.top - base.top + r.height / 2,
        };
      });
      setFlowPos(pos);
      setFlowSize({ w: grid.scrollWidth, h: grid.scrollHeight });
    }, 60);
    return () => clearTimeout(t);
  }, [showFlows, sources]);

  // Build connection edges from workflow dependencies
  const flowEdges = useMemoD(() => {
    if (!showFlows || !Object.keys(flowPos).length) return [];
    const map = {};
    (window.WORKFLOWS || []).forEach(w => {
      const deps = (w.dependsOn || []).filter(n => flowPos[n]);
      for (let i = 0; i < deps.length; i++) {
        for (let j = i + 1; j < deps.length; j++) {
          const key = [deps[i], deps[j]].sort().join('|||');
          if (!map[key]) map[key] = { a: deps[i], b: deps[j], wfs: [] };
          if (!map[key].wfs.includes(w.name)) map[key].wfs.push(w.name);
        }
      }
    });
    return Object.values(map);
  }, [showFlows, flowPos]);

  // S-curve path between two card centers
  const flowPath = (a, b) => {
    const pa = flowPos[a], pb = flowPos[b];
    if (!pa || !pb) return null;
    const mx = (pa.cx + pb.cx) / 2;
    return `M${pa.cx},${pa.cy} C${mx},${pa.cy} ${mx},${pb.cy} ${pb.cx},${pb.cy}`;
  };

  const maxScroll = Math.max(0, scrollInfo.scrollWidth - scrollInfo.clientWidth);
  const canLeft = scrollInfo.left > 2;
  const canRight = scrollInfo.left < maxScroll - 2;
  const thumbWPct = scrollInfo.scrollWidth > 0 ? Math.max(10, (scrollInfo.clientWidth / scrollInfo.scrollWidth) * 100) : 100;
  const thumbLeftPct = maxScroll > 0 ? (scrollInfo.left / maxScroll) * (100 - thumbWPct) : 0;
  const scrollBy = (dir) => { if (scrollRef.current) scrollRef.current.scrollBy({ left: dir * 250, behavior: 'smooth' }); };

  return (
    <div className="inv-board">
      <div className="inv-objective">
        <div className="inv-objective-left">
          <div className="kicker">Data infrastructure overview</div>
          <h3 className="inv-objective-h">Systems organized <em>by business unit</em>.</h3>
          <p className="inv-objective-p">All audited systems grouped by the business unit that owns them. Green means ready to connect to an AI workflow immediately. Amber requires preparation work. Gray requires longer-term investment.</p>
          <button className={'ds-flow-btn' + (showFlows ? ' is-active' : '')}
            onClick={() => { setShowFlows(f => !f); if (showFlows) { setHovNode(null); } }}>
            <span className="ds-flow-btn-dot"></span>
            {showFlows ? 'Hide connections' : 'Show connections'}
          </button>
        </div>
        <div className="inv-objective-right">
          <div className="inv-prog">
            <div className="inv-prog-track">
              <div className="inv-prog-fill" style={{width: overallPct + '%'}}></div>
            </div>
            <div className="inv-prog-meta">
              <span className="serif-num" style={{fontSize:32, color:'var(--ink-0)', lineHeight:1}}>{readyNow}<span style={{color:'var(--ink-3)', fontSize:18}}>/{total}</span></span>
              <span className="inv-prog-l">systems ready now</span>
            </div>
          </div>
          <div className="inv-tally">
            <span><span className="legend-dot" style={{background:'#1a8f59'}}></span>{readyNow} ready now</span>
            <span><span className="legend-dot" style={{background:'#b07a18'}}></span>{needsPrep} needs prep</span>
            <span><span className="legend-dot" style={{background:'#7a7d85'}}></span>{longerTerm} longer-term</span>
          </div>
        </div>
      </div>

      <div className="inv-grid-wrap">
        <div className="inv-grid-scroll" ref={scrollRef}>
          <div className="inv-grid"
            ref={gridRef}
            style={{gridTemplateColumns: `repeat(${deptOrder.length}, 220px)`, position: 'relative'}}
            onMouseOver={showFlows ? (e => { const c = e.target.closest('[data-sys]'); setHovNode(c ? c.getAttribute('data-sys') : null); }) : undefined}
            onMouseLeave={showFlows ? (() => setHovNode(null)) : undefined}
          >
            {deptOrder.map(dept => (
              <DataDeptColumn key={dept} dept={dept} items={byDept[dept]} showLogos={showLogos} onSelect={onSelect}/>
            ))}

            {/* Connection overlay */}
            {showFlows && flowSize.w > 0 && (
              <svg style={{
                position: 'absolute', top: 0, left: 0, pointerEvents: 'none',
                width: flowSize.w, height: flowSize.h, overflow: 'visible',
              }}>
                {flowEdges.map(e => {
                  const key = [e.a, e.b].sort().join('|||');
                  const d = flowPath(e.a, e.b);
                  if (!d) return null;
                  const isConn = hovNode && (e.a === hovNode || e.b === hovNode);
                  const dim    = hovNode && !isConn;
                  return (
                    <path key={key} d={d} fill="none"
                      stroke={isConn ? '#2e5dff' : 'rgba(10,10,10,0.22)'}
                      strokeWidth={isConn ? 2 : 1.5}
                      strokeDasharray={isConn ? 'none' : '5 4'}
                      opacity={dim ? 0.06 : isConn ? 1 : 0.45}
                      style={{transition:'opacity 120ms,stroke 120ms'}}
                    />
                  );
                })}
              </svg>
            )}
          </div>
        </div>

        {maxScroll > 4 && (
          <div className="inv-scroll-nav">
            <button className="inv-scroll-btn" onClick={() => scrollBy(-1)} disabled={!canLeft} aria-label="Scroll left">&#8249;</button>
            <div className="inv-scroll-track">
              <div className="inv-scroll-thumb" style={{left: thumbLeftPct + '%', width: thumbWPct + '%'}}></div>
            </div>
            <button className="inv-scroll-btn" onClick={() => scrollBy(1)} disabled={!canRight} aria-label="Scroll right">&#8250;</button>
          </div>
        )}
      </div>
    </div>
  );
}

function DataView() {
  const all = window.DATA_SOURCES;
  const [tab, setTab] = useStateD('table');
  const [tier, setTier] = useStateD('All');
  const [cat, setCat] = useStateD('All');
  const [q, setQ] = useStateD('');
  const [sortKey, setSortKey] = useStateD('tier');
  const [sortDir, setSortDir] = useStateD('asc');
  const [active, setActive] = useStateD(null);
  const [catalog, setCatalog] = useStateD(null); // { system, object } | null

  const showLogos = window.REPORT_CONFIG && window.REPORT_CONFIG.dataReadiness
    ? window.REPORT_CONFIG.dataReadiness.showLogos !== false
    : true;

  const enhanced = window.REPORT_CONFIG && window.REPORT_CONFIG.dataReadiness
    ? window.REPORT_CONFIG.dataReadiness.enhanced === true
    : false;

  const tiers = ['All', 'Ready Now', 'Needs Prep', 'Longer-Term'];
  const cats = useMemoD(() => ['All', ...Array.from(new Set(all.map(s => s.category)))], [all]);

  const tierOrder = { 'Ready Now': 0, 'Needs Prep': 1, 'Longer-Term': 2 };

  const rows = useMemoD(() => {
    let r = all.filter(s =>
      (tier === 'All' || s.tier === tier) &&
      (cat === 'All' || s.category === cat) &&
      (q === '' || (s.name + s.owner + (s.purpose || '')).toLowerCase().includes(q.toLowerCase()))
    );
    r = [...r].sort((a, b) => {
      let av = a[sortKey], bv = b[sortKey];
      if (sortKey === 'tier') { av = tierOrder[a.tier]; bv = tierOrder[b.tier]; }
      if (typeof av === 'string') return sortDir === 'asc' ? av.localeCompare(bv) : bv.localeCompare(av);
      return sortDir === 'asc' ? av - bv : bv - av;
    });
    return r;
  }, [all, tier, cat, q, sortKey, sortDir]);

  const counts = useMemoD(() => {
    const c = { 'Ready Now': 0, 'Needs Prep': 0, 'Longer-Term': 0 };
    all.forEach(s => { c[s.tier]++; });
    return c;
  }, [all]);

  const toggleSort = (k) => {
    if (sortKey === k) setSortDir(d => d === 'asc' ? 'desc' : 'asc');
    else { setSortKey(k); setSortDir('asc'); }
  };

  const SortHead = ({ k, children, align }) => (
    <th onClick={() => toggleSort(k)} style={{textAlign: align || 'left', cursor:'pointer'}}>
      <span className="th-inner">
        {children}
        {sortKey === k && (sortDir === 'asc' ? <IconChevronUp size={11}/> : <IconChevronDown size={11}/>)}
      </span>
    </th>
  );

  const usedBy = active ? (window.WORKFLOWS || []).filter(w => (w.dependsOn || []).includes(active.name)) : [];
  const connectedNames = new Set();
  usedBy.forEach(w => (w.dependsOn || []).forEach(n => { if (n !== (active && active.name)) connectedNames.add(n); }));
  const connectedSystems = Array.from(connectedNames).map(n => (window.DATA_SOURCES || []).find(d => d.name === n)).filter(Boolean);

  const activeCatalog = active && window.DATA_OBJECTS ? window.DATA_OBJECTS[active.name] : null;

  return (
    <div className="view data-view">
      <div className="page-head">
        <div>
          <div className="kicker">Section II</div>
          <h1 className="page-title">Data & Systems Readiness</h1>
          <p className="page-lede">{all.length} system{all.length !== 1 ? 's' : ''} audited across {window.CLIENT ? window.CLIENT.shortName || window.CLIENT.name : 'the organisation'}. Each is classified by how quickly it can support AI workloads as-is.</p>
        </div>
        <div className="tier-summary">
          <div className="tier-summary-item">
            <div className="ts-num serif-num" style={{color:'#1a8f59'}}>{counts['Ready Now']}</div>
            <div className="ts-l">Ready now</div>
          </div>
          <div className="tier-summary-item">
            <div className="ts-num serif-num" style={{color:'#a06d10'}}>{counts['Needs Prep']}</div>
            <div className="ts-l">Needs prep</div>
          </div>
          <div className="tier-summary-item">
            <div className="ts-num serif-num" style={{color:'#5e6068'}}>{counts['Longer-Term']}</div>
            <div className="ts-l">Longer-term</div>
          </div>
        </div>
      </div>

      <div className="dv-controls">
        <div className="seg">
          <button className={tab === 'table' ? 'is-active' : ''} onClick={() => setTab('table')}>
            <IconTable size={13}/>Table
          </button>
          <button className={tab === 'inventory' ? 'is-active' : ''} onClick={() => setTab('inventory')}>
            <IconLayers size={13}/>Inventory
          </button>
        </div>

        {tab === 'table' && (
          <>
            <div className="filter-group">
              <span className="filter-label">Tier</span>
              {tiers.map(t => (
                <button key={t} className={"chip-btn" + (tier === t ? ' is-active' : '')}
                  onClick={() => setTier(t)}>{t}</button>
              ))}
            </div>
            <div className="filter-group">
              <span className="filter-label">Category</span>
              <div className="select-wrap">
                <select value={cat} onChange={e => setCat(e.target.value)}>
                  {cats.map(c => <option key={c} value={c}>{c}</option>)}
                </select>
                <IconChevronDown size={12}/>
              </div>
            </div>
            <div className="search-wrap">
              <IconSearch size={13}/>
              <input placeholder="Search systems or owners" value={q} onChange={e => setQ(e.target.value)}/>
            </div>
          </>
        )}
      </div>

      {tab === 'table' && (
        <div className="table-wrap">
          <table className="data-table">
            <thead>
              <tr>
                <SortHead k="name">System</SortHead>
                <th className="col-logo"></th>
                <SortHead k="purpose">Purpose</SortHead>
                <SortHead k="owner">Owner</SortHead>
                <SortHead k="category">Category</SortHead>
                <SortHead k="format">Format</SortHead>
                <SortHead k="location">Location</SortHead>
                <SortHead k="tier">Tier</SortHead>
                <th></th>
              </tr>
            </thead>
            <tbody>
              {rows.map((s) => (
                <tr key={s.name} onClick={() => setActive(s)} className={active && active.name === s.name ? 'is-active' : ''}>
                  <td className="cell-strong">{s.name}</td>
                  <td className="cell-logo">{showLogos && <SoftwareLogo name={s.name} size={18}/>}</td>
                  <td className="cell-soft">{s.purpose}</td>
                  <td className="cell-soft">{s.owner}</td>
                  <td className="cell-soft">{s.category}</td>
                  <td className="cell-soft">{s.format}</td>
                  <td className="cell-soft">{s.location}</td>
                  <td><TierPill tier={s.tier}/></td>
                  <td className="cell-arrow"><IconArrowRight size={13}/></td>
                </tr>
              ))}
            </tbody>
          </table>
          {rows.length === 0 && <div className="empty">No systems match these filters.</div>}
        </div>
      )}

      {tab === 'inventory' && <DataInventoryBoard sources={all} onSelect={(s) => { setActive(s); setCatalog(null); }} />}

      {active && (
        <>
          <div className="side-backdrop" onClick={() => setActive(null)}></div>
          <aside className={enhanced ? 'side-panel side-panel--enhanced' : 'side-panel'}>
            <div className="side-head">
              <div>
                <div className="kicker">{active.category}</div>
                <div style={{display:'flex', alignItems:'center', gap:10, marginTop:6}}>
                  {LOGO_MAP[active.name] && (
                    <img
                      src={LOGO_MAP[active.name]}
                      alt={active.name}
                      width={28}
                      height={28}
                      style={{
                        objectFit: 'contain', flexShrink: 0,
                        filter: 'brightness(0) opacity(0.83)',
                      }}
                      onError={e => { e.currentTarget.style.display = 'none'; }}
                    />
                  )}
                  <h3 className="side-title" style={{margin:0}}>{active.name}</h3>
                </div>
              </div>
              <button className="icon-btn" onClick={() => setActive(null)}><IconX size={16}/></button>
            </div>
            <div className="side-meta">
              <div><span>Purpose</span><b>{active.purpose}</b></div>
              <div><span>Owner</span><b>{active.owner}</b></div>
              <div><span>Format</span><b>{active.format}</b></div>
              <div><span>Location</span><b>{active.location}</b></div>
              {active.dataStructure && (
                <div><span>Data structure</span><DataStructureTag value={active.dataStructure}/></div>
              )}
              {active.governance && (
                <div><span>Access governance</span><GovernanceChip status={active.governance}/></div>
              )}
              <div><span>Tier</span><TierPill tier={active.tier}/></div>
            </div>

            {activeCatalog && (
              <div className="side-section">
                <div className="kicker">Information held in this system</div>
                {activeCatalog.objects && activeCatalog.objects.length > 0 ? (
                  <>
                    <div className="side-obj-list">
                      {activeCatalog.objects.map(o => (
                        <button key={o.name} className="side-obj" onClick={() => setCatalog({ system: active, object: o.name })}>
                          <div className="side-obj-l">
                            <div className="side-obj-name">{o.name}</div>
                            <div className="side-obj-blurb">{o.blurb}</div>
                          </div>
                          <div className="side-obj-r">
                            <span className="side-obj-count">{o.records}</span>
                            <IconArrowRight size={13}/>
                          </div>
                        </button>
                      ))}
                    </div>
                    <button className="side-cta" onClick={() => setCatalog({ system: active, object: null })}>
                      Open system fact sheet<IconArrowRight size={14}/>
                    </button>
                  </>
                ) : (
                  <p className="side-body">{activeCatalog.note}</p>
                )}
              </div>
            )}

            {!enhanced && active.recordOf && (
              <div className="side-section">
                <div className="kicker">System of record for</div>
                <p className="side-body">{active.recordOf}</p>
              </div>
            )}
            {!enhanced && (
              <div className="side-section">
                <div className="kicker">Finding</div>
                <p className="side-body">{active.finding}</p>
              </div>
            )}

            {enhanced && (
              <div className="side-section">
                <div className="kicker">Data stored in this system</div>
                <div className="enh-data-chips">
                  {(active.recordOf || '').split(',').map(item => item.trim()).filter(Boolean).map(item => (
                    <span key={item} className="enh-chip">{item}</span>
                  ))}
                </div>
                {active.finding && <p className="side-body" style={{marginTop:10}}>{active.finding}</p>}
              </div>
            )}

            {enhanced && usedBy.length > 0 && (
              <div className="side-section">
                <div className="kicker">Used by workflows ({usedBy.length})</div>
                <div className="enh-wf-list">
                  {usedBy.map(w => (
                    <div key={w.id} className="enh-wf-row">
                      <div className="enh-wf-name">{w.name}</div>
                      <div className="enh-wf-meta">{w.dept} · {w.hours.toLocaleString()} hrs/yr</div>
                    </div>
                  ))}
                </div>
              </div>
            )}

            {enhanced && connectedSystems.length > 0 && (
              <div className="side-section">
                <div className="kicker">Connected systems</div>
                <div className="enh-sys-list">
                  {connectedSystems.map(s => (
                    <div key={s.name} className="enh-sys-row">
                      <SoftwareLogo name={s.name} size={16}/>
                      <span className="enh-sys-name">{s.name}</span>
                      <TierPill tier={s.tier}/>
                    </div>
                  ))}
                </div>
              </div>
            )}

          </aside>
        </>
      )}
      {catalog && (
        <DataCatalogOverlay
          system={catalog.system}
          catalog={window.DATA_OBJECTS ? window.DATA_OBJECTS[catalog.system.name] : null}
          initialObject={catalog.object}
          onClose={() => setCatalog(null)}
        />
      )}
    </div>
  );
}

window.DataView = DataView;
