// intake.jsx — 고객 인테이크(온보딩): 회사 → 여정(신규/갱신) → 실행

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

// ── 판정 인터뷰: 앱이 질문을 하나씩 던져 정보를 받아 판정에 사용 ──────────
const IV_QUESTIONS = [
  { key: 'name', type: 'text', q: '제품(품목)의 이름은 무엇인가요?', ph: '예: 리스파이어 DTx',
    why: '문서 표제부·품목명에 사용됩니다.', required: true },
  { key: 'indication', type: 'textarea', q: '제품의 용도와 핵심 기능을 설명해 주세요.',
    ph: '예: 만성호흡기질환 가정 호흡재활 디지털치료기기 소프트웨어, AI 분석 포함',
    why: '설명을 근거로 디지털·AI 여부를 1차 자동 판정합니다.' },
  { key: 'digital', type: 'choice', q: '소프트웨어 의료기기(SaMD·디지털)인가요?',
    options: [['yes', '예'], ['no', '아니오'], ['unknown', '모르겠어요 — 설명으로 자동 판정']],
    why: '별표2·별표3 적용 여부를 결정합니다.' },
  { key: 'ai', type: 'choice', q: '인공지능/머신러닝(AI/ML) 기능이 포함되나요?',
    options: [['yes', '예'], ['no', '아니오'], ['unknown', '모르겠어요 — 설명으로 자동 판정']],
    why: '별표4(AI 제어조치) 적용 여부를 결정합니다.' },
  { key: '등급', type: 'choice', q: '의료기기 등급은 무엇인가요?',
    options: [['1', '1등급'], ['2', '2등급'], ['3', '3등급'], ['4', '4등급'], ['', '모르겠어요']],
    why: '심사 범위·문서 구성을 결정합니다. (공식 품목분류표 기준 — 자동 판정 불가)' },
  { key: '품목분류', type: 'text', q: '품목분류번호를 알려주세요.', finder: true,
    ph: '예: E01020.01   (모르면 아래 “찾기 도우미”로 좁혀보세요)',
    why: '대상 품목을 확인합니다. 디지털 SW는 E코드(대분류 E·임상영역·기능)로 분류됩니다.' },
  { key: '심사구분', type: 'choice', q: '신규 취득인가요, 갱신 심사인가요?',
    options: [['신규', '신규 취득'], ['갱신', '갱신 심사']],
    why: '신규/갱신 워크플로를 분기합니다.' },
];

// 식약처 의료기기 소프트웨어(SaMD) 품목분류 — 대분류 E, 임상영역별 중분류 11개(웹 검증, 2025 고시).
// 소분류(끝번호)·등급은 임상영역+기능+등급 조합으로 정해지므로 식약처 확정 필요. 확인된 예시만 subs에 수록.
const SW_AREAS = [
  { code: 'E01000', name: '심혈관 진료용', kw: '심혈관·심장·심전도·혈관·ASCVD·순환기',
    subs: [['E01010.01', '심혈관영상치료계획'], ['E01020.01', '심전도분석'], ['E01120.01', '심혈관영상검출·진단보조']] },
  { code: 'E02000', name: '치의학 진료용', kw: '치과·구강·치아',
    subs: [['E02010.01', '치과영상전송(1등급)'], ['E02010.02', '치과영상전송(2등급)']] },
  { code: 'E03000', name: '이비인후과학 진료용', kw: '귀·코·목·청력·이비인후', subs: [] },
  { code: 'E04000', name: '위장병학·비뇨의학 진료용', kw: '소화기·위장·대장·비뇨·내시경', subs: [] },
  { code: 'E05000', name: '병원 진료용(일반)', kw: '병원일반·통합·범용', subs: [] },
  { code: 'E06000', name: '신경과학 진료용', kw: '뇌·신경·뇌파·EEG·뇌졸중', subs: [] },
  { code: 'E07000', name: '산부인과학 진료용', kw: '산부인과·태아·자궁·임신', subs: [] },
  { code: 'E08000', name: '안과학 진료용', kw: '눈·안과·망막·안저·시력', subs: [] },
  { code: 'E09000', name: '정형외과학 진료용', kw: '뼈·관절·척추·정형외과·골', subs: [] },
  { code: 'E10000', name: '재활의학 진료용', kw: '재활·물리치료·운동', subs: [] },
  { code: 'E11000', name: '방사선종양학·영상의학 진료용', kw: '영상의학·CT·MRI·X선·방사선치료·판독', subs: [] },
];
const SW_FUNCS = [
  ['검출·진단보조', '영상/데이터에서 이상을 검출해 진단 보조 (…검출·진단보조소프트웨어)'],
  ['치료계획', '치료 계획 수립·보조 (…영상치료계획소프트웨어)'],
  ['신호분석', '생체신호(심전도·뇌파 등) 분석 (…분석소프트웨어)'],
  ['영상전송·저장', '영상 전송·저장·표시 (…영상전송장치소프트웨어)'],
  ['기타·모름', '위에 해당하지 않거나 확실치 않음'],
];

const _fbtn = (on) => ({
  fontFamily: 'inherit', fontSize: 11.5, padding: '5px 9px', borderRadius: 6, cursor: 'pointer',
  border: `1px solid ${on ? 'var(--coral)' : 'var(--line)'}`,
  background: on ? 'var(--coral-soft)' : 'var(--surface)', color: on ? 'var(--coral-2)' : 'var(--ink)',
});

// 품목 찾기 도우미: 임상영역+기능을 물어 중분류(E코드) 후보로 좁힘. 소분류·등급은 식약처 확정.
const ClassFinder = ({ onPick }) => {
  const [area, setArea] = React.useState(null);
  const [func, setFunc] = React.useState(null);
  const a = SW_AREAS.find((x) => x.code === area);
  return (
    <div style={{ marginTop: 10, padding: 12, border: '1px dashed var(--line)', borderRadius: 8, background: 'var(--bg, #F6F4EF)' }}>
      <div style={{ fontSize: 12.5, fontWeight: 700, color: 'var(--navy)', marginBottom: 4 }}>품목 찾기 도우미</div>
      <div className="muted" style={{ fontSize: 11.5, marginBottom: 10 }}>
        디지털 소프트웨어(SaMD)는 대분류 <b>E(소프트웨어)</b> · 임상영역별 중분류 · 기능별 소분류로 나뉩니다. 아래에서 좁혀보세요.
      </div>

      <div style={{ fontSize: 11.5, fontWeight: 700, marginBottom: 6 }}>① 어느 임상영역인가요?</div>
      <div className="row" style={{ gap: 6, flexWrap: 'wrap', marginBottom: 12 }}>
        {SW_AREAS.map((x) => (
          <button key={x.code} onClick={() => setArea(x.code)} title={x.kw} style={_fbtn(area === x.code)}>{x.name}</button>
        ))}
      </div>

      {area && (
        <div>
          <div style={{ fontSize: 11.5, fontWeight: 700, marginBottom: 6 }}>② 핵심 기능은?</div>
          <div className="row" style={{ gap: 6, flexWrap: 'wrap', marginBottom: 12 }}>
            {SW_FUNCS.map(([k, desc]) => (
              <button key={k} onClick={() => setFunc(k)} title={desc} style={_fbtn(func === k)}>{k}</button>
            ))}
          </div>
        </div>
      )}

      {area && (
        <div style={{ borderTop: '1px dashed var(--line)', paddingTop: 10 }}>
          <div style={{ fontSize: 12, marginBottom: 3 }}>대분류 <b>E</b> · 의료기기 소프트웨어(SaMD)</div>
          <div style={{ fontSize: 12.5, marginBottom: 6 }}>중분류 후보 <b style={{ color: 'var(--coral-2)' }}>{a.code}</b> · {a.name} 소프트웨어</div>
          {a.subs.length > 0 ? (
            <div style={{ fontSize: 11.5, color: 'var(--ink-2)', marginBottom: 6, lineHeight: 1.6 }}>
              이 영역의 실제 소분류 예: {a.subs.map(([c, n]) => c + ' ' + n).join(' · ')}
            </div>
          ) : (
            <div style={{ fontSize: 11.5, color: 'var(--ink-2)', marginBottom: 6 }}>
              이 영역의 소분류(끝번호)는 식약처 품목분류에서 확인하세요.
            </div>
          )}
          <div className="muted" style={{ fontSize: 11, marginBottom: 8, lineHeight: 1.6 }}>
            ⚠ 정확한 소분류 끝번호·등급은 임상영역+기능+등급 조합으로 정해집니다. <b>지어내지 않습니다</b> — 식약처 의료기기 품목분류에서 최종 확인하세요.
          </div>
          <div className="row" style={{ gap: 10, flexWrap: 'wrap', alignItems: 'center' }}>
            <Button variant="soft" size="sm" onClick={() => onPick(a.code + ' ' + a.name + ' 소프트웨어 (후보·소분류/등급 식약처 확인)')}>이 후보를 입력란에 넣기</Button>
            <a href="https://udiportal.mfds.go.kr/search/data/P02_01" target="_blank" rel="noopener noreferrer" style={{ fontSize: 11.5, color: 'var(--coral-2)' }}>식약처 품목분류 조회 ↗</a>
          </div>
        </div>
      )}
    </div>
  );
};

// 임상 필요성 '안내'(참고용) — 확정 아님. Q1~Q4 → 동등/개량/신제품 경로 안내.
const CG_TONE = {
  green: { bg: '#EAF7EF', bd: '#22C55E', fg: '#15924A' },
  amber: { bg: '#FFF6E5', bd: '#F5A623', fg: '#9A6800' },
  coral: { bg: 'var(--coral-soft)', bd: 'var(--coral)', fg: 'var(--coral-2)' },
};
const CG_DS = {
  req: { t: '필수', c: '#15924A', b: '#EAF7EF' },
  cond: { t: '조건부', c: '#9A6800', b: '#FFF6E5' },
  exempt: { t: '면제', c: 'var(--ink-3)', b: '#F1F2F4' },
};

const ClinicalGuide = ({ aiHint }) => {
  const [open, setOpen] = React.useState(false);
  const [ans, setAns] = React.useState(() => (aiHint ? { ai_decision: 'yes' } : {}));
  const [res, setRes] = React.useState(null);
  const [busy, setBusy] = React.useState(false);
  const set = (k, v) => { setAns((s) => ({ ...s, [k]: v })); setRes(null); };
  const canAssess = ans.similar_exists === 'no'
    || (ans.similar_exists === 'yes' && ans.same_purpose === 'no')
    || (ans.similar_exists === 'yes' && ans.same_purpose === 'yes' && !!ans.diff_level);
  const run = () => {
    setBusy(true);
    fetch('/api/clinical-guide', {
      method: 'POST', headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ answers: ans }),
    }).then((r) => r.json()).then((d) => { setRes(d); setBusy(false); }).catch(() => setBusy(false));
  };

  const Q = ({ label, k, opts }) => (
    <div style={{ marginBottom: 10 }}>
      <div style={{ fontSize: 12.5, fontWeight: 700, color: 'var(--navy)', marginBottom: 5 }}>{label}</div>
      <div className="row" style={{ gap: 6, flexWrap: 'wrap' }}>
        {opts.map(([v, t]) => <button key={v} onClick={() => set(k, v)} style={_fbtn(ans[k] === v)}>{t}</button>)}
      </div>
    </div>
  );

  return (
    <div style={{ marginTop: 16, borderTop: '1px dashed var(--line)', paddingTop: 14 }}>
      <button onClick={() => setOpen((o) => !o)}
        style={{ fontFamily: 'inherit', fontSize: 14, fontWeight: 700, color: 'var(--navy)', background: 'none', border: 'none', cursor: 'pointer', padding: 0 }}>
        🩺 임상 필요성 안내 (참고용) {open ? '▾' : '▸'}
      </button>
      {!open && <div className="muted" style={{ fontSize: 12, marginTop: 4 }}>“우리도 임상해야 하나요?”를 몇 가지 질문으로 안내합니다. (확정 아님)</div>}

      {open && (
        <div style={{ marginTop: 12 }}>
          {/* 안내 원칙(면책) 배너 */}
          <div style={{ background: '#FFF6E5', border: '1px solid #F5A623', borderRadius: 10, padding: '10px 14px', marginBottom: 14, fontSize: 12, color: '#6B4E00', lineHeight: 1.55 }}>
            ⚠ <b>RAlly는 임상 필요 여부를 확정하지 않고 안내만 합니다.</b> 최종 판단은 식약처 심사에서 이루어지며, 아래는 참고용입니다. RAlly는 GMP 문서를 생성하되 임상시험·허가 제출 자료는 생성하지 않습니다.
          </div>

          <Q label="Q1. 시장에 비슷한 제품이 이미 허가받아 팔리고 있나요?" k="similar_exists"
             opts={[['yes', '예 · 있어요'], ['no', '아니오 · 없어요']]} />
          {ans.similar_exists === 'yes' && (
            <Q label="Q2. 그 제품과 “무엇을 위해, 어떻게 작동하는지”가 같나요?" k="same_purpose"
               opts={[['yes', '예 · 목적·작동방식 같음'], ['no', '아니오 · 다름']]} />
          )}
          {ans.similar_exists === 'yes' && ans.same_purpose === 'yes' && (
            <Q label="Q3. 성능·재료·사용법도 똑같나요, 아니면 개선했나요?" k="diff_level"
               opts={[['same', '똑같음'], ['improved', '개선함 · 더 정확/새 기술/사용법 변경']]} />
          )}
          <Q label="Q4. 제품이 스스로 진단·판단을 내리나요? (SaMD·AI)" k="ai_decision"
             opts={[['yes', '예 · 스스로 진단·판단'], ['no', '아니오 · 데이터 표시만']]} />

          <div className="row" style={{ gap: 10, alignItems: 'center', marginTop: 6 }}>
            <Button variant="primary" onClick={run} disabled={!canAssess || busy}>
              {busy ? '안내 준비 중…' : '임상 필요성 안내 받기 →'}
            </Button>
            {!canAssess && <span className="muted" style={{ fontSize: 11.5 }}>Q1~Q3에 답하면 경로를 안내합니다.</span>}
          </div>

          {res && res.complete && (
            <div style={{ marginTop: 14 }}>
              <div style={{ background: CG_TONE[res.tone].bg, border: `1.5px solid ${CG_TONE[res.tone].bd}`, borderRadius: 12, padding: '14px 16px' }}>
                <div className="row" style={{ gap: 8, alignItems: 'center', marginBottom: 4, flexWrap: 'wrap' }}>
                  <span style={{ fontSize: 11.5, fontWeight: 800, color: '#fff', background: CG_TONE[res.tone].bd, padding: '3px 10px', borderRadius: 6 }}>{res.branch_label}</span>
                  <span style={{ fontSize: 15, fontWeight: 800, color: CG_TONE[res.tone].fg }}>{res.headline}</span>
                </div>
                <div style={{ fontSize: 13, color: 'var(--ink-2)', marginBottom: res.ai_note ? 6 : 0 }}>{res.clinical}</div>
                {res.ai_note && (
                  <div style={{ fontSize: 12, color: '#2a5a8a', background: '#E8F2FD', borderRadius: 8, padding: '8px 11px', marginTop: 6 }}>🧠 {res.ai_note}</div>
                )}
              </div>

              <div style={{ fontSize: 12.5, fontWeight: 700, color: 'var(--navy)', margin: '14px 0 6px' }}>이 경로에서 필요할 수 있는 문서 (안내)</div>
              {res.docs.map((d, i) => (
                <div key={i} className="row" style={{ gap: 10, alignItems: 'flex-start', padding: '8px 0', borderTop: i ? '1px solid var(--line-soft, #eef1f4)' : 'none' }}>
                  <span style={{ fontSize: 10.5, fontWeight: 800, padding: '2px 8px', borderRadius: 5, whiteSpace: 'nowrap', color: CG_DS[d.state].c, background: CG_DS[d.state].b, marginTop: 1 }}>{CG_DS[d.state].t}</span>
                  <div style={{ flex: 1 }}>
                    <div style={{ fontSize: 13, fontWeight: 600, color: 'var(--ink)' }}>{d.name}</div>
                    <div className="muted" style={{ fontSize: 11.5 }}>{d.note}</div>
                  </div>
                </div>
              ))}

              <div className="muted" style={{ fontSize: 11, marginTop: 12, lineHeight: 1.6 }}>
                <b>근거</b> · {(res.basis || []).join(' / ')}<br />{res.disclaimer}
              </div>
            </div>
          )}
        </div>
      )}
    </div>
  );
};

// ── 통합 프로필 입력 필드(회사·제품 전항목) ─────────────────────────
const _inp = { width: '100%', fontFamily: 'inherit', fontSize: 13, padding: '7px 10px', border: '1px solid var(--line)', borderRadius: 7 };

const ProfileField = ({ f, value, onChange, note }) => (
  <div style={{ marginBottom: 10 }}>
    <div style={{ fontSize: 11.5, fontWeight: 600, color: 'var(--ink-2)', marginBottom: 3 }}>{f.label}</div>
    {f.multiline ? (
      <textarea value={value || ''} onChange={(e) => onChange(f.key, e.target.value)} placeholder={f.example} rows={2}
        style={{ ..._inp, resize: 'vertical' }} />
    ) : (
      <input value={value || ''} onChange={(e) => onChange(f.key, e.target.value)} placeholder={f.example} style={_inp} />
    )}
    {(note || f.desc) && (
      <div className="muted" style={{ fontSize: 10.5, marginTop: 3, lineHeight: 1.45 }}>{note || f.desc}</div>
    )}
  </div>
);

// 회사·제품 전항목 폼 — 그룹별 접이식. 통합 인테이크: 처음에 모두 입력 → 전 문서 자동 반영.
const ProfileForm = ({ fields, values, onChange, title, hint, notes }) => {
  const [open, setOpen] = React.useState(true);
  const groups = {};
  (fields || []).forEach((f) => { (groups[f.group] = groups[f.group] || []).push(f); });
  const filled = (fields || []).filter((f) => String(values[f.key] || '').trim()).length;
  return (
    <div style={{ marginTop: 14, border: '1px solid var(--line)', borderRadius: 10, overflow: 'hidden' }}>
      <button onClick={() => setOpen((o) => !o)}
        style={{ width: '100%', textAlign: 'left', fontFamily: 'inherit', fontSize: 13.5, fontWeight: 700, color: 'var(--navy)', background: 'var(--bg, #F6F4EF)', border: 'none', cursor: 'pointer', padding: '10px 14px', display: 'flex', justifyContent: 'space-between' }}>
        <span>{title} <span className="muted" style={{ fontWeight: 500, fontSize: 11.5 }}>· {filled}/{(fields || []).length} 입력</span></span>
        <span>{open ? '▾' : '▸'}</span>
      </button>
      {open && (
        <div style={{ padding: 14 }}>
          {hint && <div className="muted" style={{ fontSize: 11.5, marginBottom: 10, lineHeight: 1.5 }}>{hint}</div>}
          {Object.entries(groups).map(([g, fs]) => (
            <div key={g} style={{ marginBottom: 10 }}>
              <div style={{ fontSize: 11, fontWeight: 800, color: 'var(--coral-2)', letterSpacing: '.04em', marginBottom: 6 }}>{g}</div>
              <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '0 12px' }}>
                {fs.map((f) => (
                  <div key={f.key} style={{ gridColumn: f.multiline ? '1 / -1' : 'auto' }}>
                    <ProfileField f={f} value={values[f.key]} onChange={onChange}
                      note={(notes || {})[f.key]} />
                  </div>
                ))}
              </div>
            </div>
          ))}
        </div>
      )}
    </div>
  );
};

// 기존 문서 업로드 → 슬롯 후보 추출 → 확인·반영(무확인 자동반영 금지)
const ExtractUploader = ({ onApply }) => {
  const [files, setFiles] = React.useState(null);
  const [busy, setBusy] = React.useState(false);
  const [res, setRes] = React.useState(null);
  const [picked, setPicked] = React.useState({});
  const run = () => {
    if (!files || !files.length) { alert('제품표준서·기존 문서(.docx/.hwpx)를 선택하세요'); return; }
    setBusy(true); setRes(null);
    const fd = new FormData();
    Array.from(files).forEach((f) => fd.append('files', f));
    fetch('/api/intake/extract', { method: 'POST', body: fd })
      .then((r) => r.json()).then((d) => {
        setRes(d);
        const pk = {}; Object.keys(d.candidates || {}).forEach((k) => { pk[k] = true; });
        setPicked(pk); setBusy(false);
      }).catch(() => { setRes({ ok: false, error: '추출 실패' }); setBusy(false); });
  };
  const apply = () => {
    const vals = {};
    Object.entries(res.candidates || {}).forEach(([k, v]) => { if (picked[k]) vals[k] = v.value; });
    onApply(vals);
  };
  const cand = res && res.candidates ? Object.values(res.candidates) : [];
  return (
    <div style={{ marginTop: 14, border: '1px dashed var(--line)', borderRadius: 10, padding: 14, background: 'var(--bg, #F6F4EF)' }}>
      <div style={{ fontSize: 13, fontWeight: 700, color: 'var(--navy)', marginBottom: 4 }}>📎 기존 문서로 자동 채우기 <span className="muted" style={{ fontWeight: 500, fontSize: 11 }}>(선택)</span></div>
      <div className="muted" style={{ fontSize: 11.5, marginBottom: 10, lineHeight: 1.5 }}>
        제품표준서·기존 심사문서(.docx/.hwpx)를 올리면 회사·제품 정보를 추출합니다. <b>추출값은 후보</b>이며, 확인·수정 후 반영됩니다(자동 반영 안 함).
      </div>
      <div className="row" style={{ gap: 8, alignItems: 'center' }}>
        <input type="file" accept=".docx,.hwpx" multiple onChange={(e) => setFiles(e.target.files)} style={{ fontSize: 12 }} />
        <Button variant="soft" size="sm" onClick={run} disabled={busy}>{busy ? '추출 중…' : '추출 →'}</Button>
      </div>
      {res && res.ok && cand.length > 0 && (
        <div style={{ marginTop: 12 }}>
          <div style={{ fontSize: 12, fontWeight: 700, marginBottom: 6 }}>추출된 후보 {cand.length}건 — 반영할 항목을 선택하세요</div>
          {cand.map((v) => (
            <label key={v.key} className="row" style={{ gap: 8, fontSize: 12.5, cursor: 'pointer', padding: '3px 0', alignItems: 'center' }}>
              <input type="checkbox" checked={!!picked[v.key]} onChange={(e) => setPicked((s) => ({ ...s, [v.key]: e.target.checked }))} />
              <span style={{ minWidth: 130, color: 'var(--ink-2)' }}>{v.label}</span>
              <span style={{ fontWeight: 600 }}>{v.value}</span>
            </label>
          ))}
          <Button variant="primary" size="sm" onClick={apply} style={{ marginTop: 8 }}>선택 항목 반영 →</Button>
        </div>
      )}
      {res && res.ok && cand.length === 0 && <div className="muted" style={{ fontSize: 11.5, marginTop: 8 }}>추출된 후보가 없습니다(라벨 인식 실패).</div>}
      {res && !res.ok && <div style={{ fontSize: 11.5, marginTop: 8, color: 'var(--coral-2)' }}>{res.error}</div>}
    </div>
  );
};

const Interview = ({ onDone, classifying }) => {
  const [idx, setIdx] = React.useState(0);
  const [ans, setAns] = React.useState({});
  const [finderOpen, setFinderOpen] = React.useState(false);
  React.useEffect(() => { setFinderOpen(false); }, [idx]);  // 질문 넘어가면 도우미 접기
  const q = IV_QUESTIONS[idx];
  const last = idx === IV_QUESTIONS.length - 1;
  const val = ans[q.key] === undefined ? '' : ans[q.key];
  const set = (v) => setAns((s) => ({ ...s, [q.key]: v }));
  const canNext = !q.required || String(val).trim();
  const next = () => { if (last) onDone(ans); else setIdx((i) => i + 1); };
  const prev = () => setIdx((i) => Math.max(0, i - 1));
  const pct = Math.round(((idx + 1) / IV_QUESTIONS.length) * 100);

  return (
    <div>
      <div className="row" style={{ justifyContent: 'space-between', marginBottom: 6 }}>
        <div style={{ fontWeight: 700, color: 'var(--navy)' }}>① 판정을 위한 질문 <span className="muted" style={{ fontWeight: 500, fontSize: 12 }}>{idx + 1} / {IV_QUESTIONS.length}</span></div>
        <span className="tabular" style={{ fontSize: 12, fontWeight: 700, color: 'var(--coral)' }}>{pct}%</span>
      </div>
      <Progress value={pct} />

      <div style={{ marginTop: 16 }}>
        <div style={{ fontSize: 15.5, fontWeight: 700, color: 'var(--ink)', marginBottom: 4 }}>{q.q}</div>
        <div className="muted" style={{ fontSize: 12, marginBottom: 12 }}>{q.why}</div>

        {q.type === 'text' && (
          <input value={val} onChange={(e) => set(e.target.value)} placeholder={q.ph} autoFocus
            onKeyDown={(e) => { if (e.key === 'Enter' && canNext) next(); }}
            style={{ width: '100%', fontFamily: 'inherit', fontSize: 14, padding: '10px 12px', border: '1px solid var(--line)', borderRadius: 8 }} />
        )}
        {q.finder && (
          <div style={{ marginTop: 8 }}>
            <button onClick={() => setFinderOpen((o) => !o)}
              style={{ fontFamily: 'inherit', fontSize: 12, fontWeight: 600, color: 'var(--coral-2)', background: 'none', border: 'none', cursor: 'pointer', padding: 0 }}>
              {finderOpen ? '− 찾기 도우미 닫기' : '❓ 품목분류번호를 모르세요? 찾기 도우미 열기'}
            </button>
            {finderOpen && <ClassFinder onPick={(v) => { set(v); setFinderOpen(false); }} />}
          </div>
        )}
        {q.type === 'textarea' && (
          <textarea value={val} onChange={(e) => set(e.target.value)} placeholder={q.ph} rows={3} autoFocus
            style={{ width: '100%', fontFamily: 'inherit', fontSize: 13.5, padding: '10px 12px', border: '1px solid var(--line)', borderRadius: 8, resize: 'vertical' }} />
        )}
        {q.type === 'choice' && (
          <div className="row" style={{ gap: 8, flexWrap: 'wrap' }}>
            {q.options.map(([v, label]) => {
              const on = String(val) === String(v);
              return (
                <button key={v} onClick={() => set(v)}
                  style={{
                    fontFamily: 'inherit', fontSize: 13, fontWeight: 600, padding: '9px 14px', borderRadius: 8, cursor: 'pointer',
                    border: `1px solid ${on ? 'var(--coral)' : 'var(--line)'}`,
                    background: on ? 'var(--coral-soft)' : 'var(--surface)',
                    color: on ? 'var(--coral-2)' : 'var(--ink)',
                  }}>{label}</button>
              );
            })}
          </div>
        )}
      </div>

      <div className="row" style={{ marginTop: 18, gap: 8, alignItems: 'center' }}>
        {idx > 0 && <Button variant="ghost" onClick={prev} disabled={classifying}>← 이전</Button>}
        <span style={{ marginLeft: 'auto' }}>
          <Button variant="primary" onClick={next} disabled={!canNext || classifying}>
            {classifying ? '판정 중…' : last ? '판정 받기 →' : '다음 →'}
          </Button>
        </span>
      </div>
      {q.type === 'choice' && !q.required && (
        <div className="muted" style={{ fontSize: 11, marginTop: 8 }}>선택 후 ‘다음’을 누르세요.</div>
      )}
    </div>
  );
};

const Intake = ({ go }) => {
  const [step, setStep] = React.useState('org');     // org → journey → run
  const [orgs, setOrgs] = React.useState([]);
  const [org, setOrg] = React.useState(null);
  const [orgName, setOrgName] = React.useState('');
  const [journey, setJourney] = React.useState(null);
  const [busy, setBusy] = React.useState(false);
  const [result, setResult] = React.useState(null);
  const [file, setFile] = React.useState(null);
  const [prod, setProd] = React.useState({ name: '', indication: '', digital: true, ai: true });
  const [useLlm, setUseLlm] = React.useState(true);   // 기본 ON: claude -p 제품맞춤 확장(백엔드 없으면 아래 effect가 OFF 폴백)
  const [production, setProduction] = React.useState(false);  // false=미리보기(가상채움), true=제출용([입력필요])
  const [backends, setBackends] = React.useState([]);
  const [cls, setCls] = React.useState(null);          // 판정 결과
  const [classifying, setClassifying] = React.useState(false);
  const [extra, setExtra] = React.useState({});        // needs_info 답변(등급·품목분류·심사구분)
  const [schema, setSchema] = React.useState({ company_fields: [], product_fields: [] });
  const [company, setCompany] = React.useState({});    // 회사 전항목 프로필
  const [prodExtra, setProdExtra] = React.useState({}); // 제품 추가 항목(버전·안전등급·플랫폼 등)

  React.useEffect(() => {
    fetch('/api/orgs').then((r) => r.json()).then((d) => setOrgs(d.orgs || [])).catch(() => {});
    fetch('/api/profile/schema').then((r) => r.json()).then((d) => setSchema(d)).catch(() => {});
    fetch('/api/llm-writer/backends').then((r) => r.json()).then((d) => {
      const bs = d.backends || [];
      setBackends(bs);
      if (!bs.length) setUseLlm(false);  // LLM 백엔드(claude CLI) 없으면 기본 OFF 폴백 — 생성은 계속 가능
    }).catch(() => setUseLlm(false));
  }, []);
  // 회사 선택 시 저장된 회사 프로필 불러오기(재사용)
  React.useEffect(() => {
    if (org && org.id) {
      fetch('/api/org/' + org.id + '/profile').then((r) => r.json())
        .then((d) => { if (d.ok && d.profile) setCompany((c) => ({ ...d.profile, ...c })); }).catch(() => {});
    }
  }, [org]);
  // ── 문서번호 접두(doc_prefix): 회사명에서 자동 제안 + 사용자 수정 가능 ──
  // 사용자가 직접 손대면(prefixTouched) 자동 제안이 그 값을 덮어쓰지 않는다(사용자 지정 우선).
  const [prefixTouched, setPrefixTouched] = React.useState(false);
  const [prefixSuggest, setPrefixSuggest] = React.useState('');

  const setCompanyField = (k, v) => {
    if (k === 'doc_prefix') {
      setPrefixTouched(true);                      // 직접 입력 → 자동 제안 중단
      v = String(v || '').toUpperCase().replace(/[^A-Z]/g, '').slice(0, 4);
    }
    setCompany((s) => ({ ...s, [k]: v }));
  };
  const setProdField = (k, v) => setProdExtra((s) => ({ ...s, [k]: v }));

  // 회사명(국문/영문) 변경 → 접두 제안 조회. 사용자가 아직 수정하지 않았으면 자동 채움.
  const cKo = company.company_name_ko || '';
  const cEn = company.company_name_en || '';
  React.useEffect(() => {
    if (!cKo && !cEn) { setPrefixSuggest(''); return; }
    const q = new URLSearchParams({ company_name_ko: cKo, company_name_en: cEn });
    fetch('/api/profile/doc-prefix?' + q).then((r) => r.json()).then((d) => {
      if (!d.ok) return;
      setPrefixSuggest(d.suggested || '');
      if (!prefixTouched) setCompany((s) => ({ ...s, doc_prefix: d.suggested || '' }));
    }).catch(() => {});
  }, [cKo, cEn, prefixTouched]);

  // 저장된 회사 프로필에 접두가 이미 있으면 사용자 지정으로 간주(자동 덮어쓰기 방지)
  React.useEffect(() => {
    if (company.doc_prefix && !prefixTouched && !prefixSuggest) setPrefixTouched(true);
  }, [company.doc_prefix]);

  const prefixNote = company.doc_prefix
    ? `문서번호 예: ${company.doc_prefix}-OP-M01 · ${company.doc_prefix}-RMP-001` +
      (prefixTouched ? ' (직접 지정)' : ' (회사명에서 자동 제안 — 수정 가능)')
    : '회사명을 입력하면 접두가 자동 제안됩니다. 직접 수정할 수 있습니다(영문 대문자 2~4자).';
  // 추출 후보 반영: 회사/제품 스키마 키에 맞춰 분배
  const applyExtracted = (vals) => {
    const ckeys = new Set((schema.company_fields || []).map((f) => f.key));
    const pkeys = new Set((schema.product_fields || []).map((f) => f.key));
    const cpatch = {}, ppatch = {};
    Object.entries(vals).forEach(([k, v]) => {
      if (ckeys.has(k)) cpatch[k] = v;
      else if (pkeys.has(k)) ppatch[k] = v;
    });
    if (Object.keys(cpatch).length) setCompany((s) => ({ ...s, ...cpatch }));
    if (Object.keys(ppatch).length) {
      setProdExtra((s) => ({ ...s, ...ppatch }));
      if (ppatch.name) setProd((p) => ({ ...p, name: ppatch.name }));
      if (ppatch.indication) setProd((p) => ({ ...p, indication: ppatch.indication }));
    }
  };

  const createOrg = () => {
    if (!orgName.trim()) return;
    fetch('/api/orgs', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name: orgName.trim() }) })
      .then((r) => r.json()).then((d) => { if (d.ok) { setOrg({ id: d.id, name: d.name }); setStep('journey'); } });
  };
  const pickOrg = (o) => { setOrg(o); setStep('journey'); };

  const _profile = () => ({
    ...prodExtra,  // 제품 추가 항목(버전·안전등급·플랫폼·OS·언어·프레임워크 등)
    name: prod.name || null, brand: prod.name || null, indication: prod.indication || prod.name || null,
    digital_specific: prod.digital, ai: prod.ai,
    등급: extra['등급'] || prodExtra['등급'] || null, 품목분류: extra['품목분류'] || prodExtra['품목분류'] || null,
    심사구분: extra['심사구분'] || null,
  });
  const runClassify = () => {
    if (!prod.name.trim()) { alert('제품명을 입력하세요'); return; }
    setClassifying(true);
    fetch('/api/classify', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ profile: _profile(), use_llm: true }) })
      .then((r) => r.json()).then((d) => {
        setCls(d);
        // 판정 결과로 디지털/AI 체크 동기화
        setProd((p) => ({ ...p, digital: d.digital, ai: d.ai }));
        setClassifying(false);
      }).catch(() => setClassifying(false));
  };
  // 인터뷰 답변 → 프로필 구성 → 판정 실행
  const handleInterview = (a) => {
    setProd((p) => ({ ...p, name: a.name || '', indication: a.indication || '' }));
    setExtra({ '등급': a['등급'] || '', '품목분류': a['품목분류'] || '', '심사구분': a['심사구분'] || '' });
    setClassifying(true);
    const profile = {
      name: a.name || null, brand: a.name || null, indication: a.indication || a.name || null,
      digital_specific: a.digital === 'yes' ? true : a.digital === 'no' ? false : null,
      ai: a.ai === 'yes' ? true : a.ai === 'no' ? false : null,
      '등급': a['등급'] || null, '품목분류': a['품목분류'] || null, '심사구분': a['심사구분'] || null,
    };
    fetch('/api/classify', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ profile, use_llm: true }) })
      .then((r) => r.json()).then((d) => {
        setCls(d);
        setProd((p) => ({ ...p, name: a.name || '', indication: a.indication || '', digital: d.digital, ai: d.ai }));
        setClassifying(false);
      }).catch(() => setClassifying(false));
  };
  const runNew = () => {
    setBusy(true);
    const body = { org_id: org.id, profile: _profile(), company, use_llm: useLlm, production, backend: backends[0] || 'cli' };
    fetch('/api/intake/new', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) })
      .then((r) => r.json()).then((d) => { setResult(d); setStep('run'); setBusy(false); }).catch(() => setBusy(false));
  };
  const runRenew = () => {
    if (!file) { alert('기존 문서 ZIP을 선택하세요'); return; }
    setBusy(true);
    const fd = new FormData(); fd.append('file', file); fd.append('org_id', org.id); fd.append('org_name', org.name);
    fetch('/api/intake/renew', { method: 'POST', body: fd })
      .then((r) => r.json()).then((d) => { if (!d.ok) { alert(d.error); setBusy(false); return; } setResult(d); setStep('run'); setBusy(false); }).catch(() => setBusy(false));
  };
  const openKanban = () => { window.__RALLY_TRACK = result.track_id; go('kanban'); };
  const openTrack = () => { window.__RALLY_TRACK = result.track_id; go('track'); };
  const [reBusy, setReBusy] = React.useState(false);
  const [reMsg, setReMsg] = React.useState(null);
  const runReexpand = () => {
    setReBusy(true); setReMsg(null);
    fetch('/api/track/' + result.track_id + '/reexpand', {
      method: 'POST', headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ production }),
    }).then((r) => r.json()).then((d) => {
      const n = (d.fixed || []).length;
      setReMsg(n ? (n + '개 문서 확장 완료: ' + d.fixed.map((f) => f.code).join(', ')) : '추가 확장할(짧은) 문서가 없습니다.');
      setReBusy(false);
    }).catch(() => { setReMsg('재확장 실패 — 잠시 후 다시 시도하세요.'); setReBusy(false); });
  };
  const [dfBusy, setDfBusy] = React.useState(false);
  const [dfMsg, setDfMsg] = React.useState(null);
  const runDemoFill = () => {
    setDfBusy(true); setDfMsg(null);
    fetch('/api/track/' + result.track_id + '/demofill', {
      method: 'POST', headers: { 'Content-Type': 'application/json' }, body: '{}',
    }).then((r) => r.json()).then((d) => {
      setDfMsg((d.docs || 0) + '개 문서 · ' + (d.markers || 0) + '개 [입력 필요]를 예시값으로 채웠습니다 (모두 "예시·실측 아님" 표기).');
      setDfBusy(false);
    }).catch(() => { setDfMsg('데모 채우기 실패.'); setDfBusy(false); });
  };

  return (
    <div className="page" style={{ maxWidth: 880, margin: '0 auto' }}>
      <div className="page__head">
        <div>
          <div className="row" style={{ gap: 8, marginBottom: 6 }}>
            <Pill variant="coral">온보딩</Pill>
            <Pill>회사별 격리</Pill>
          </div>
          <div className="page__title">RAlly 시작하기</div>
          <div className="page__sub">회사를 만들고, 신규 GMP 준비 또는 기존 문서 갱신 분석을 시작하세요. 데이터는 회사별로 분리됩니다.</div>
        </div>
      </div>

      {/* Stepper */}
      <div className="row" style={{ gap: 8, marginBottom: 20 }}>
        {[['org', '1 회사'], ['journey', '2 여정'], ['run', '3 실행']].map(([k, label]) => (
          <Pill key={k} variant={step === k ? 'navy' : 'default'}>{label}</Pill>
        ))}
      </div>

      {/* Step 1: org */}
      {step === 'org' && (
        <div className="card card--pad">
          <div style={{ fontWeight: 700, color: 'var(--navy)', marginBottom: 10 }}>회사(테넌트) 만들기</div>
          <div className="row" style={{ gap: 8 }}>
            <input value={orgName} onChange={(e) => setOrgName(e.target.value)} placeholder="회사명 (예: 가온메디텍 주식회사)"
              style={{ flex: 1, fontFamily: 'inherit', fontSize: 14, padding: '10px 12px', border: '1px solid var(--line)', borderRadius: 8 }} />
            <Button variant="primary" onClick={createOrg}>만들기 →</Button>
          </div>
          {orgs.length > 0 && (
            <div style={{ marginTop: 16 }}>
              <div className="muted" style={{ fontSize: 12, marginBottom: 8 }}>또는 기존 회사 선택</div>
              {orgs.map((o) => (
                <div key={o.id} className="sec" style={{ cursor: 'pointer' }} onClick={() => pickOrg(o)}>
                  <div className="sec__b"><div className="sec__t">{o.name}</div><div className="sec__c">org #{o.id}</div></div>
                  <Icon name="arrow_right" size={14} />
                </div>
              ))}
            </div>
          )}
        </div>
      )}

      {/* Step 2: journey */}
      {step === 'journey' && (
        <div>
          <div className="muted" style={{ marginBottom: 12 }}>회사: <b style={{ color: 'var(--ink)' }}>{org.name}</b></div>
          <div className="grid-2">
            <div className="card card--pad" style={{ cursor: 'pointer', borderColor: journey === 'new' ? 'var(--coral)' : null }} onClick={() => setJourney('new')}>
              <Icon name="flag" size={22} style={{ color: 'var(--coral)' }} />
              <div style={{ fontSize: 17, fontWeight: 700, marginTop: 8 }}>신규 GMP 준비</div>
              <div className="muted" style={{ fontSize: 13, marginTop: 4 }}>품목 정보만 가져오면, 적용 문서종을 모두 생성해 칸반에 올려드립니다.</div>
            </div>
            <div className="card card--pad" style={{ cursor: 'pointer', borderColor: journey === 'renew' ? 'var(--coral)' : null }} onClick={() => setJourney('renew')}>
              <Icon name="layers" size={22} style={{ color: 'var(--navy)' }} />
              <div style={{ fontSize: 17, fontWeight: 700, marginTop: 8 }}>GMP 갱신 분석</div>
              <div className="muted" style={{ fontSize: 13, marginTop: 4 }}>기존 문서를 올리면 전부 분석해 <b>지금 무엇을 보완해야 하는지</b> 알려드립니다.</div>
            </div>
          </div>

          {journey === 'new' && !cls && (
            <div className="card card--pad" style={{ marginTop: 16 }}>
              <Interview onDone={handleInterview} classifying={classifying} />
            </div>
          )}

          {journey === 'new' && cls && (
            <div className="card card--pad" style={{ marginTop: 16 }}>
              <div className="row" style={{ justifyContent: 'space-between', alignItems: 'center', marginBottom: 12 }}>
                <div style={{ fontWeight: 700, color: 'var(--navy)' }}>① 판정 결과</div>
                <Button variant="ghost" size="sm" onClick={() => setCls(null)} disabled={classifying}>↻ 질문 다시 하기</Button>
              </div>

              {/* 판정 결과 */}
              {cls && (
                <div style={{ padding: 16, background: 'var(--coral-soft)', borderRadius: 10, border: '1px solid var(--coral-line)' }}>
                  <div className="row" style={{ gap: 8, marginBottom: 8, flexWrap: 'wrap' }}>
                    <span style={{ fontWeight: 700, color: 'var(--coral-2)' }}>판정: {cls.verdict}</span>
                  </div>
                  <div style={{ fontSize: 12.5, color: 'var(--ink-2)', marginBottom: 8 }}>
                    디지털 <b>{cls.digital ? 'O' : 'X'}</b> ({cls.digital_source}) · AI <b>{cls.ai ? 'O' : 'X'}</b>
                  </div>
                  <div className="row" style={{ gap: 6, flexWrap: 'wrap', marginBottom: 10 }}>
                    {cls.annexes.map((a, i) => <Pill key={i} variant="navy">{a}</Pill>)}
                  </div>
                  {/* 수집된 품목 정보 요약 */}
                  <div style={{ fontSize: 12, color: 'var(--ink-2)', marginBottom: 10, lineHeight: 1.7, borderTop: '1px dashed var(--coral-line)', paddingTop: 10 }}>
                    <div><b>품목명</b> · {prod.name || '—'}</div>
                    <div><b>품목분류번호</b> · {extra['품목분류'] || <span style={{ color: 'var(--coral-2)' }}>미입력 — 문서에 [입력 필요]로 표기</span>}</div>
                    <div><b>등급</b> · {extra['등급'] ? extra['등급'] + '등급' : '미입력'} &nbsp;|&nbsp; <b>심사구분</b> · {extra['심사구분'] || '미입력'}</div>
                  </div>
                  {/* 필요 정보 요청 */}
                  {cls.needs_info && cls.needs_info.length > 0 && (
                    <div style={{ borderTop: '1px dashed var(--coral-line)', paddingTop: 10 }}>
                      <div style={{ fontWeight: 700, fontSize: 12.5, color: 'var(--coral-2)', marginBottom: 8 }}>⚠ 판정·문서 작성에 필요한 정보를 알려주세요</div>
                      {cls.needs_info.map((n, i) => (
                        <div key={i} style={{ marginBottom: 8 }}>
                          <div style={{ fontSize: 12.5, color: 'var(--ink)' }}>{n.q} <span className="muted" style={{ fontSize: 11 }}>— {n.why}</span></div>
                          {n.key === 'ai' ? (
                            <label className="row" style={{ gap: 6, fontSize: 12.5, cursor: 'pointer', marginTop: 3 }}>
                              <input type="checkbox" checked={prod.ai} onChange={(e) => setProd({ ...prod, ai: e.target.checked })} /> AI/ML 기능 포함
                            </label>
                          ) : n.key === 'digital' ? (
                            <label className="row" style={{ gap: 6, fontSize: 12.5, cursor: 'pointer', marginTop: 3 }}>
                              <input type="checkbox" checked={prod.digital} onChange={(e) => setProd({ ...prod, digital: e.target.checked })} /> 소프트웨어 의료기기(디지털)
                            </label>
                          ) : (
                            <input value={extra[n.key] || ''} onChange={(e) => setExtra({ ...extra, [n.key]: e.target.value })}
                              placeholder={n.key === '심사구분' ? '신규 / 갱신' : ''}
                              style={{ width: '100%', fontSize: 13, padding: '7px 10px', border: '1px solid var(--line)', borderRadius: 7, marginTop: 4 }} />
                          )}
                        </div>
                      ))}
                      <div className="row" style={{ gap: 8, alignItems: 'center', marginTop: 6 }}>
                        <Button variant="soft" size="sm" onClick={runClassify} disabled={classifying}>{classifying ? '판정 중…' : '↻ 다시 판정'}</Button>
                        <span className="muted" style={{ fontSize: 11 }}>입력 후 ‘다시 판정’ 또는 바로 ‘전 문서 생성’. 미입력 값은 문서에 [입력 필요]로 표시됩니다.</span>
                      </div>
                    </div>
                  )}
                </div>
              )}

              {/* 임상 필요성 안내(참고용) — 확정 아님, 안내만 */}
              {cls && <ClinicalGuide aiHint={!!cls.ai} />}

              {/* ② 회사·제품 정보 입력(전 문서 자동 반영) */}
              {cls && (
                <div style={{ marginTop: 16, borderTop: '1px dashed var(--line)', paddingTop: 14 }}>
                  <div style={{ fontWeight: 700, color: 'var(--navy)', marginBottom: 4 }}>② 회사·제품 정보 입력</div>
                  <div className="muted" style={{ fontSize: 12, marginBottom: 6, lineHeight: 1.5 }}>
                    여기 입력한 회사·제품 정보는 <b>필요한 모든 문서에 자동 반영</b>됩니다(표제부·승인란·바닥글·본문 [입력 필요]).
                    한 번만 입력하면 다음 트랙에도 재사용됩니다. 시험결과·성능·서명 등 실측값은 계속 직접 채웁니다.
                  </div>
                  <ExtractUploader onApply={applyExtracted} />
                  <ProfileForm title="🏢 회사 정보" fields={schema.company_fields} values={company} onChange={setCompanyField}
                    notes={{ doc_prefix: prefixNote }}
                    hint="회사명·대표자·주소·제조업 허가번호·서명자 명단 등 — 전 문서 표제부·승인란·제조사 정보에 반영됩니다." />
                  <ProfileForm title="📦 제품 상세 정보" values={prodExtra} onChange={setProdField}
                    fields={(schema.product_fields || []).filter((f) => !['name', 'indication', 'ai', '등급', '품목분류'].includes(f.key))}
                    hint="모델명·버전·안전등급·플랫폼·OS·개발언어 등 — 제품표준서·SRS·SDS 등에 반영됩니다. (제품명·사용목적·등급·품목분류·AI는 위 판정에서 사용)" />
                </div>
              )}

              {/* ③ 생성 */}
              {cls && (
                <div style={{ marginTop: 16, borderTop: '1px dashed var(--line)', paddingTop: 14 }}>
                  <div style={{ fontWeight: 700, color: 'var(--navy)', marginBottom: 10 }}>③ 전 문서 생성</div>
                  <label className="row" style={{ gap: 8, cursor: 'pointer', alignItems: 'flex-start', marginBottom: 10 }}>
                    <input type="checkbox" checked={useLlm} onChange={(e) => setUseLlm(e.target.checked)} style={{ marginTop: 3 }} />
                    <span>
                      <span style={{ fontWeight: 700, color: 'var(--navy)' }}>🤖 LLM으로 작성 <span style={{ color: 'var(--coral)', fontSize: 11 }}>(권장·기본)</span></span>
                      <span className="muted" style={{ fontSize: 12, display: 'block', marginTop: 2 }}>
                        {backends.length ? ('제품 맞춤 본문을 ' + backends[0] + ' 백엔드로 작성(고품질·느림, 문서 많으면 수분+). 중간에 확장 실패한 문서는 자동 재개하며, 남으면 결과 화면의 “↻ 확장 이어서 완료”로 마무리합니다. 끄면 템플릿(즉시).') : 'LLM 백엔드 미가용 — 템플릿으로 생성됩니다.'}
                      </span>
                    </span>
                  </label>
                  <label className="row" style={{ gap: 8, cursor: 'pointer', alignItems: 'flex-start', marginBottom: 12 }}>
                    <input type="checkbox" checked={production} onChange={(e) => setProduction(e.target.checked)} style={{ marginTop: 3 }} />
                    <span>
                      <span style={{ fontWeight: 700, color: 'var(--navy)' }}>📄 제출용(공란) 모드</span>
                      <span className="muted" style={{ fontSize: 12, display: 'block', marginTop: 2 }}>
                        {production
                          ? '날짜·담당자·실측값을 [입력 필요]로 비웁니다 — 실제 제출 전 회사가 채웁니다.'
                          : '미리보기: 가상 날짜·담당자를 채워 실제 문서처럼 보여줍니다(데모용).'}
                      </span>
                    </span>
                  </label>
                  <Button variant="primary" onClick={runNew} disabled={busy || (useLlm && !backends.length)}>
                    {busy ? (useLlm ? 'LLM 작성 중… (수십 초~)' : '생성 중…') : '전 문서 생성 시작 →'}
                  </Button>
                </div>
              )}
            </div>
          )}
          {journey === 'renew' && (
            <div className="card card--pad" style={{ marginTop: 16 }}>
              <div className="muted" style={{ fontSize: 13, marginBottom: 12 }}>기존 문서 폴더를 <span className="mono">.zip</span>으로 올려주세요(.docx). 회사 내부에서만 처리됩니다.</div>
              <div className="row" style={{ gap: 8 }}>
                <input type="file" accept=".zip" onChange={(e) => setFile(e.target.files[0])} style={{ fontSize: 13 }} />
                <Button variant="primary" onClick={runRenew} disabled={busy}>{busy ? '분석 중…' : '분석 시작 →'}</Button>
              </div>
            </div>
          )}
        </div>
      )}

      {/* Step 3: run/result */}
      {step === 'run' && result && (
        <div className="card card--pad">
          {result.journey === 'new' ? (
            <div>
              <div style={{ fontSize: 17, fontWeight: 700, color: 'var(--navy)' }}>✅ {result.brand} · 신규 준비 완료
                <Pill variant={result.use_llm ? 'coral' : 'default'} style={{ marginLeft: 8 }}>{result.use_llm ? '🤖 LLM 작성' : '템플릿'}</Pill>
              </div>
              <div className="muted" style={{ marginTop: 6 }}>적용 문서 <b>{result.doc_count}</b>개를 칸반 '시작 전'에 올렸습니다 · 채울 증거값 <b style={{ color: 'var(--coral)' }}>{result.input_count}</b>개</div>
              <div style={{ marginTop: 12 }} className="muted">{result.applicable_docs.map((d) => d.code).join(', ')}</div>
              {result.use_llm && (
                <div style={{ marginTop: 12, padding: '10px 12px', background: 'var(--bg, #F6F4EF)', borderRadius: 8 }}>
                  <div className="muted" style={{ fontSize: 12, marginBottom: 6 }}>
                    LLM 확장은 대량 생성 시 일부 문서가 호출 한도로 빠질 수 있어요. 아래 버튼으로 <b>빠진 문서만 이어서 확장</b>합니다.
                  </div>
                  <Button variant="ghost" onClick={runReexpand} disabled={reBusy}>
                    {reBusy ? '확장 이어서 진행 중…' : '↻ 확장 이어서 완료'}
                  </Button>
                  {reMsg && <span style={{ marginLeft: 10, fontSize: 12.5, color: 'var(--navy)' }}>{reMsg}</span>}
                </div>
              )}
              <div style={{ marginTop: 10, padding: '10px 12px', background: 'var(--bg, #F6F4EF)', borderRadius: 8 }}>
                <div className="muted" style={{ fontSize: 12, marginBottom: 6 }}>
                  <b style={{ color: 'var(--coral-2, #b94a2c)' }}>데모용</b> — [입력 필요]를 예시값으로 채워 화면 시연. 모든 값에 <b>"예시(실측 아님)"</b> 표기가 붙어 <b>실제 제출엔 쓸 수 없습니다</b>(회사가 실값으로 교체).
                </div>
                <Button variant="ghost" onClick={runDemoFill} disabled={dfBusy}>
                  {dfBusy ? '예시값 채우는 중…' : '▣ 데모 예시값 채우기'}
                </Button>
                {dfMsg && <span style={{ marginLeft: 10, fontSize: 12.5, color: 'var(--navy)' }}>{dfMsg}</span>}
              </div>
            </div>
          ) : (
            <div>
              <div style={{ fontSize: 17, fontWeight: 700, color: 'var(--navy)' }}>✅ 갱신 분석 완료 — {result.doc_count}개 문서</div>
              <div className="muted" style={{ marginTop: 6 }}>이미 충족 {result.summary['이미충족']} · <b style={{ color: 'var(--coral)' }}>보완 필요 {result.summary['보강됨']}</b> · 검토 {result.summary['규칙없음']}</div>
              {result.to_supplement.length > 0 && (
                <div style={{ marginTop: 12 }}>
                  <div style={{ fontWeight: 700, color: 'var(--coral)', fontSize: 13, marginBottom: 6 }}>⚠ 지금 보완해야 할 문서</div>
                  {result.to_supplement.map((s, i) => (
                    <div key={i} className="sec"><div className="sec__b"><div className="sec__t">{s.name}</div>
                      <div className="sec__c">[{s.doc_type}] 보완: {(s.gaps || []).join(', ') || s.supplemented.join(', ')}</div></div></div>
                  ))}
                </div>
              )}
            </div>
          )}
          <div className="row" style={{ marginTop: 16, gap: 8 }}>
            <Button variant="primary" iconRight="arrow_right" onClick={openKanban}>내 칸반에서 보기</Button>
            <Button variant="soft" iconRight="arrow_right" onClick={openTrack}>트랙 상세로 이동</Button>
            <Button variant="ghost" onClick={() => { setStep('org'); setResult(null); setJourney(null); }}>처음으로</Button>
          </div>
        </div>
      )}
    </div>
  );
};

window.RAlly.Intake = Intake;
