// assistant.jsx — 전역 AI 어시스턴트 패널(모든 화면 우측 상주)
// 3탭: 대화 / 요청(RFI) / 가이드
// 백엔드가 아직 없거나 404여도 크래시하지 않고 "아직 없음"을 정직하게 표시한다.

const { Icon, Pill, Button, Progress } = window.RAlly;

// ── 안전 fetch: 실패·404·비JSON이면 null 반환(패널 크래시 금지) ──
const jget = (url) =>
  fetch(url)
    .then((r) => (r.ok ? r.json() : null))
    .then((d) => (d && d.ok !== false ? d : (d && d.ok === false ? null : d)))
    .catch(() => null);

const jpost = (url, body) =>
  fetch(url, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(body || {}),
  })
    .then((r) => (r.ok ? r.json() : null))
    .catch(() => null);

const PANEL_KEY = 'RALLY_AI_PANEL';       // '1' 열림 / '0' 접힘
window.RAlly.isPanelOpen = () => {
  try { return localStorage.getItem(PANEL_KEY) !== '0'; } catch (e) { return true; }
};
window.RAlly.setPanelOpen = (b) => {
  try { localStorage.setItem(PANEL_KEY, b ? '1' : '0'); } catch (e) {}
};

// 스피너 키프레임(전역 CSS를 건드리지 않고 주입)
(() => {
  if (document.getElementById('ai-spin-kf')) return;
  const st = document.createElement('style');
  st.id = 'ai-spin-kf';
  st.textContent = '@keyframes ai-spin{to{transform:rotate(360deg)}}';
  document.head.appendChild(st);
})();

const ROLE_LABEL = { dev: '개발', ra: 'RA', qa_manager: '품질책임자' };
const STATUS_LABEL = { open: '열림', answered: '답변됨', na: '해당없음' };

// ── LLM 백엔드 상태 배지 ──
// 정상 답변에는 아무것도 띄우지 않는다(노이즈 금지). 폴백(degraded)일 때만,
// 백엔드가 정말 없는 경우와 이번 호출이 실패한 경우를 구분해 작게 표시한다.
const BackendBadge = ({ backend, degraded }) => {
  if (!degraded) return null;
  const none = backend === 'none';
  return (
    <div style={{
      marginTop: 5, display: 'inline-flex', alignItems: 'center', gap: 4,
      fontSize: 10.5, lineHeight: 1.4, padding: '2px 7px', borderRadius: 10,
      background: none ? 'rgba(120,120,120,.10)' : 'rgba(224,122,95,.12)',
      color: none ? '#6b6b6b' : '#a24b31', border: '1px solid rgba(0,0,0,.06)',
    }}>
      <Icon name="shield" size={10} />
      <span>{none ? 'AI 백엔드 미설정' : '근거만 표시 — 요약 생성 실패'}</span>
    </div>
  );
};

// ── API 키 안내(백엔드가 cli뿐일 때 한 번만) ──
const APIKEY_HINT_KEY = 'RALLY_AI_APIKEY_HINT_DISMISSED';
const hintDismissed = () => {
  try { return localStorage.getItem(APIKEY_HINT_KEY) === '1'; } catch (e) { return true; }
};
const dismissHint = () => {
  try { localStorage.setItem(APIKEY_HINT_KEY, '1'); } catch (e) {}
};

const ApiKeyHint = ({ onClose }) => (
  <div style={{
    margin: '8px 12px 2px', padding: '7px 9px', borderRadius: 8, fontSize: 11, lineHeight: 1.55,
    background: 'rgba(120,150,200,.10)', border: '1px solid rgba(0,0,0,.06)', color: '#4a5568',
    display: 'flex', alignItems: 'flex-start', gap: 6,
  }}>
    <span style={{ flex: 1 }}>
      지금은 claude CLI 백엔드로 답하고 있어 응답에 20~40초가 걸립니다.
      <b> ANTHROPIC_API_KEY</b>를 서버 환경변수로 설정하면 응답이 수 초대로 빨라집니다.
    </span>
    <button onClick={onClose} title="다시 보지 않기"
      style={{ border: 0, background: 'transparent', cursor: 'pointer', color: '#8a94a6', fontSize: 13, lineHeight: 1, padding: 0 }}>
      ✕
    </button>
  </div>
);

// ── 빈 상태 ──
const Empty = ({ title, note }) => (
  <div className="ai-empty">
    <div className="ai-empty__title">{title}</div>
    {note && <div className="ai-empty__note">{note}</div>}
  </div>
);

// ─────────────────────────────────────────────────────────
// 답변 폼 — input_type별 (text / table / file / choice) + 해당없음
// ─────────────────────────────────────────────────────────
const AnswerForm = ({ card, seed, onDone, onCancel }) => {
  const spec = card.table_spec || null;
  const headers = (spec && spec.headers) || [];
  const initRows = () => {
    if (seed && seed.rows && seed.rows.length) return seed.rows.map((r) => r.slice());
    const n = Math.max(1, (spec && spec.rows) || 3);
    return Array.from({ length: n }, () => headers.map(() => ''));
  };

  const [text, setText] = React.useState((seed && seed.value) || '');
  const [rows, setRows] = React.useState(initRows);
  const [choice, setChoice] = React.useState('');
  const [file, setFile] = React.useState(null);      // {name, b64}
  const [naMode, setNaMode] = React.useState(false);
  const [naReason, setNaReason] = React.useState('');
  const [busy, setBusy] = React.useState(false);
  const [err, setErr] = React.useState('');

  // seed(가이드 템플릿 주입)가 바뀌면 폼 갱신
  React.useEffect(() => {
    if (!seed) return;
    if (seed.value != null) setText(seed.value);
    if (seed.rows && seed.rows.length) setRows(seed.rows.map((r) => r.slice()));
  }, [seed]);

  const setCell = (i, j, v) =>
    setRows((rs) => rs.map((r, ri) => (ri === i ? r.map((c, ci) => (ci === j ? v : c)) : r)));

  // 엑셀 붙여넣기(TSV) — 클릭한 셀을 시작점으로 채움
  const onPaste = (i, j) => (e) => {
    const txt = (e.clipboardData || window.clipboardData).getData('text');
    if (!txt || txt.indexOf('\t') < 0 && txt.indexOf('\n') < 0) return;  // 단일 셀은 기본 동작
    e.preventDefault();
    const grid = txt.replace(/\r/g, '').replace(/\n+$/, '').split('\n').map((l) => l.split('\t'));
    setRows((rs) => {
      const w = headers.length || (grid[0] ? grid[0].length : 1);
      const next = rs.map((r) => r.slice());
      grid.forEach((line, gi) => {
        const ri = i + gi;
        while (next.length <= ri) next.push(Array.from({ length: w }, () => ''));
        line.forEach((cell, gj) => {
          const ci = j + gj;
          if (ci < w) next[ri][ci] = cell;
        });
      });
      return next;
    });
  };

  const pickFile = (e) => {
    const f = e.target.files && e.target.files[0];
    if (!f) return;
    const rd = new FileReader();
    rd.onload = () => {
      const s = String(rd.result || '');
      setFile({ name: f.name, b64: s.slice(s.indexOf(',') + 1) });
    };
    rd.readAsDataURL(f);
  };

  const submit = () => {
    setErr(''); setBusy(true);
    let body = {};
    if (naMode) {
      if (!naReason.trim()) { setErr('해당 없음 사유를 적어주세요. (규제 문서에서 빈칸과 해당없음은 다릅니다)'); setBusy(false); return; }
      body = { na_reason: naReason.trim() };
    } else if (card.input_type === 'table') {
      const clean = rows.filter((r) => r.some((c) => String(c).trim()));
      if (!clean.length) { setErr('표에 최소 1행을 입력하세요.'); setBusy(false); return; }
      body = { rows: clean };
    } else if (card.input_type === 'file') {
      if (!file) { setErr('파일을 선택하세요.'); setBusy(false); return; }
      body = { file_b64: file.b64, filename: file.name };
    } else if (card.input_type === 'choice') {
      if (!choice) { setErr('항목을 선택하세요.'); setBusy(false); return; }
      body = { value: choice };
    } else {
      if (!text.trim()) { setErr('내용을 입력하세요.'); setBusy(false); return; }
      body = { value: text.trim() };
    }
    jpost('/api/rfi/' + encodeURIComponent(card.id) + '/answer', body).then((d) => {
      setBusy(false);
      if (!d || d.ok === false) { setErr('제출에 실패했습니다. 서버 응답을 받지 못했습니다.'); return; }
      onDone(d);
    });
  };

  const opts = (card.options || (card.table_spec && card.table_spec.options) || []);

  return (
    <div className="ai-form">
      <div className="ai-form__head">
        <button className="ai-linkbtn" onClick={onCancel}>← 목록</button>
        <span className="ai-chip">{ROLE_LABEL[card.role] || card.role}</span>
      </div>
      <div className="ai-form__title">{card.title}</div>
      <div className="ai-form__meta">
        {card.doc_code ? card.doc_code + ' · ' : ''}{card.doc_name || ''}{card.section ? ' · ' + card.section : ''}
      </div>
      {card.why && <div className="ai-why"><b>왜 필요한가</b><div>{card.why}</div></div>}
      {card.regulation && (
        <div className="ai-reg">
          <Icon name="shield" size={12} />
          <span>{card.regulation.source}{card.regulation.clause ? ' ' + card.regulation.clause : ''}</span>
        </div>
      )}

      {!naMode && (
        <div className="ai-form__body">
          {card.input_type === 'table' && (
            <div>
              <div className="ai-hint">엑셀에서 표를 복사해 셀에 붙여넣으면(Ctrl+V) 자동으로 채워집니다.</div>
              <div className="ai-tablewrap">
                <table className="ai-table">
                  <thead>
                    <tr>{headers.map((h, j) => <th key={j}>{h}</th>)}</tr>
                  </thead>
                  <tbody>
                    {rows.map((r, i) => (
                      <tr key={i}>
                        {headers.map((h, j) => (
                          <td key={j}>
                            <input value={r[j] || ''} onChange={(e) => setCell(i, j, e.target.value)} onPaste={onPaste(i, j)} />
                          </td>
                        ))}
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
              <button className="ai-linkbtn" onClick={() => setRows((rs) => rs.concat([headers.map(() => '')]))}>+ 행 추가</button>
            </div>
          )}
          {card.input_type === 'file' && (
            <div>
              <input type="file" onChange={pickFile} className="ai-file" />
              {file && <div className="ai-hint">선택됨: {file.name}</div>}
            </div>
          )}
          {card.input_type === 'choice' && (
            <div className="ai-choices">
              {opts.length === 0 && <div className="ai-hint">선택지가 제공되지 않았습니다. 직접 입력하세요.</div>}
              {opts.length === 0 ? (
                <textarea className="ai-textarea" rows={3} value={choice} onChange={(e) => setChoice(e.target.value)} />
              ) : opts.map((o) => (
                <label key={o} className={'ai-choice' + (choice === o ? ' ai-choice--on' : '')}>
                  <input type="radio" name={'c' + card.id} checked={choice === o} onChange={() => setChoice(o)} />
                  <span>{o}</span>
                </label>
              ))}
            </div>
          )}
          {(!card.input_type || card.input_type === 'text') && (
            <textarea className="ai-textarea" rows={7} value={text} onChange={(e) => setText(e.target.value)}
              placeholder="내용을 입력하세요. 가이드 탭의 템플릿을 불러올 수도 있습니다." />
          )}
        </div>
      )}

      {naMode && (
        <div className="ai-form__body">
          <div className="ai-hint">이 항목이 우리 제품에 해당하지 않는 이유를 적어주세요. 심사에서는 빈칸과 &lsquo;해당없음&rsquo;이 다르게 평가됩니다.</div>
          <textarea className="ai-textarea" rows={4} value={naReason} onChange={(e) => setNaReason(e.target.value)}
            placeholder="예: 본 제품은 멸균 제품이 아니므로 멸균 밸리데이션 해당 없음" />
        </div>
      )}

      {err && <div className="ai-err">{err}</div>}

      <div className="ai-form__foot">
        <Button variant="accent" size="sm" onClick={submit} disabled={busy}>{busy ? '제출 중…' : '제출'}</Button>
        <Button variant="ghost" size="sm" onClick={() => { setNaMode((v) => !v); setErr(''); }}>
          {naMode ? '← 답변 입력' : '해당 없음'}
        </Button>
        {card.marker_count > 0 && <span className="ai-hint" style={{ marginLeft: 'auto' }}>빈칸 {card.marker_count}개</span>}
      </div>
    </div>
  );
};

// ─────────────────────────────────────────────────────────
// 요청(RFI) 탭
// ─────────────────────────────────────────────────────────
const RfiTab = ({ cards, summary, loading, filters, setFilters, active, setActive, reload, seed, onOpenGuide }) => {
  if (active) {
    return (
      <AnswerForm
        card={active}
        seed={seed}
        onCancel={() => setActive(null)}
        onDone={(d) => {
          setActive(null);
          reload();
          if (d && d.remaining != null) {
            window.RAlly.__aiToast && window.RAlly.__aiToast('제출 완료 · 남은 빈칸 ' + d.remaining + '개');
          }
        }}
      />
    );
  }

  return (
    <div className="ai-scroll">
      <div className="ai-filters">
        <select value={filters.role} onChange={(e) => setFilters({ ...filters, role: e.target.value })}>
          <option value="">역할 전체</option>
          <option value="dev">개발</option>
          <option value="ra">RA</option>
          <option value="qa_manager">품질책임자</option>
        </select>
        <select value={filters.status} onChange={(e) => setFilters({ ...filters, status: e.target.value })}>
          <option value="open">열림</option>
          <option value="answered">답변됨</option>
          <option value="na">해당없음</option>
          <option value="">상태 전체</option>
        </select>
        <select value={filters.priority} onChange={(e) => setFilters({ ...filters, priority: e.target.value })}>
          <option value="">우선순위 전체</option>
          <option value="1">1 · 제출 차단</option>
          <option value="2">2 · 필요</option>
          <option value="3">3 · 선택</option>
        </select>
        {filters.doc_id && (
          <span className="ai-chip ai-chip--coral" onClick={() => setFilters({ ...filters, doc_id: '' })} style={{ cursor: 'pointer' }}>
            현재 문서만 ✕
          </span>
        )}
      </div>

      {summary && (
        <div className="ai-summary">
          열림 {summary.open != null ? summary.open : '–'} · 답변 {summary.answered != null ? summary.answered : '–'} · 해당없음 {summary.na != null ? summary.na : '–'}
          {summary.by_priority && summary.by_priority['1'] != null && (
            <span> · 제출 차단(1순위) {summary.by_priority['1']}</span>
          )}
        </div>
      )}

      {loading && <Empty title="불러오는 중…" />}
      {!loading && cards.length === 0 && (
        <Empty title="아직 요청이 없습니다"
          note="RAlly가 문서를 분석하면서 회사만 아는 정보를 여기로 요청합니다. (요청 API가 아직 준비되지 않았다면 서버 연결 후 표시됩니다)" />
      )}

      {cards.map((c) => (
        <div key={c.id} className="ai-card" onClick={() => setActive(c)}>
          <div className="ai-card__top">
            <span className={'ai-chip ai-chip--' + (c.role || 'ra')}>{ROLE_LABEL[c.role] || c.role}</span>
            {c.priority === 1 && <span className="ai-chip ai-chip--coral">긴급</span>}
            <span className="ai-card__doc">{c.doc_code || ''}</span>
            <span className="ai-card__status">{STATUS_LABEL[c.status] || c.status}</span>
          </div>
          <div className="ai-card__title">{c.title}</div>
          {c.why && <div className="ai-card__why">{c.why}</div>}
          <div className="ai-card__foot">
            {c.marker_count > 0 && <span>빈칸 {c.marker_count}</span>}
            <span className="ai-linkbtn" onClick={(e) => { e.stopPropagation(); setActive(c); onOpenGuide(c); }}>가이드 보기</span>
          </div>
        </div>
      ))}
    </div>
  );
};

// ─────────────────────────────────────────────────────────
// 가이드 탭
// ─────────────────────────────────────────────────────────
const GuideTab = ({ guide, loading, card, onUseTemplate }) => {
  const [openReg, setOpenReg] = React.useState(false);

  if (loading) return <Empty title="가이드를 불러오는 중…" />;
  if (!card) return <Empty title="선택된 요청이 없습니다" note="요청 탭에서 카드를 고르면 해당 항목의 작성 가이드가 여기에 표시됩니다." />;
  if (!guide) return <Empty title="이 항목의 가이드가 아직 없습니다" note="RAlly가 근거를 갖고 있지 않으면 지어내지 않습니다. 규정 원문·표준 예시가 준비되면 표시됩니다." />;

  const t = guide.template || {};
  return (
    <div className="ai-scroll">
      <div className="ai-guide__title">{guide.title}</div>

      {/* ① 평문 설명 */}
      {guide.plain && (
        <div className="ai-sec">
          <div className="ai-sec__h">① 쉬운 설명</div>
          <div className="ai-sec__b">{guide.plain}</div>
        </div>
      )}

      {/* ② 빈 템플릿 */}
      <div className="ai-sec">
        <div className="ai-sec__h">② 빈 템플릿</div>
        {t.type === 'table' && t.headers && (
          <div className="ai-tablewrap">
            <table className="ai-table ai-table--ro">
              <thead><tr>{t.headers.map((h, i) => <th key={i}>{h}</th>)}</tr></thead>
              <tbody>
                {Array.from({ length: Math.max(1, t.rows || 2) }).map((_, i) => (
                  <tr key={i}>{t.headers.map((h, j) => <td key={j}>&nbsp;</td>)}</tr>
                ))}
              </tbody>
            </table>
          </div>
        )}
        {t.type === 'outline' && (
          <ul className="ai-bullets">{(t.bullets || []).map((b, i) => <li key={i}>{b}</li>)}</ul>
        )}
        {t.type === 'text' && <pre className="ai-pre">{t.skeleton || ''}</pre>}
        {!t.type && <div className="ai-hint">템플릿이 제공되지 않았습니다.</div>}
        {t.type && (
          <Button variant="soft" size="sm" onClick={() => onUseTemplate(guide)}>이 템플릿으로 채우기</Button>
        )}
      </div>

      {/* ③ 작성 예시 */}
      {guide.examples && guide.examples.length > 0 && (
        <div className="ai-sec">
          <div className="ai-sec__h">③ 작성 예시</div>
          {guide.examples.map((ex, i) => (
            <div key={i} className="ai-ex">
              <div className="ai-ex__head">
                <span className={'ai-chip ' + (ex.source === 'own' ? 'ai-chip--coral' : 'ai-chip--ra')}>
                  {ex.source === 'own' ? '우리 회사 이전 문서' : '업계 표준 문구'}
                </span>
                {ex.label && <span className="ai-ex__label">{ex.label}</span>}
              </div>
              <div className="ai-ex__body">{ex.text}</div>
            </div>
          ))}
        </div>
      )}

      {/* ④ 체크리스트 */}
      {guide.checklist && guide.checklist.length > 0 && (
        <div className="ai-sec">
          <div className="ai-sec__h">④ 체크리스트</div>
          <ul className="ai-checks">{guide.checklist.map((c, i) => <li key={i}><Icon name="check" size={12} /> <span>{c}</span></li>)}</ul>
        </div>
      )}

      {/* ⑤ 과거 보완 사례 */}
      {guide.common_findings && guide.common_findings.length > 0 && (
        <div className="ai-sec ai-sec--warn">
          <div className="ai-sec__h">⑤ 과거 보완 요구 사례</div>
          <ul className="ai-bullets">{guide.common_findings.map((c, i) => <li key={i}>{c}</li>)}</ul>
        </div>
      )}

      {/* 규정 원문(접힘) */}
      {guide.regulation && (
        <div className="ai-sec">
          <div className="ai-sec__h ai-sec__h--tog" onClick={() => setOpenReg((v) => !v)}>
            <Icon name={openReg ? 'chev_down' : 'chev_right'} size={12} />
            규정 원문 · {guide.regulation.source}{guide.regulation.clause ? ' ' + guide.regulation.clause : ''}
          </div>
          {openReg && <pre className="ai-pre ai-pre--reg">{guide.regulation.text || '(원문 없음)'}</pre>}
        </div>
      )}
    </div>
  );
};

// ─────────────────────────────────────────────────────────
// 근거(cite) — 접이식
// ─────────────────────────────────────────────────────────
const SRC_LABEL = { regulation: '규정', guide: '가이드', product: '제품지식', catalog: '카탈로그', live: '내 데이터' };

const Cites = ({ cites }) => {
  const [open, setOpen] = React.useState(false);
  if (!cites || !cites.length) return null;
  return (
    <div className="ai-cites" style={{ marginTop: 6 }}>
      <div className="ai-sec__h ai-sec__h--tog" style={{ cursor: 'pointer', fontSize: 11 }}
        onClick={() => setOpen((v) => !v)}>
        <Icon name={open ? 'chev_down' : 'chev_right'} size={11} />
        <span>근거 {cites.length}건</span>
      </div>
      {open && (
        <ul className="ai-bullets" style={{ margin: '4px 0 0', paddingLeft: 14, fontSize: 11, lineHeight: 1.5 }}>
          {cites.map((c, i) => (
            <li key={i}>
              <span className="ai-chip" style={{ marginRight: 4 }}>{SRC_LABEL[c.source] || c.source || '근거'}</span>
              <b>{c.cite || ''}</b>{c.title ? ' — ' + c.title : ''}
            </li>
          ))}
        </ul>
      )}
    </div>
  );
};

// ─────────────────────────────────────────────────────────
// 대화 탭 (+ 인터뷰 흐름)
// ─────────────────────────────────────────────────────────
const ChatTab = ({ ctx, screen, go, onAsk, trackId, docId }) => {
  const [msgs, setMsgs] = React.useState([
    { role: 'bot', text: '무엇을 도와드릴까요? 현재 화면·트랙을 보고 근거를 갖고 답합니다.\n예: "우리 AI 제품은 어떤 별표가 적용돼?", "지금 우리 트랙 상태 어때?", "제품표준서 제조방법 어떻게 써?"' },
  ]);
  const [input, setInput] = React.useState('');
  const [busy, setBusy] = React.useState(false);
  const [sid, setSid] = React.useState(null);        // 대화 세션(멀티턴)
  const [iv, setIv] = React.useState(null);          // 인터뷰 세션 {session_id, question, progress}
  const [ivAns, setIvAns] = React.useState('');
  const [backend, setBackend] = React.useState(null);       // 'api' | 'cli' | 'none'
  const [hintOff, setHintOff] = React.useState(hintDismissed);
  const endRef = React.useRef(null);

  React.useEffect(() => { if (endRef.current) endRef.current.scrollIntoView({ block: 'end' }); }, [msgs, busy, iv]);

  const send = (t) => {
    const q = (t != null ? t : input).trim();
    if (!q || busy) return;
    setMsgs((m) => m.concat([{ role: 'me', text: q }]));
    setInput(''); setBusy(true);
    jpost('/api/assistant/chat', {
      message: q,
      session_id: sid || undefined,
      context: { track_id: trackId, doc_id: docId, page: screen },
    }).then((d) => {
      setBusy(false);
      if (!d) {
        setMsgs((m) => m.concat([{ role: 'bot', text: '어시스턴트 서버에 연결하지 못했습니다. (백엔드 /api/assistant/chat 준비 전이거나 응답 없음)' }]));
        return;
      }
      if (d.session_id && d.session_id !== sid) setSid(d.session_id);
      if (d.backend) setBackend(d.backend);
      setMsgs((m) => m.concat([{
        role: 'bot', text: d.reply || '(빈 응답)',
        actions: d.actions || [], asks: d.asks || [], cites: d.cites || [],
        backend: d.backend || null, degraded: !!d.degraded,
      }]));
    });
  };

  const doAction = (a) => {
    const p = a.payload || {};
    if (p.track_id) window.__RALLY_TRACK = p.track_id;
    if (p.doc_id) window.__RALLY_DOC = p.doc_id;
    if (a.kind === 'navigate' || a.kind === 'screen' || p.screen) { go(p.screen || a.kind); return; }
    if (a.kind === 'interview') { startInterview(p.topic); return; }
    if (a.kind === 'api' && p.url) {
      setBusy(true);
      jpost(p.url, p.body || {}).then((d) => {
        setBusy(false);
        setMsgs((m) => m.concat([{ role: 'bot', text: d && d.reply ? d.reply : (d ? '실행했습니다.' : '실행에 실패했습니다.') }]));
      });
      return;
    }
    // 알 수 없는 kind — 지어내지 말고 정직하게
    setMsgs((m) => m.concat([{ role: 'bot', text: '이 동작(' + a.kind + ')은 아직 화면에서 지원하지 않습니다.' }]));
  };

  const startInterview = (topic) => {
    setBusy(true);
    jpost('/api/interview/start', { track_id: trackId, topic: topic }).then((d) => {
      setBusy(false);
      if (!d || !d.question) {
        setMsgs((m) => m.concat([{ role: 'bot', text: '인터뷰를 시작하지 못했습니다. (백엔드 /api/interview/start 미준비)' }]));
        return;
      }
      setIv({ session_id: d.session_id, question: d.question, progress: d.progress });
    });
  };

  const answerInterview = () => {
    if (!iv || !ivAns.trim()) return;
    setBusy(true);
    const a = ivAns.trim();
    setMsgs((m) => m.concat([{ role: 'me', text: a }]));
    setIvAns('');
    jpost('/api/interview/answer', { session_id: iv.session_id, answer: a }).then((d) => {
      setBusy(false);
      if (!d) { setMsgs((m) => m.concat([{ role: 'bot', text: '답변 저장에 실패했습니다.' }])); setIv(null); return; }
      if (d.done) {
        setIv(null);
        setMsgs((m) => m.concat([{ role: 'bot', text: '인터뷰가 끝났습니다.' + (d.applied ? ' 입력한 정보를 문서에 반영했습니다.' : '') }]));
        return;
      }
      setIv({ session_id: iv.session_id, question: d.question, progress: d.progress });
    });
  };

  return (
    <div className="ai-chat">
      <div className="ai-chat__thread">
        {msgs.map((m, i) => (
          <div key={i} className={'ai-msg ai-msg--' + m.role}>
            <div className="ai-msg__bubble">{m.text}</div>
            {m.role === 'bot' && m.degraded && <BackendBadge backend={m.backend} degraded={m.degraded} />}
            {m.actions && m.actions.length > 0 && (
              <div className="ai-msg__actions">
                {m.actions.map((a, j) => (
                  <button key={j} className="ai-actionbtn" onClick={() => doAction(a)}>{a.label}</button>
                ))}
              </div>
            )}
            {m.cites && m.cites.length > 0 && <Cites cites={m.cites} />}
            {m.asks && m.asks.length > 0 && (
              <div className="ai-msg__asks">
                {m.asks.map((c, j) => (
                  <div key={j} className="ai-card ai-card--sm" onClick={() => onAsk(c)}>
                    <div className="ai-card__top">
                      <span className={'ai-chip ai-chip--' + (c.role || 'ra')}>{ROLE_LABEL[c.role] || c.role}</span>
                      <span className="ai-card__doc">{c.doc_code || ''}</span>
                    </div>
                    <div className="ai-card__title">{c.title}</div>
                    <div className="ai-card__foot"><span className="ai-linkbtn">답변하기 →</span></div>
                  </div>
                ))}
              </div>
            )}
          </div>
        ))}
        {busy && (
          <div className="ai-msg ai-msg--bot">
            <div className="ai-msg__bubble ai-msg__bubble--wait">
              <span className="ai-spinner" style={{
                display: 'inline-block', width: 10, height: 10, marginRight: 6,
                border: '2px solid rgba(0,0,0,.18)', borderTopColor: 'rgba(0,0,0,.55)',
                borderRadius: '50%', animation: 'ai-spin .8s linear infinite', verticalAlign: '-1px',
              }} />
              생각 중… (규정·가이드 근거를 찾고 있습니다. 수 초 걸릴 수 있어요)
            </div>
          </div>
        )}
        <div ref={endRef} />
      </div>

      {iv ? (
        <div className="ai-interview">
          <div className="ai-interview__bar">
            <span>제품 인터뷰</span>
            {iv.progress && <span>{iv.progress.step} / {iv.progress.total}</span>}
          </div>
          {iv.progress && iv.progress.total ? (
            <Progress value={Math.round((iv.progress.step / iv.progress.total) * 100)} size="sm" />
          ) : null}
          <div className="ai-interview__q">{iv.question.text}</div>
          {iv.question.help && <div className="ai-hint">{iv.question.help}</div>}
          {iv.question.input_type === 'choice' && (iv.question.options || []).length > 0 ? (
            <div className="ai-choices">
              {iv.question.options.map((o) => (
                <label key={o} className={'ai-choice' + (ivAns === o ? ' ai-choice--on' : '')}>
                  <input type="radio" name="ivq" checked={ivAns === o} onChange={() => setIvAns(o)} />
                  <span>{o}</span>
                </label>
              ))}
            </div>
          ) : (
            <textarea className="ai-textarea" rows={3} value={ivAns} onChange={(e) => setIvAns(e.target.value)} />
          )}
          <div className="ai-form__foot">
            <Button variant="accent" size="sm" onClick={answerInterview} disabled={busy || !ivAns.trim()}>다음</Button>
            <Button variant="ghost" size="sm" onClick={() => { setIv(null); setIvAns(''); }}>중단</Button>
          </div>
        </div>
      ) : (
        <div>
          {backend === 'cli' && !hintOff && (
            <ApiKeyHint onClose={() => { dismissHint(); setHintOff(true); }} />
          )}
        <div className="ai-composer">
          <textarea
            value={input}
            onChange={(e) => setInput(e.target.value)}
            onKeyDown={(e) => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); send(); } }}
            placeholder="질문하거나 시켜보세요 (Enter 전송 / Shift+Enter 줄바꿈)"
            rows={2}
          />
          <button className="ai-send" onClick={() => send()} disabled={busy || !input.trim()} title="보내기">
            <Icon name="arrow_right" size={16} />
          </button>
        </div>
        </div>
      )}
    </div>
  );
};

// ─────────────────────────────────────────────────────────
// 패널 본체
// ─────────────────────────────────────────────────────────
const AssistantPanel = ({ screen, go, open, onToggle }) => {
  const [tab, setTab] = React.useState('chat');
  const [ctx, setCtx] = React.useState(null);
  const [ctxTried, setCtxTried] = React.useState(false);

  const [trackId, setTrackId] = React.useState(window.__RALLY_TRACK || null);
  const [docId, setDocId] = React.useState(window.__RALLY_DOC || null);

  const [cards, setCards] = React.useState([]);
  const [summary, setSummary] = React.useState(null);
  const [loadingCards, setLoadingCards] = React.useState(false);
  const [filters, setFilters] = React.useState({ role: '', status: 'open', doc_id: '', priority: '' });
  const [active, setActive] = React.useState(null);

  const [guide, setGuide] = React.useState(null);
  const [loadingGuide, setLoadingGuide] = React.useState(false);
  const [seed, setSeed] = React.useState(null);

  const [toast, setToast] = React.useState('');
  React.useEffect(() => {
    window.RAlly.__aiToast = (t) => { setToast(t); setTimeout(() => setToast(''), 3200); };
  }, []);

  // 화면 전환 시 컨텍스트(트랙·문서) 재해석
  React.useEffect(() => {
    const t = window.__RALLY_TRACK || null;
    const d = screen === 'editor' ? (window.__RALLY_DOC || null) : null;
    setTrackId(t);
    setDocId(d);
    // 화면이 바뀌면 열어 둔 답변 폼은 닫는다(다른 문서의 폼이 남아 있지 않도록)
    setActive(null);
    setSeed(null);
    // 에디터에서 문서를 열면 요청 탭을 해당 문서로 자동 필터
    setFilters((f) => ({ ...f, doc_id: d || '' }));
  }, [screen]);

  // 컨텍스트 헤더
  React.useEffect(() => {
    if (!open) return;
    const qs = [];
    if (trackId) qs.push('track_id=' + encodeURIComponent(trackId));
    if (docId) qs.push('doc_id=' + encodeURIComponent(docId));
    qs.push('page=' + encodeURIComponent(screen));
    jget('/api/assistant/context?' + qs.join('&')).then((d) => { setCtx(d); setCtxTried(true); });
  }, [open, screen, trackId, docId]);

  // 요청 목록
  const loadCards = React.useCallback(() => {
    if (!open || !trackId) { setCards([]); setSummary(null); return; }
    setLoadingCards(true);
    const qs = ['track_id=' + encodeURIComponent(trackId)];
    if (filters.role) qs.push('role=' + filters.role);
    if (filters.status) qs.push('status=' + filters.status);
    if (filters.doc_id) qs.push('doc_id=' + encodeURIComponent(filters.doc_id));
    if (filters.priority) qs.push('priority=' + filters.priority);
    jget('/api/rfi/list?' + qs.join('&')).then((d) => {
      setLoadingCards(false);
      setCards((d && d.cards) || []);
      setSummary((d && d.summary) || null);
    });
  }, [open, trackId, filters.role, filters.status, filters.doc_id, filters.priority]);

  React.useEffect(() => { loadCards(); }, [loadCards]);

  // 선택 카드의 가이드 — /api/rfi/{id}가 카드 컨텍스트를 반영한 가이드를 함께 준다
  React.useEffect(() => {
    if (!active) { setGuide(null); return; }
    setLoadingGuide(true);
    const q = active.track_id ? ('?track_id=' + encodeURIComponent(active.track_id)) : '';
    jget('/api/rfi/' + encodeURIComponent(active.id) + q).then((d) => {
      setLoadingGuide(false);
      setGuide((d && d.guide) || null);
    });
  }, [active]);

  const openCard = (c) => { setActive(c); setSeed(null); setTab('rfi'); };

  const useTemplate = (g) => {
    const t = (g && g.template) || {};
    if (t.type === 'table') setSeed({ rows: Array.from({ length: Math.max(1, t.rows || 3) }, () => (t.headers || []).map(() => '')) });
    else if (t.type === 'outline') setSeed({ value: (t.bullets || []).map((b) => '- ' + b + '\n  ').join('\n') });
    else setSeed({ value: t.skeleton || '' });
    setTab('rfi');
  };

  const openCount = (summary && summary.open != null) ? summary.open
    : (ctx && ctx.open_rfi != null ? ctx.open_rfi : cards.filter((c) => c.status === 'open').length);

  if (!open) {
    return (
      <button className="ai-tab-closed" onClick={() => onToggle(true)} title="AI 어시스턴트 열기">
        <Icon name="sparkles" size={16} />
        <span className="ai-tab-closed__label">AI 어시스턴트</span>
        {openCount > 0 && <span className="ai-tab-closed__badge">{openCount}</span>}
      </button>
    );
  }

  return (
    <aside className="ai-panel">
      <div className="ai-panel__head">
        <div className="ai-panel__brand">
          <Icon name="sparkles" size={15} />
          <span>AI 어시스턴트</span>
        </div>
        <button className="ai-collapse" onClick={() => onToggle(false)} title="패널 접기">
          <Icon name="chev_right" size={16} />
        </button>
      </div>

      {/* 컨텍스트 바 */}
      <div className="ai-ctx">
        {ctx ? (
          <React.Fragment>
            <div className="ai-ctx__row">
              <span className="ai-ctx__k">트랙</span>
              <span className="ai-ctx__v">{ctx.track ? ctx.track.name : '선택 안 됨'}</span>
              {ctx.track && ctx.track.progress != null && <span className="ai-ctx__pct">{ctx.track.progress}%</span>}
            </div>
            {ctx.track && ctx.track.progress != null && <Progress value={ctx.track.progress} size="sm" />}
            <div className="ai-ctx__row">
              <span className="ai-ctx__k">문서</span>
              <span className="ai-ctx__v">{ctx.doc ? ctx.doc.name : '없음'}</span>
            </div>
            {ctx.next_action && <div className="ai-ctx__next"><b>다음 할 일</b> {ctx.next_action}</div>}
          </React.Fragment>
        ) : (
          <div className="ai-ctx__row">
            <span className="ai-ctx__v ai-ctx__v--dim">
              {ctxTried ? '컨텍스트 정보 없음 (서버 미연결)' : '컨텍스트 확인 중…'}
            </span>
          </div>
        )}
      </div>

      {/* 탭 */}
      <div className="ai-tabs">
        <button className={'ai-tabbtn' + (tab === 'chat' ? ' ai-tabbtn--on' : '')} onClick={() => setTab('chat')}>대화</button>
        <button className={'ai-tabbtn' + (tab === 'rfi' ? ' ai-tabbtn--on' : '')} onClick={() => setTab('rfi')}>
          요청{openCount ? ' (' + openCount + ')' : ''}
        </button>
        <button className={'ai-tabbtn' + (tab === 'guide' ? ' ai-tabbtn--on' : '')} onClick={() => setTab('guide')}>가이드</button>
      </div>

      <div className="ai-body">
        {tab === 'chat' && (
          <ChatTab ctx={ctx} screen={screen} go={go} trackId={trackId} docId={docId} onAsk={openCard} />
        )}
        {tab === 'rfi' && (
          <RfiTab
            cards={cards} summary={summary} loading={loadingCards}
            filters={filters} setFilters={setFilters}
            active={active} setActive={setActive}
            reload={loadCards} seed={seed}
            onOpenGuide={() => setTab('guide')}
          />
        )}
        {tab === 'guide' && (
          <GuideTab guide={guide} loading={loadingGuide} card={active} onUseTemplate={useTemplate} />
        )}
      </div>

      {toast && <div className="ai-toast">{toast}</div>}
    </aside>
  );
};

window.RAlly.AssistantPanel = AssistantPanel;
