// mod-table.jsx - BranchPicker + ModTable components
// Loaded after sortof-shared.jsx; defines globals that sortof-app.jsx references.
const { useState, useMemo } = React;

function BranchPicker({ wsid, branches, selected, userTouched, onToggle }) {
  const radio = isRadioMode(branches);
  const inputType = radio ? 'radio' : 'checkbox';
  const activeSet = new Set(D.SORTED_ORDER || []);
  const effective = userTouched ? selected : defaultSelectionForBranches(branches, activeSet);
  return (
    <tr>
      <td colSpan={COLUMN_COUNT} className="branch-panel">
        <div className="branch-panel-inner">
          <div className="branch-panel-meta">
            workshop {wsid} · {branches.length} mod_ids · {radio ? 'pick one' : 'multi-select'}
          </div>
          {branches.map(b => {
            const checked = effective.includes(b.modId);
            return (
              <label key={b.modId} className={'branch-row' + (checked ? ' is-checked' : '')}>
                <input
                  type={inputType}
                  name={radio ? `branch-${wsid}` : undefined}
                  className="branch-input"
                  checked={checked}
                  onChange={() => onToggle(wsid, b.modId, branches)}
                />
                <WsidLink wsid={wsid} className="branch-modid">{b.modId}</WsidLink>
                <span className="branch-name">{b.name}</span>
                <span className={'cat ' + b.cat}>{b.cat}</span>
                <span className="branch-deps">
                  {b.deps && b.deps.length ? b.deps.join(', ') : '-'}
                </span>
                <span className="branch-pos">
                  {b.pos === 'first' ? 'first' : (b.pos === 'last' ? 'last' : '-')}
                </span>
                {b.hint && <span className="branch-hint">{b.hint}</span>}
              </label>
            );
          })}
        </div>
      </td>
    </tr>
  );
}

function ModTable({ defaultOpen = false, branchSelections, onToggleBranch, expandedWsids, onToggleExpansion }) {
  const [open, setOpen] = useState(defaultOpen);

  const groupedByWsid = useMemo(() => {
    const g = {};
    for (const m of (D.MOD_DB || [])) {
      const w = m.wsid || '';
      if (!w) continue;
      (g[w] = g[w] || []).push(m);
    }
    return g;
  }, [D.MOD_DB]);

  const rowSpecs = useMemo(() => {
    const specs = [];
    const seenWsid = new Set();
    for (const modId of (D.SORTED_ORDER || [])) {
      const m = (D.MOD_DB || []).find(x => x.modId === modId);
      if (!m || !m.wsid) continue;
      if (seenWsid.has(m.wsid)) continue;
      seenWsid.add(m.wsid);
      const branches = groupedByWsid[m.wsid] || [m];
      const isMulti = branches.length >= 2;
      specs.push({ wsid: m.wsid, primary: m, branches, isMulti });
    }
    for (const w of Object.keys(groupedByWsid)) {
      if (!seenWsid.has(w)) {
        const branches = groupedByWsid[w];
        specs.push({ wsid: w, primary: branches[0], branches, isMulti: branches.length >= 2 });
      }
    }
    return specs;
  }, [D.SORTED_ORDER, D.MOD_DB, groupedByWsid]);

  return (
    <div className="panel table-section">
      <div className="tbl-head" role="button" tabIndex={0} onClick={() => setOpen(!open)} onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); setOpen(!open); } }}>
        <span>mod details</span>
        <span className="count">· {(D.SORTED_ORDER || []).length} mods</span>
        <span className="tbl-subtitle">
          why everything ended up where it did
        </span>
        <span className="chev">{open ? '▾' : '▸'}</span>
      </div>
      {open && (
        <table className="mods-table">
          <thead>
            <tr>
              <th>#</th>
              <th>mod id</th>
              <th>workshop id</th>
              <th>category</th>
              <th>dependencies</th>
              <th>load</th>
            </tr>
          </thead>
          <tbody>
            {rowSpecs.map((spec, i) => {
              const idx = String(i + 1).padStart(2, '0');
              if (!spec.isMulti) {
                const m = spec.primary;
                const rowState = rowStateForMod(m.modId);
                const stateGlyph = { resolved: '✓', warning: '⚠', error: '✗' }[rowState] || '·';
                return (
                  <tr key={spec.wsid} className={'mod-row mod-row-' + rowState}>
                    <td className="idx">
                      <span className="row-state-glyph" aria-hidden="true">{stateGlyph}</span>{idx}
                    </td>
                    <td><WsidLink wsid={spec.wsid} className="modid">{m.modId}</WsidLink></td>
                    <td><span className="wsid">{spec.wsid}</span></td>
                    <td><span className={'cat ' + m.cat}>{m.cat}</span></td>
                    <td><span className="deps">{m.deps && m.deps.length ? m.deps.join(', ') : '-'}</span></td>
                    <td>
                      {m.pos === 'first' && <span className="pos first">first</span>}
                      {m.pos === 'last'  && <span className="pos last">last</span>}
                      {!m.pos && <span className="pos">-</span>}
                    </td>
                  </tr>
                );
              }
              const selected = branchSelections[spec.wsid] || [];
              const N = spec.branches.length;
              const X = selected.length;
              const userTouched = (spec.wsid in branchSelections);
              const affordance = userTouched ? `✓ ${X} of ${N}` : `▾ ${N} branches`;
              const firstSelected = spec.branches.find(b => selected.includes(b.modId)) || spec.branches[0];
              const showAsZero = userTouched && X === 0;
              const display = showAsZero ? null : firstSelected;
              const expanded = expandedWsids.has(spec.wsid);
              const rowState = display ? rowStateForMod(display.modId) : 'resolved';
              const stateGlyph = { resolved: '✓', warning: '⚠', error: '✗' }[rowState] || '·';
              return (
                <React.Fragment key={spec.wsid}>
                  <tr className={'mod-row mod-row-' + rowState}>
                    <td className="idx">
                      <span className="row-state-glyph" aria-hidden="true">{stateGlyph}</span>{idx}
                    </td>
                    <td>
                      <button className="branch-affordance"
                              aria-expanded={expanded}
                              onClick={() => onToggleExpansion(spec.wsid)}>
                        {affordance}
                      </button>
                    </td>
                    <td><span className="wsid">{spec.wsid}</span></td>
                    <td>{display ? <span className={'cat ' + display.cat}>{display.cat}</span> : '-'}</td>
                    <td>{display && display.deps && display.deps.length ? display.deps.join(', ') : '-'}</td>
                    <td>
                      {display && display.pos === 'first' && <span className="pos first">first</span>}
                      {display && display.pos === 'last'  && <span className="pos last">last</span>}
                      {(!display || !display.pos) && <span className="pos">-</span>}
                    </td>
                  </tr>
                  {expanded && (
                    <BranchPicker
                      wsid={spec.wsid}
                      branches={spec.branches}
                      selected={selected}
                      userTouched={userTouched}
                      onToggle={onToggleBranch}
                    />
                  )}
                </React.Fragment>
              );
            })}
          </tbody>
        </table>
      )}
    </div>
  );
}

Object.assign(window, { ModTable, BranchPicker, rowStateForMod });
