// Component — Requested actions banner.
// Sits above the three-column Course architecture grid. Shows source items
// the AI placed with low confidence (or items it wants to reassign after a
// source update). User can Accept, Reassign per-row, or bulk-reassign.

const REQUESTED_ACTIONS = [
  { id: 'A-101', source: 'CLEAR-framework_handbook.docx', loc: 'p. 12',
    snippet: 'The CLEAR model originated at the Center for Creative Leadership and frames difficult conversations as a 5-step contract.',
    suggested: 'M2', confidence: 0.86,
    note: 'Currently mapped to M1 — reads more like a framework introduction.' },
  { id: 'A-102', source: 'Priya-Naidu_SME-interview.mp4', loc: '04:32',
    snippet: '"The hardest part of every difficult conversation is the first sentence — the bit you rehearse on the drive in."',
    suggested: 'M3', confidence: 0.91,
    note: 'Strong anecdote, opens the door to the script practice in M3.' },
  { id: 'A-103', source: 'Difficult-Interactions_v3-final.docx', loc: '¶ 47',
    snippet: 'Three-paragraph definition of psychological safety with a footnote citing Edmondson (1999).',
    suggested: 'M1', confidence: 0.72,
    note: 'Could also belong in M3 as in-the-moment scaffolding.' },
  { id: 'A-104', source: 'Manager-anecdotes-collected.docx', loc: '¶ 8',
    snippet: 'Anecdote: a regional director who delayed a performance conversation by 11 months and lost the team.',
    suggested: 'M1', confidence: 0.79,
    note: 'Sharp cautionary tale — fits early in the arc.' },
  { id: 'A-105', source: 'Customer-escalation-case_audio.mp3', loc: '06:14',
    snippet: 'Audio segment describing how a follow-up coffee 2 weeks later repaired a soured working relationship.',
    suggested: 'M4', confidence: 0.88,
    note: 'Repair & follow-through — natural M4 placement.' },
  { id: 'A-106', source: 'CLEAR-framework_handbook.docx', loc: 'p. 28',
    snippet: 'Body-language cues and pacing notes — when to slow down, when to pause, when to mirror posture.',
    suggested: 'M3', confidence: 0.68,
    note: 'Low confidence — could also slot into a Brand-and-settings tone guide.' },
  { id: 'A-107', source: 'Difficult-Interactions_v3-final.docx', loc: '¶ 91',
    snippet: 'Statistic: 73% of managers report avoiding at least one difficult feedback conversation per quarter.',
    suggested: 'M1', confidence: 0.84,
    note: 'Strong opener stat for the recognising-tension arc.' },
];

function RequestedActions({ modules, moduleGroups, onAssignToModule }) {
  const [items, setItems] = React.useState(REQUESTED_ACTIONS);
  const [selected, setSelected] = React.useState(() => new Set());
  const [expanded, setExpanded] = React.useState(true);
  const [bulkTarget, setBulkTarget] = React.useState('');

  if (items.length === 0) return null;

  const toggleOne = (id) => {
    setSelected(s => {
      const next = new Set(s);
      if (next.has(id)) next.delete(id); else next.add(id);
      return next;
    });
  };
  const toggleAll = () => {
    setSelected(s => s.size === items.length ? new Set() : new Set(items.map(i => i.id)));
  };
  const resolveIds = (ids) => {
    setItems(it => it.filter(i => !ids.includes(i.id)));
    setSelected(s => {
      const next = new Set(s);
      ids.forEach(id => next.delete(id));
      return next;
    });
  };
  const acceptOne = (id) => resolveIds([id]);
  const reassignOne = (id, target) => {
    onAssignToModule && onAssignToModule(id, target);
    resolveIds([id]);
  };
  const applyBulk = () => {
    if (!bulkTarget || selected.size === 0) return;
    const ids = Array.from(selected);
    ids.forEach(id => onAssignToModule && onAssignToModule(id, bulkTarget));
    resolveIds(ids);
    setBulkTarget('');
  };
  const acceptAll = () => {
    const ids = items.map(i => i.id);
    resolveIds(ids);
  };

  const selectedCount = selected.size;
  const allChecked = selectedCount === items.length;

  return (
    <section style={{
      borderBottom: '1px solid var(--border)',
      background: 'var(--surface-inset)',
      borderLeft: '4px solid var(--warning)',
    }} aria-label="Requested actions">

      {/* Header bar */}
      <div style={{
        display: 'flex', alignItems: 'center', gap: 12,
        padding: '12px 20px',
        borderBottom: expanded ? '1px solid var(--border-faint)' : 0,
      }}>
        <span style={{
          width: 28, height: 28, borderRadius: 7,
          background: 'var(--warning-bg)',
          color: 'var(--warning-text)',
          display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
        }}>
          <I.AlertTriangle size={14} />
        </span>
        <div style={{ minWidth: 0 }}>
          <div style={{ display: 'flex', alignItems: 'baseline', gap: 8 }}>
            <h2 style={{ margin: 0, fontSize: 14, fontWeight: 600, color: 'var(--text)' }}>
              Requested actions
            </h2>
            <span style={{ fontSize: 11.5, color: 'var(--text-muted)' }}>
              {items.length} item{items.length === 1 ? '' : 's'} need a module assignment
            </span>
          </div>
          <div style={{ fontSize: 11.5, color: 'var(--text-faint)', marginTop: 1 }}>
            The AI placed these with low confidence — review and confirm before publishing.
          </div>
        </div>
        <div style={{ flex: 1 }} />
        {selectedCount > 0 && (
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginRight: 4 }}>
            <span style={{ fontSize: 11.5, fontWeight: 600, color: 'var(--text-muted)' }}>
              {selectedCount} selected
            </span>
            <select value={bulkTarget} onChange={e => setBulkTarget(e.target.value)}
              className="field" style={{ height: 28, fontSize: 12, padding: '0 8px' }}>
              <option value="">Assign to…</option>
              {(moduleGroups || []).map(g => {
                const inG = modules.filter(m => m.group === g.id);
                if (inG.length === 0) return null;
                return (
                  <optgroup key={g.id} label={locText(g.title)}>
                    {inG.map(m => (
                      <option key={m.id} value={m.id}>{m.id} · {locText(m.title)}</option>
                    ))}
                  </optgroup>
                );
              })}
              {modules.filter(m => !m.group).length > 0 && (
                <optgroup label="Ungrouped">
                  {modules.filter(m => !m.group).map(m => (
                    <option key={m.id} value={m.id}>{m.id} · {locText(m.title)}</option>
                  ))}
                </optgroup>
              )}
            </select>
            <button className="btn sm primary" onClick={applyBulk}
              disabled={!bulkTarget}
              style={{ opacity: bulkTarget ? 1 : 0.5 }}>
              Apply
            </button>
            <div style={{ width: 1, height: 20, background: 'var(--border)' }} />
          </div>
        )}
        <button className="btn sm ghost" onClick={acceptAll}>
          Accept all suggestions
        </button>
        <button className="btn sm ghost" onClick={() => setExpanded(e => !e)}
          title={expanded ? 'Collapse' : 'Expand'}
          style={{ width: 28, height: 28, padding: 0, justifyContent: 'center' }}>
          {expanded ? <I.ChevronUp size={14} /> : <I.ChevronDown size={14} />}
        </button>
      </div>

      {/* Body */}
      {expanded && (
        <div style={{ padding: '12px 20px 16px' }}>

          {/* Table */}
          <div style={{
            border: '1px solid var(--border)',
            borderRadius: 'var(--radius-md)',
            overflow: 'hidden',
            background: 'var(--surface)',
          }}>
            {/* Header row */}
            <div style={{
              display: 'grid',
              gridTemplateColumns: '34px 130px minmax(0, 1fr) 220px 200px',
              gap: 12, alignItems: 'center',
              padding: '8px 12px',
              background: 'var(--surface-inset)',
              borderBottom: '1px solid var(--border)',
              fontSize: 10.5, fontWeight: 700,
              color: 'var(--text-faint)',
              letterSpacing: '.06em', textTransform: 'uppercase',
            }}>
              <span style={{ display: 'inline-flex', alignItems: 'center' }}>
                <input type="checkbox" checked={allChecked} onChange={toggleAll}
                  style={{ width: 14, height: 14, margin: 0, cursor: 'default' }} />
              </span>
              <span>Source</span>
              <span>Excerpt</span>
              <span>AI-suggested module</span>
              <span style={{ textAlign: 'right' }}>Actions</span>
            </div>

            {/* Rows */}
            {items.map((item, i) => (
              <ActionRow key={item.id}
                item={item}
                modules={modules}
                moduleGroups={moduleGroups}
                checked={selected.has(item.id)}
                onCheck={() => toggleOne(item.id)}
                onAccept={() => acceptOne(item.id)}
                onReassign={(target) => reassignOne(item.id, target)}
                last={i === items.length - 1} />
            ))}
          </div>
        </div>
      )}
    </section>
  );
}

// ── One row in the actions table ───────────────────────────────────────────
function ActionRow({ item, modules, moduleGroups, checked, onCheck, onAccept, onReassign, last }) {
  const [menuOpen, setMenuOpen] = React.useState(false);
  const [menuPos, setMenuPos] = React.useState(null); // { top, left, openUp }
  const btnRef = React.useRef(null);
  const suggestedModule = modules.find(m => m.id === item.suggested);
  const conf = Math.round(item.confidence * 100);
  const confTone = conf >= 85 ? 'var(--success-text)' :
                   conf >= 75 ? 'var(--text-muted)' :
                                'var(--warning-text)';

  const POPUP_W = 280;
  const POPUP_H = Math.min(360, 60 + modules.length * 34);

  const openMenu = () => {
    if (menuOpen) { setMenuOpen(false); return; }
    const rect = btnRef.current && btnRef.current.getBoundingClientRect();
    if (!rect) return;
    const spaceBelow = window.innerHeight - rect.bottom;
    const openUp = spaceBelow < POPUP_H + 16;
    const top = openUp
      ? Math.max(8, rect.top - POPUP_H - 6)
      : rect.bottom + 6;
    const left = Math.min(
      Math.max(8, rect.right - POPUP_W),
      window.innerWidth - POPUP_W - 8
    );
    setMenuPos({ top, left });
    setMenuOpen(true);
  };
  return (
    <div style={{
      display: 'grid',
      gridTemplateColumns: '34px 130px minmax(0, 1fr) 220px 200px',
      gap: 12, alignItems: 'flex-start',
      padding: '12px',
      background: checked ? 'var(--accent-bg)' : 'transparent',
      borderBottom: last ? 0 : '1px solid var(--border-faint)',
      transition: 'background 80ms',
    }}>
      <span style={{ display: 'inline-flex', alignItems: 'center', paddingTop: 2 }}>
        <input type="checkbox" checked={checked} onChange={onCheck}
          style={{ width: 14, height: 14, margin: 0, cursor: 'default' }} />
      </span>

      {/* Source */}
      <div style={{ minWidth: 0 }}>
        <a href="#"
          onClick={e => { e.preventDefault(); /* prototype: would open original */ }}
          className="truncate"
          title={`Open ${item.source}`}
          style={{
            fontSize: 12, fontWeight: 500,
            color: 'var(--accent-text)',
            textDecoration: 'none',
            display: 'block',
            cursor: 'default',
          }}
          onMouseOver={e => e.currentTarget.style.textDecoration = 'underline'}
          onMouseOut={e => e.currentTarget.style.textDecoration = 'none'}>
          {item.source}
        </a>
        <div style={{ fontSize: 10.5, color: 'var(--text-faint)',
          fontFamily: 'var(--font-mono)', marginTop: 1 }}>{item.loc}</div>
      </div>

      {/* Excerpt */}
      <div style={{ minWidth: 0 }}>
        <div style={{ fontSize: 12.5, color: 'var(--text)', lineHeight: 1.45,
          display: '-webkit-box', WebkitLineClamp: 2, WebkitBoxOrient: 'vertical',
          overflow: 'hidden' }}>{item.snippet}</div>
        <div style={{ fontSize: 11, color: 'var(--text-faint)', marginTop: 4,
          fontStyle: 'italic' }}>{item.note}</div>
      </div>

      {/* Suggested module */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
        <span style={{
          display: 'inline-flex', alignItems: 'center', gap: 6,
          padding: '3px 8px', borderRadius: 4,
          background: 'color-mix(in oklab, var(--accent) 12%, transparent)',
          color: 'var(--accent-text)',
          fontSize: 11.5, fontWeight: 600,
        }}>
          <I.Sparkle size={10} />
          <span style={{ fontFamily: 'var(--font-mono)' }}>{item.suggested}</span>
          <span style={{ opacity: 0.8 }}>·</span>
          <span style={{ fontWeight: 500 }}>{locText(suggestedModule?.title)}</span>
        </span>
        <span style={{ fontSize: 10.5, fontWeight: 600,
          color: confTone, fontFamily: 'var(--font-mono)' }}>
          {conf}%
        </span>
      </div>

      {/* Actions */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 6, justifyContent: 'flex-end' }}>
        <button className="btn sm" onClick={onAccept}
          style={{ background: 'color-mix(in oklab, var(--success) 16%, var(--surface))',
            borderColor: 'color-mix(in oklab, var(--success) 30%, var(--border))',
            color: 'var(--success-text)' }}>
          <I.Check size={11} />Accept
        </button>
        <div style={{ position: 'relative' }}>
          <button ref={btnRef} className="btn sm ghost" onClick={openMenu}>
            Reassign<I.ChevronDown size={11} />
          </button>
          {menuOpen && menuPos && (
            <>
              <div onClick={() => setMenuOpen(false)}
                style={{ position: 'fixed', inset: 0, zIndex: 60 }} />
              <div style={{
                position: 'fixed', top: menuPos.top, left: menuPos.left,
                width: POPUP_W, maxHeight: POPUP_H, overflowY: 'auto',
                padding: 6,
                background: 'var(--surface)', border: '1px solid var(--border)',
                borderRadius: 'var(--radius-md)', boxShadow: 'var(--shadow-lg)',
                zIndex: 61,
              }}>
                <div style={{ padding: '6px 8px 4px', fontSize: 10.5, fontWeight: 600,
                  color: 'var(--text-faint)', letterSpacing: '.06em',
                  textTransform: 'uppercase' }}>
                  Move to module
                </div>
                {(moduleGroups || []).map(g => {
                  const inG = modules.filter(m => m.group === g.id);
                  if (inG.length === 0) return null;
                  return (
                    <div key={g.id} style={{ marginTop: 2 }}>
                      <div style={{
                        display: 'flex', alignItems: 'center', gap: 5,
                        padding: '6px 8px 2px',
                        fontSize: 10, fontWeight: 700,
                        color: 'var(--text-muted)',
                        letterSpacing: '.05em', textTransform: 'uppercase',
                      }}>
                        <I.Folder size={10} />
                        <span style={{ flex: 1, minWidth: 0,
                          overflow: 'hidden', textOverflow: 'ellipsis',
                          whiteSpace: 'nowrap' }}>{locText(g.title)}</span>
                      </div>
                      {inG.map(m => (
                        <ReassignRow key={m.id} module={m} item={item}
                          onPick={(id) => { setMenuOpen(false); onReassign(id); }} />
                      ))}
                    </div>
                  );
                })}
                {modules.filter(m => !m.group).length > 0 && (
                  <div style={{ marginTop: 4 }}>
                    <div style={{ padding: '6px 8px 2px', fontSize: 10, fontWeight: 700,
                      color: 'var(--text-muted)',
                      letterSpacing: '.05em', textTransform: 'uppercase' }}>
                      Ungrouped
                    </div>
                    {modules.filter(m => !m.group).map(m => (
                      <ReassignRow key={m.id} module={m} item={item}
                        onPick={(id) => { setMenuOpen(false); onReassign(id); }} />
                    ))}
                  </div>
                )}
              </div>
            </>
          )}
        </div>
      </div>
    </div>
  );
}

// ── One row inside the Reassign popup ──────────────────────────────────────
function ReassignRow({ module: m, item, onPick }) {
  return (
    <button onClick={() => onPick(m.id)}
      style={{
        display: 'flex', alignItems: 'center', gap: 8,
        width: '100%', padding: '6px 8px',
        border: 0, borderRadius: 'var(--radius)',
        background: 'transparent', textAlign: 'left',
        cursor: 'default', fontFamily: 'inherit', fontSize: 12,
        color: 'var(--text)',
      }}
      onMouseOver={e => e.currentTarget.style.background = 'var(--surface-inset)'}
      onMouseOut={e => e.currentTarget.style.background = 'transparent'}>
      <span style={{ fontFamily: 'var(--font-mono)', fontSize: 10.5,
        fontWeight: 600, color: 'var(--text-muted)',
        background: 'var(--surface-inset)',
        padding: '1px 5px', borderRadius: 3 }}>{m.id}</span>
      <span style={{ flex: 1, minWidth: 0,
        overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
        {locText(m.title)}
      </span>
      {item.suggested === m.id && (
        <I.Sparkle size={10} style={{ color: 'var(--accent)' }}
          title="AI suggestion" />
      )}
    </button>
  );
}

Object.assign(window, { RequestedActions });