/* Approvals queue — wired to live /api/approvals.
   Returns { approvals: [...] }. Each approval has an id, target type/id,
   submitted_by, submitted_at, decision, etc. (shape varies by route). */

function APV_relativeTime(iso) {
  if (!iso) return '—';
  const ageMs = Date.now() - new Date(iso).getTime();
  const m = Math.round(ageMs / 60000);
  if (m < 1) return 'just now';
  if (m < 60) return `${m}m`;
  const h = Math.round(m / 60);
  if (h < 24) return `${h}h`;
  const d = Math.round(h / 24);
  return `${d}d`;
}

/* Approval-decision modal — note + submit, used for both reject and
   changes-requested. Same UX as ReviewDecisionModal in single-campaign
   but operates on the /api/approvals/:id/reject route which serves
   double duty (decision='changes_requested' to send back, no decision
   to outright reject). */
function APV_DecisionModal({ open, action, approvalId, onClose, onDone }) {
  const [note, setNote] = useState('');
  const [busy, setBusy] = useState(false);
  const [err, setErr]   = useState(null);

  useEffect(() => {
    if (!open) return;
    setNote(''); setBusy(false); setErr(null);
  }, [open, action]);

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

  async function submit(e) {
    e && e.preventDefault();
    setBusy(true); setErr(null);
    try {
      const body = { note: note.trim() };
      if (action === 'changes') body.outcome = 'changes_requested';
      await apiFetch(`/api/approvals/${approvalId}/reject`, {
        method: 'POST',
        body: JSON.stringify(body),
      });
      window.toast && window.toast.success(action === 'changes' ? 'Changes requested' : 'Submission rejected');
      if (onDone) onDone();
      onClose && onClose();
    } catch (e2) {
      setErr(e2.message);
    } finally {
      setBusy(false);
    }
  }

  if (!open) return null;
  const isReject = action === 'reject';
  return (
    <div
      onClick={(e) => { if (e.target === e.currentTarget) onClose && onClose(); }}
      style={{
        position: 'fixed', inset: 0, zIndex: 220,
        background: 'rgba(6, 7, 10, 0.78)', backdropFilter: 'blur(6px)',
        display: 'grid', placeItems: 'center', padding: 24,
        animation: 'aqModalFade 0.18s ease-out',
      }}
    >
      <form
        className="aq-rise"
        onSubmit={submit}
        style={{
          width: 'min(480px, 100%)',
          background: 'var(--aq-surface)',
          border: '1px solid var(--aq-line)',
          borderRadius: 14, boxShadow: 'var(--aq-shadow-2)',
          display: 'flex', flexDirection: 'column', maxHeight: '82vh',
        }}
      >
        <header style={{
          padding: '14px 18px', borderBottom: '1px solid var(--aq-line)',
          display: 'flex', alignItems: 'center', gap: 10,
        }}>
          <div style={{ flex: 1, fontFamily: 'var(--aq-ff-display)', fontSize: 14.5, color: 'var(--aq-text)', fontWeight: 500 }}>
            {isReject ? 'Reject submission' : 'Request changes'}
          </div>
          <button type="button" className="aq-icon-btn" onClick={onClose}><Icon name="close" size={13} /></button>
        </header>

        <div style={{ overflowY: 'auto', padding: 16, display: 'flex', flexDirection: 'column', gap: 14 }}>
          <label style={{ display: 'block' }}>
            <div style={{ fontSize: 11.5, color: 'var(--aq-text-dim)', marginBottom: 5 }}>
              {isReject ? 'Reason' : 'What changes are needed'}
            </div>
            <textarea
              autoFocus rows={5} maxLength={1000}
              value={note} onChange={(e) => setNote(e.target.value)}
              placeholder={isReject
                ? 'Why this can\'t be approved as-is.'
                : 'Specific edits the submitter should make before resubmitting.'}
              style={{
                width: '100%', padding: '8px 10px', fontSize: 13,
                background: 'var(--aq-surface-2)', border: '1px solid var(--aq-line)',
                borderRadius: 7, color: 'var(--aq-text)', font: 'inherit', outline: 0,
                resize: 'vertical',
              }}
            />
          </label>

          {err && (
            <div style={{
              padding: '8px 10px', borderRadius: 6,
              background: 'color-mix(in srgb, var(--aq-danger) 12%, transparent)',
              color: 'var(--aq-danger)', fontSize: 12,
            }}>{err}</div>
          )}
        </div>

        <footer style={{
          padding: '10px 16px', borderTop: '1px solid var(--aq-line)',
          background: 'var(--aq-surface-2)',
          display: 'flex', justifyContent: 'flex-end', gap: 8,
        }}>
          <button type="button" className="x-btn ghost" onClick={onClose}>Cancel</button>
          <button
            type="submit"
            className={isReject ? 'x-btn is-danger' : 'x-btn'}
            disabled={busy}
          >{busy ? 'Sending…' : (isReject ? 'Reject' : 'Send change request')}</button>
        </footer>
      </form>
    </div>
  );
}

function ApprovalsScreen() {
  const [approvals, setApprovals] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);
  const [activeId, setActiveId] = useState(null);
  const [busy, setBusy] = useState(null);            /* 'approve' | 'reject' | 'changes' | 'ai' */
  const [aiReview, setAiReview] = useState({});       /* keyed by approval id */
  const [reload, setReload] = useState(0);
  /* Inline modal: { action: 'reject' | 'changes' } when open. */
  const [decisionModal, setDecisionModal] = useState(null);

  useEffect(() => {
    let cancelled = false;
    setLoading(true);
    apiFetch('/api/approvals')
      .then((res) => {
        if (cancelled) return;
        const list = res.approvals || [];
        setApprovals(list);
        if (list.length > 0 && !activeId) setActiveId(list[0].id);
        setLoading(false);
      })
      .catch((err) => {
        if (cancelled) return;
        setError(err.message);
        setLoading(false);
      });
    return () => { cancelled = true; };
  }, [reload]);

  const active = approvals.find((a) => a.id === activeId) || null;

  /* Approve goes through directly; reject + changes route through the
     modal so the reviewer can write a proper note (with linebreaks,
     full-width text area, esc-to-cancel) instead of squinting at a
     tiny system prompt. */
  async function decide(action) {
    if (!active) return;
    if (action === 'reject' || action === 'changes') {
      setDecisionModal({ action });
      return;
    }
    setBusy(action);
    try {
      await apiFetch(`/api/approvals/${active.id}/approve`, {
        method: 'POST',
        body: JSON.stringify({}),
      });
      advanceQueue();
    } catch (err) {
      window.toast && window.toast.danger(`Approve failed: ${err.message}`);
    } finally {
      setBusy(null);
    }
  }

  function advanceQueue() {
    setReload((n) => n + 1);
    /* Move to the next pending submission so the queue keeps flowing. */
    const idx = approvals.findIndex((a) => a.id === active.id);
    const next = approvals[idx + 1] || approvals[0];
    setActiveId(next ? next.id : null);
  }

  async function runAiReview() {
    if (!active) return;
    setBusy('ai');
    try {
      const res = await apiFetch(`/api/approvals/${active.id}/ai-review`, { method: 'POST' });
      setAiReview((cur) => ({ ...cur, [active.id]: res }));
    } catch (err) {
      window.alert(`AI review failed: ${err.message}`);
    } finally {
      setBusy(null);
    }
  }

  function openTarget(a) {
    if (!a || !a.target_type || !a.target_id) return;
    /* Map approval target_type → our hash route. Mirrors original CMS
       drilldown so the reviewer can see the full record before deciding. */
    const route = ({
      species: 'species',
      campaign: 'campaign',
      asset: 'media',
    })[a.target_type];
    if (route) window.location.hash = `#${route}/${a.target_id}`;
  }

  return (
    <div className="aq-content">
      <div className="aq-content-inner" style={{ maxWidth: 1200 }}>
        <header style={{ marginBottom: 16 }}>
          <div className="aq-eyebrow">
            <span>Slate</span>
            <span className="aq-sep">·</span>
            <span>Pending sign-off</span>
          </div>
          <h1 style={{
            fontFamily: 'var(--aq-ff-display)', fontSize: 26, fontWeight: 500,
            letterSpacing: '-0.012em', color: 'var(--aq-text)', margin: '4px 0 4px',
          }}>Approvals</h1>
          <p style={{ fontSize: 13, color: 'var(--aq-text-faint)', margin: 0 }}>
            Review queue. Submissions awaiting org-admin sign-off.
          </p>
        </header>

        {loading && (
          <div style={{ padding: 60, textAlign: 'center', color: 'var(--aq-text-faint)' }}>
            Loading approvals…
          </div>
        )}
        {error && (
          <div style={{
            padding: '10px 14px',
            background: 'color-mix(in srgb, var(--aq-danger) 12%, transparent)',
            border: '1px solid color-mix(in srgb, var(--aq-danger) 30%, transparent)',
            borderRadius: 6, color: 'var(--aq-danger)', fontSize: 12,
          }}>{error}</div>
        )}

        {!loading && !error && approvals.length === 0 && (
          <div className="x-card" style={{ padding: '60px 24px', textAlign: 'center' }}>
            <Icon name="check" size={32} />
            <div style={{
              fontSize: 14, color: 'var(--aq-text)', margin: '14px 0 6px',
              fontFamily: 'var(--aq-ff-display)', fontWeight: 500,
            }}>All caught up</div>
            <div style={{ fontSize: 12.5, color: 'var(--aq-text-faint)', maxWidth: 380, margin: '0 auto' }}>
              No content awaiting review right now. Submitted campaigns and species edits will land here.
            </div>
          </div>
        )}

        {!loading && !error && approvals.length > 0 && (
          <div className="x-approval">
            <div className="x-approval-list">
              {approvals.map((a) => (
                <div
                  key={a.id}
                  className={`x-approval-row ${a.id === activeId ? 'is-active' : ''}`}
                  onClick={() => setActiveId(a.id)}
                >
                  <div className="x-approval-row-head">
                    <div className="x-approval-row-title">
                      {a.title || a.target_name || `${a.target_type || 'Item'} review`}
                    </div>
                    <div className="x-approval-row-time">{APV_relativeTime(a.submitted_at || a.created_at)}</div>
                  </div>
                  <div className="x-approval-row-meta">
                    {a.target_type || 'Submission'}
                    {a.submitted_by_name && <> · by {a.submitted_by_name}</>}
                  </div>
                </div>
              ))}
            </div>

            <div className="x-diff">
              {active ? <>
                <div style={{ display: 'flex', alignItems: 'baseline', gap: 8, marginBottom: 14 }}>
                  <h3 style={{
                    margin: 0, fontFamily: 'var(--aq-ff-display)',
                    fontSize: 14, fontWeight: 500, color: 'var(--aq-text)',
                  }}>{active.title || active.target_name || 'Submission'}</h3>
                  {active.target_type && active.target_id && (
                    <a
                      href="#"
                      onClick={(e) => { e.preventDefault(); openTarget(active); }}
                      style={{ fontSize: 11.5, color: 'var(--aq-accent)', textDecoration: 'none' }}
                    >Open {active.target_type} →</a>
                  )}
                </div>
                <div style={{ fontSize: 12.5, color: 'var(--aq-text-dim)', whiteSpace: 'pre-wrap' }}>
                  {active.notes || active.summary || 'No diff data on this submission.'}
                </div>

                {/* AI review findings — populated when reviewer clicks
                    "Run AI review". Backend returns a structured payload
                    with checklist, factual concerns, tone, accessibility. */}
                {aiReview[active.id] && (
                  <div style={{
                    marginTop: 14, padding: '10px 12px', borderRadius: 6,
                    background: 'var(--aq-surface-2)',
                    border: '1px solid var(--aq-line)', fontSize: 12.5,
                  }}>
                    <div style={{
                      fontFamily: 'var(--aq-ff-mono)', fontSize: 9.5,
                      letterSpacing: '0.08em', textTransform: 'uppercase',
                      color: 'var(--aq-text-faint)', marginBottom: 6,
                    }}>AI review</div>
                    {(() => {
                      const r = aiReview[active.id];
                      const blocks = [
                        ['Summary', r.summary],
                        ['Factual concerns', r.factual_concerns],
                        ['Tone', r.tone],
                        ['Accessibility', r.accessibility],
                        ['Checklist', r.checklist],
                      ];
                      return blocks.filter(([, v]) => v).map(([label, v]) => (
                        <div key={label} style={{ marginBottom: 6 }}>
                          <div style={{
                            fontFamily: 'var(--aq-ff-mono)', fontSize: 9.5,
                            color: 'var(--aq-accent)', letterSpacing: '0.06em',
                          }}>{label}</div>
                          <div style={{ color: 'var(--aq-text-muted)', whiteSpace: 'pre-wrap' }}>
                            {Array.isArray(v) ? v.join('\n') : v}
                          </div>
                        </div>
                      ));
                    })()}
                  </div>
                )}

                <div style={{ display: 'flex', gap: 8, marginTop: 14, flexWrap: 'wrap' }}>
                  {Auth.canApprove() ? (
                    <>
                      <button
                        className="x-btn"
                        onClick={() => decide('approve')}
                        disabled={busy != null}
                      >{busy === 'approve' ? 'Approving…' : 'Approve'}</button>
                      <button
                        className="x-btn ghost"
                        onClick={() => decide('changes')}
                        disabled={busy != null}
                      >{busy === 'changes' ? 'Sending…' : 'Request changes'}</button>
                      <button
                        className="x-btn ghost"
                        onClick={runAiReview}
                        disabled={busy != null}
                        title="Ask Claude to flag factual / tone / accessibility issues"
                      >{busy === 'ai' ? 'Reviewing…' : 'Run AI review'}</button>
                      <button
                        className="x-btn is-danger"
                        style={{ marginLeft: 'auto' }}
                        onClick={() => decide('reject')}
                        disabled={busy != null}
                      >{busy === 'reject' ? 'Rejecting…' : 'Reject'}</button>
                    </>
                  ) : (
                    <span style={{
                      fontSize: 11.5, color: 'var(--aq-text-faint)',
                      fontFamily: 'var(--aq-ff-mono)', letterSpacing: '0.04em',
                    }}>VIEW ONLY · approval requires reviewer role</span>
                  )}
                </div>
              </> : (
                <div style={{ color: 'var(--aq-text-faint)', fontSize: 12.5 }}>Pick a submission from the list.</div>
              )}
            </div>

            <aside className="x-approval-side">
              <div className="x-eyebrow">Submission</div>
              {active && (
                <>
                  <div style={{ fontSize: 12.5, color: 'var(--aq-text-dim)' }}>
                    <b style={{ color: 'var(--aq-text)' }}>{active.submitted_by_name || 'Someone'}</b> submitted
                    {' '}{APV_relativeTime(active.submitted_at)}
                  </div>
                  {active.target_type && (
                    <div style={{ fontFamily: 'var(--aq-ff-mono)', fontSize: 11, color: 'var(--aq-text-faint)', marginTop: 6 }}>
                      {active.target_type} · {(active.target_id || '').slice(0, 8)}
                    </div>
                  )}
                </>
              )}
            </aside>
          </div>
        )}
      </div>

      <APV_DecisionModal
        open={decisionModal != null}
        action={decisionModal && decisionModal.action}
        approvalId={active && active.id}
        onClose={() => setDecisionModal(null)}
        onDone={() => advanceQueue()}
      />
    </div>
  );
}

window.ApprovalsScreen = ApprovalsScreen;
