/* Pedigree Map (Screen E1) — Sankey + Bubble views */
const { useState, useMemo, useCallback, useRef, useEffect } = React;

/* ═══════ DATA AGGREGATION ═══════ */
function aggregatePedigree(members) {
  var ok = members.filter(function (m) { return m.status === 'ok'; });
  var withPedigree = ok.filter(function (m) { return m.pedigree; });
  var schoolCounts = {}, employerCounts = {};
  var flows = {}; /* "school|employer" → { count, people:[] } */
  var schoolDirect = {}; /* school → xAI (no employer known) */
  var employerDirect = {}; /* employer → xAI (no school known) */
  var noPedigree = ok.length - withPedigree.length;
  var noSchoolNoEmployer = 0;

  withPedigree.forEach(function (m) {
    var p = m.pedigree;
    var schools = p.schools || [];
    var employers = p.previousEmployers || [];
    schools.forEach(function (s) { schoolCounts[s] = (schoolCounts[s] || 0) + 1; });
    employers.forEach(function (e) { employerCounts[e] = (employerCounts[e] || 0) + 1; });

    if (schools.length > 0 && employers.length > 0) {
      schools.forEach(function (s) {
        employers.forEach(function (e) {
          var k = s + '|' + e;
          if (!flows[k]) flows[k] = { school: s, employer: e, count: 0, people: [] };
          flows[k].count++;
          flows[k].people.push(m);
        });
      });
    } else if (schools.length > 0) {
      schools.forEach(function (s) {
        if (!schoolDirect[s]) schoolDirect[s] = { count: 0, people: [] };
        schoolDirect[s].count++;
        schoolDirect[s].people.push(m);
      });
    } else if (employers.length > 0) {
      employers.forEach(function (e) {
        if (!employerDirect[e]) employerDirect[e] = { count: 0, people: [] };
        employerDirect[e].count++;
        employerDirect[e].people.push(m);
      });
    } else {
      noSchoolNoEmployer++;
    }
  });

  var topSchools = Object.entries(schoolCounts).sort(function (a, b) { return b[1] - a[1]; }).slice(0, 15);
  var topEmployers = Object.entries(employerCounts).sort(function (a, b) { return b[1] - a[1]; }).slice(0, 15);

  return { topSchools: topSchools, topEmployers: topEmployers, flows: flows, schoolDirect: schoolDirect, employerDirect: employerDirect, noPedigree: noPedigree, noSchoolNoEmployer: noSchoolNoEmployer, totalOk: ok.length, withPedigreeCount: withPedigree.length };
}

/* ═══════ SANKEY VIEW ═══════ */
function SankeyView({ data, onSelectOrg }) {
  var [hovered, setHovered] = useState(null); /* { type:'school'|'employer', id } */
  var svgW = 780, svgH = 520;
  var colX = [30, 360, 710];
  var nodeW = 14;
  var labels = window.ORG_LABELS || {};
  var label = function (id) { return labels[id] || id.replace('@', ''); };

  /* Layout nodes */
  var gap = 6, topPad = 30;
  var availH = svgH - topPad - 20;

  var schoolNodes = useMemo(function () {
    var total = data.topSchools.reduce(function (s, e) { return s + e[1]; }, 0) || 1;
    var y = topPad;
    return data.topSchools.map(function (e) {
      var h = Math.max(8, (e[1] / total) * (availH - data.topSchools.length * gap));
      var node = { id: e[0], count: e[1], x: colX[0], y: y, h: h };
      y += h + gap;
      return node;
    });
  }, [data]);

  var employerNodes = useMemo(function () {
    var total = data.topEmployers.reduce(function (s, e) { return s + e[1]; }, 0) || 1;
    var y = topPad;
    return data.topEmployers.map(function (e) {
      var h = Math.max(8, (e[1] / total) * (availH - data.topEmployers.length * gap));
      var node = { id: e[0], count: e[1], x: colX[1], y: y, h: h };
      y += h + gap;
      return node;
    });
  }, [data]);

  var xaiNode = { id: '@xai', x: colX[2], y: topPad, h: availH * 0.7 };

  /* Build links */
  var links = useMemo(function () {
    var result = [];
    var schoolPorts = {}, employerPortsL = {}, employerPortsR = {};
    schoolNodes.forEach(function (n) { schoolPorts[n.id] = { y: n.y, remain: n.h }; });
    employerNodes.forEach(function (n) { employerPortsL[n.id] = { y: n.y, remain: n.h }; employerPortsR[n.id] = { y: n.y, remain: n.h }; });

    var maxFlow = 1;
    Object.values(data.flows).forEach(function (f) { if (f.count > maxFlow) maxFlow = f.count; });

    /* school → employer links */
    Object.values(data.flows).forEach(function (f) {
      var sp = schoolPorts[f.school];
      var ep = employerPortsL[f.employer];
      if (!sp || !ep) return;
      var thickness = Math.max(2, (f.count / maxFlow) * 18);
      result.push({ from: f.school, to: f.employer, type: 'school-employer', y1: sp.y + (sp.remain - thickness) / 2, y2: ep.y + (ep.remain - thickness) / 2, x1: colX[0] + nodeW, x2: colX[1], thickness: thickness, count: f.count, people: f.people });
      sp.y += thickness + 1;
      sp.remain -= thickness + 1;
      ep.y += thickness + 1;
      ep.remain -= thickness + 1;
    });

    /* employer → xAI links */
    var xaiY = xaiNode.y;
    employerNodes.forEach(function (n) {
      var ep = employerPortsR[n.id];
      if (!ep) return;
      var thickness = Math.max(2, (n.count / (data.topEmployers[0] ? data.topEmployers[0][1] : 1)) * 16);
      result.push({ from: n.id, to: '@xai', type: 'employer-xai', y1: n.y + n.h / 2 - thickness / 2, y2: xaiY, x1: colX[1] + nodeW, x2: colX[2], thickness: thickness, count: n.count });
      xaiY += thickness + 2;
    });

    return result;
  }, [data, schoolNodes, employerNodes]);

  function isHighlighted(nodeId) {
    if (!hovered) return true;
    if (hovered.id === nodeId) return true;
    return links.some(function (l) { return (l.from === hovered.id && l.to === nodeId) || (l.from === nodeId && l.to === hovered.id); });
  }

  function linkOpacity(link) {
    if (!hovered) return 0.35;
    if (link.from === hovered.id || link.to === hovered.id) return 0.65;
    return 0.06;
  }

  function bezierPath(x1, y1, x2, y2, t) {
    var mx = (x1 + x2) / 2;
    return 'M ' + x1 + ' ' + y1 + ' C ' + mx + ' ' + y1 + ', ' + mx + ' ' + y2 + ', ' + x2 + ' ' + y2;
  }

  return (
    <svg viewBox={'0 0 ' + svgW + ' ' + svgH} style={{ width: '100%', maxWidth: svgW, display: 'block' }}>
      {/* Column labels */}
      <text x={colX[0]} y={16} fill="var(--text-tertiary)" fontSize="11" fontWeight="600" fontFamily="var(--sans)">SCHOOLS</text>
      <text x={colX[1]} y={16} fill="var(--text-tertiary)" fontSize="11" fontWeight="600" fontFamily="var(--sans)">PREVIOUS EMPLOYERS</text>
      <text x={colX[2]} y={16} fill="var(--text-tertiary)" fontSize="11" fontWeight="600" fontFamily="var(--sans)">CURRENT</text>

      {/* Links */}
      {links.map(function (l, i) {
        var p1 = bezierPath(l.x1, l.y1 + l.thickness / 2, l.x2, l.y2 + l.thickness / 2, l.thickness);
        return <path key={i} d={p1} fill="none" stroke={l.type === 'school-employer' ? 'rgba(255,255,255,0.6)' : 'var(--accent)'} strokeWidth={l.thickness} strokeOpacity={linkOpacity(l)} style={{ transition: 'stroke-opacity .2s' }} />;
      })}

      {/* School nodes */}
      {schoolNodes.map(function (n) {
        var hi = isHighlighted(n.id);
        return (
          <g key={n.id} style={{ cursor: 'pointer', opacity: hi ? 1 : 0.25, transition: 'opacity .2s' }}
            onMouseEnter={function () { setHovered({ type: 'school', id: n.id }); }}
            onMouseLeave={function () { setHovered(null); }}
            onClick={function () { onSelectOrg && onSelectOrg(n.id, 'school'); }}>
            <rect x={n.x} y={n.y} width={nodeW} height={n.h} rx={3} fill="rgba(255,255,255,0.7)" opacity={0.8} />
            <text x={n.x + nodeW + 6} y={n.y + n.h / 2 + 4} fill="var(--text-secondary)" fontSize="11" fontFamily="var(--sans)">{label(n.id)}</text>
            <text x={n.x + nodeW + 6 + label(n.id).length * 6 + 6} y={n.y + n.h / 2 + 4} fill="var(--text-tertiary)" fontSize="10" fontFamily="var(--mono)">{n.count}</text>
          </g>
        );
      })}

      {/* Employer nodes */}
      {employerNodes.map(function (n) {
        var hi = isHighlighted(n.id);
        return (
          <g key={n.id} style={{ cursor: 'pointer', opacity: hi ? 1 : 0.25, transition: 'opacity .2s' }}
            onMouseEnter={function () { setHovered({ type: 'employer', id: n.id }); }}
            onMouseLeave={function () { setHovered(null); }}
            onClick={function () { onSelectOrg && onSelectOrg(n.id, 'employer'); }}>
            <rect x={n.x} y={n.y} width={nodeW} height={n.h} rx={3} fill="var(--accent)" opacity={0.7} />
            <text x={n.x + nodeW + 6} y={n.y + n.h / 2 + 4} fill="var(--text-secondary)" fontSize="11" fontFamily="var(--sans)">{label(n.id)}</text>
            <text x={n.x + nodeW + 6 + label(n.id).length * 6 + 6} y={n.y + n.h / 2 + 4} fill="var(--text-tertiary)" fontSize="10" fontFamily="var(--mono)">{n.count}</text>
          </g>
        );
      })}

      {/* xAI node */}
      <rect x={xaiNode.x} y={xaiNode.y} width={nodeW + 4} height={xaiNode.h} rx={4} fill="var(--text-primary)" opacity={0.8} />
      <text x={xaiNode.x + nodeW + 12} y={xaiNode.y + xaiNode.h / 2 + 5} fill="var(--text-primary)" fontSize="14" fontWeight="600" fontFamily="var(--mono)">xAI</text>
    </svg>
  );
}

/* ═══════ BUBBLE VIEW ═══════ */
function BubbleView({ data, onSelectOrg }) {
  var [hovered, setHovered] = useState(null);
  var labels = window.ORG_LABELS || {};
  var label = function (id) { return labels[id] || id.replace('@', ''); };

  var allOrgs = useMemo(function () {
    var combined = {};
    data.topSchools.forEach(function (e) { combined[e[0]] = { id: e[0], count: e[1], type: 'school' }; });
    data.topEmployers.forEach(function (e) {
      if (combined[e[0]]) { combined[e[0]].count += e[1]; combined[e[0]].type = 'both'; }
      else combined[e[0]] = { id: e[0], count: e[1], type: 'employer' };
    });
    return Object.values(combined).sort(function (a, b) { return b.count - a.count; });
  }, [data]);

  var maxCount = allOrgs.length > 0 ? allOrgs[0].count : 1;

  return (
    <div style={{ display: 'flex', flexWrap: 'wrap', gap: 10, padding: '16px 0', alignItems: 'center', justifyContent: 'center' }}>
      {allOrgs.map(function (org) {
        var size = 40 + (org.count / maxCount) * 80;
        var color = org.type === 'school' ? 'rgba(255,255,255,0.8)' : org.type === 'employer' ? 'var(--accent)' : 'var(--text-primary)';
        var bgColor = org.type === 'school' ? 'rgba(255,255,255,0.06)' : org.type === 'employer' ? 'var(--accent-muted)' : 'rgba(255,255,255,0.06)';
        var isHov = hovered === org.id;
        return (
          <div key={org.id}
            onMouseEnter={function () { setHovered(org.id); }}
            onMouseLeave={function () { setHovered(null); }}
            onClick={function () { onSelectOrg && onSelectOrg(org.id, org.type); }}
            style={{
              width: size, height: size, borderRadius: '50%',
              background: isHov ? color : bgColor,
              display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center',
              cursor: 'pointer', transition: 'all .2s',
              border: '1px solid ' + (isHov ? color : 'transparent'),
              transform: isHov ? 'scale(1.08)' : 'scale(1)',
            }}>
            <div style={{ fontSize: Math.max(9, size * 0.14), fontWeight: 600, color: isHov ? '#000' : color, fontFamily: 'var(--sans)', textAlign: 'center', lineHeight: 1.1, padding: '0 4px' }}>{label(org.id)}</div>
            <div style={{ fontSize: Math.max(8, size * 0.12), color: isHov ? 'rgba(0,0,0,0.6)' : 'var(--text-tertiary)', fontFamily: 'var(--mono)', fontFeatureSettings: "'tnum' 1" }}>{org.count}</div>
          </div>
        );
      })}
    </div>
  );
}

/* ═══════ SIDE PANEL — People list for selected org ═══════ */
function OrgPeoplePanel({ orgId, orgType, members, onClose, onSelectPerson }) {
  var labels = window.ORG_LABELS || {};
  var label = function (id) { return labels[id] || id.replace('@', ''); };
  var people = useMemo(function () {
    if (!orgId) return [];
    return members.filter(function (m) {
      if (!m.pedigree) return false;
      if (orgType === 'school') return m.pedigree.schools && m.pedigree.schools.indexOf(orgId) >= 0;
      return m.pedigree.previousEmployers && m.pedigree.previousEmployers.indexOf(orgId) >= 0;
    });
  }, [orgId, orgType, members]);

  if (!orgId) return null;

  return (
    <div style={{ width: 280, flexShrink: 0, borderLeft: '1px solid var(--border-subtle)', background: 'var(--bg-card)', overflowY: 'auto', padding: '16px' }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 12 }}>
        <div>
          <div style={{ fontSize: 14, fontWeight: 600, color: 'var(--text-primary)' }}>{label(orgId)}</div>
          <div style={{ fontSize: 11, color: 'var(--text-tertiary)' }}>{people.length} people · {orgType}</div>
        </div>
        <button onClick={onClose} style={{ background: 'none', border: '1px solid var(--border-default)', borderRadius: 4, color: 'var(--text-tertiary)', cursor: 'pointer', fontSize: 12, padding: '2px 6px' }}>✕</button>
      </div>
      {people.map(function (p) {
        return (
          <div key={p.handle} onClick={function () { onSelectPerson && onSelectPerson(p.handle); }}
            style={{ display: 'flex', gap: 8, alignItems: 'center', padding: '8px 6px', borderRadius: 6, cursor: 'pointer', marginBottom: 2, transition: 'background .1s' }}
            onMouseEnter={function (e) { e.currentTarget.style.background = 'var(--bg-elevated)'; }}
            onMouseLeave={function (e) { e.currentTarget.style.background = 'transparent'; }}>
            <Avatar name={p.name} handle={p.handle} size={28} />
            <div style={{ minWidth: 0 }}>
              <div style={{ fontSize: 12, fontFamily: 'var(--mono)', color: 'var(--text-primary)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>@{p.handle}</div>
              <div style={{ fontSize: 11, color: 'var(--text-tertiary)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{p.pedigree && p.pedigree.role ? p.pedigree.role : p.name}</div>
            </div>
          </div>
        );
      })}
    </div>
  );
}

/* ═══════ MAIN PEDIGREE SCREEN ═══════ */
function PedigreeScreen() {
  var [subView, setSubView] = useState('sankey');
  var [selectedOrg, setSelectedOrg] = useState(null); /* { id, type } */
  var members = window.COHORT.members;
  var aggData = useMemo(function () { return aggregatePedigree(members); }, [members]);

  var handleSelectOrg = useCallback(function (id, type) {
    setSelectedOrg(function (prev) { return prev && prev.id === id ? null : { id: id, type: type }; });
  }, []);

  var coverage = aggData.withPedigreeCount;
  var pct = Math.round(coverage / aggData.totalOk * 100);

  return (
    <div style={{ display: 'flex', height: '100%', overflow: 'hidden' }}>
      <div style={{ flex: 1, display: 'flex', flexDirection: 'column', overflow: 'hidden' }}>
        {/* Sub-tab bar */}
        <div style={{ padding: '12px 28px', borderBottom: '1px solid var(--border-subtle)', display: 'flex', alignItems: 'center', gap: 16, flexShrink: 0 }}>
          <SubTab label="Sankey Flow" active={subView === 'sankey'} onClick={function () { setSubView('sankey'); }} />
          <SubTab label="Bubble Map" active={subView === 'bubble'} onClick={function () { setSubView('bubble'); }} />
          <div style={{ flex: 1 }}></div>
          <div style={{ fontSize: 12, color: 'var(--text-tertiary)', fontFamily: 'var(--mono)', fontFeatureSettings: "'tnum' 1" }}>
            Coverage: <span style={{ color: pct > 50 ? 'var(--text-primary)' : 'var(--accent)' }}>{coverage}</span> / {aggData.totalOk} ({pct}%)
          </div>
        </div>

        {/* Legend */}
        <div style={{ padding: '10px 28px 4px', display: 'flex', gap: 16, fontSize: 11, color: 'var(--text-tertiary)', flexShrink: 0 }}>
          <span><span style={{ display: 'inline-block', width: 8, height: 8, borderRadius: 2, background: 'rgba(255,255,255,0.7)', marginRight: 4 }}></span>School</span>
          <span><span style={{ display: 'inline-block', width: 8, height: 8, borderRadius: 2, background: 'var(--accent)', marginRight: 4 }}></span>Previous Employer</span>
          <span><span style={{ display: 'inline-block', width: 8, height: 8, borderRadius: 2, background: 'var(--text-primary)', marginRight: 4 }}></span>Current (xAI)</span>
          <span style={{ marginLeft: 'auto', fontStyle: 'italic' }}>{aggData.noPedigree} profiles with no pedigree data (empty bio)</span>
        </div>

        {/* Visualization */}
        <div style={{ flex: 1, overflowY: 'auto', padding: '12px 28px 28px' }}>
          {subView === 'sankey'
            ? <SankeyView data={aggData} onSelectOrg={handleSelectOrg} />
            : <BubbleView data={aggData} onSelectOrg={handleSelectOrg} />
          }
        </div>
      </div>

      {/* Side panel */}
      {selectedOrg && <OrgPeoplePanel orgId={selectedOrg.id} orgType={selectedOrg.type} members={members} onClose={function () { setSelectedOrg(null); }} />}
    </div>
  );
}

function SubTab({ label, active, onClick }) {
  return (
    <button onClick={onClick} style={{
      padding: '4px 0', fontSize: 13, fontWeight: active ? 600 : 400,
      color: active ? 'var(--text-primary)' : 'var(--text-tertiary)',
      background: 'none', border: 'none', borderBottom: active ? '2px solid var(--accent)' : '2px solid transparent',
      cursor: 'pointer', fontFamily: 'var(--sans)', transition: 'all .15s',
      paddingBottom: 6,
    }}>{label}</button>
  );
}

window.PedigreeScreen = PedigreeScreen;
