/* SEAL — 💬 미소 챗봇 (전역 위젯) · AI② 접점.
   혁신법 QnA 하네싱 양식 A로 답한다: [관련 근거]/[해석]/[답변] 3섹션 + 합쇼체.
   1순위 = /api/chat (answerQuestion, 혁신법 모트 근거조문 grounded).
   네트워크 실패 시 = 동일 양식의 결정론 폴백(혁신법 모트 근거 인용 유지). */
const { useState, useEffect, useRef } = React;
const Dc = window.SEAL_DATA;

const SUGGESTS = [
  "노트북 사도 돼?",
  "밴쿠버 출장 숙박 얼마까지?",
  "회식비 처리되나요?",
  "남은 국외출장비 얼마야?",
];

/* 폴백: /api/chat 미응답 시에도 하네싱 양식(3섹션) 유지.
   [관련 근거]는 혁신법 모트 근거조문 인용만 기재(해설 금지·합쇼체). */
function misoFallback(q) {
  const t = q.toLowerCase();
  const has = (...ks) => ks.some((k) => q.includes(k) || t.includes(k));
  const mk = (verdict, sections, ref) => ({ verdict, sections, ref: ref || [] });

  if (has("노트북", "맥북", "랩탑")) {
    return mk("보완요청", [
      { label: "[관련 근거]", text: "· [L2-criteria] 혁신법/이지바로 공통 criteria(연구재료비) — 내부결재+거래명세서+검수확인서 (출처: innovation_law_criteria.json > 연구재료비)" },
      { label: "[해석]", text: "연구재료비는 실비 기준이며, 취득가 50만원 이상·내용연수 1년 이상의 자산성 물품은 연구재료비가 아니라 연구시설·장비비로 분류됩니다." },
      { label: "[답변]", text: "노트북은 자산성 물품에 해당하면 장비비로 별도 승인이 필요합니다. 50만원 미만 주변기기는 소모품으로 바로 집행하실 수 있습니다." },
    ], [{ layer: "L2-criteria", ref: "연구재료비 증빙기준" }]);
  }
  if (has("밴쿠버", "국외출장", "해외출장") || (has("출장", "숙박", "호텔") && has("얼마"))) {
    return mk("집행가능", [
      { label: "[관련 근거]", text: "· [L2-매뉴얼] 국가연구개발혁신법 매뉴얼 표3-17(국외출장 증명자료) — 출장계획서+출장결과보고서+지급증빙 (출처: 혁신법 매뉴얼 인쇄227쪽)\n· [L4-자체규정] 기관 여비규정 — 등급·한도 위임(실비) (출처: 위임)" },
      { label: "[해석]", text: "국외출장비는 실비 기준이며 한도는 기관 자체규정에 위임되어 있습니다. 자체규정이 없으면 공무원여비 별표4를 베이스라인으로 참고할 수 있습니다." },
      { label: "[답변]", text: "자체규정 숙박 상한 범위 내라면 집행 가능합니다. 항공은 이코노미가 원칙이며 비즈니스석은 사전승인이 필요합니다." },
    ], [{ layer: "L2-매뉴얼", ref: "혁신법 매뉴얼 표3-17" }, { layer: "L4-자체규정", ref: "기관 여비규정" }]);
  }
  if (has("회식", "주류", "술", "회의", "다과", "식대")) {
    return mk("보완요청", [
      { label: "[관련 근거]", text: "· [L2-criteria] 혁신법/이지바로 공통 criteria(회의비) — 내부결재/회의록+영수증, 식비는 외부인원+사전결재 (출처: innovation_law_criteria.json > 회의비)\n· [L2-즉시불인정] 외부인원 없는 회의비 식비 집행분 — 즉시 불인정 (출처: innovation_law_criteria.json immediate_disallow)" },
      { label: "[해석]", text: "회의비 식비는 외부인원 참석과 사전결재가 요건이며, 단순 회식·주류는 연구비로 인정되지 않습니다." },
      { label: "[답변]", text: "외부인원이 참석하는 연구 협의 회의라면 회의비로 처리할 수 있으나, 안건·참석자 명단이 필요하고 주류는 제외됩니다. 단순 회식비는 불인정입니다." },
    ], [{ layer: "L2-즉시불인정", ref: "외부인원 없는 회의비 식비" }]);
  }
  if (has("야근", "특근", "초과근무")) {
    return mk("보완요청", [
      { label: "[관련 근거]", text: "· [L2-매뉴얼] 연구개발비 사용 매뉴얼 — 야근(특근)식대 — 과제 수행 위해 지출된 야근(특근) 식대 (출처: 혁신법 매뉴얼)" },
      { label: "[해석]", text: "야근/특근 식대는 초과근무내역(근무자·시간·업무)과 지급증빙이 필요하며, 동일인·동일일자 출장 식비와 중복되면 불인정됩니다." },
      { label: "[답변]", text: "초과근무 내역과 지급증빙을 갖추면 집행 가능합니다. 출장 식비와의 중복 여부를 확인해 주십시오." },
    ], [{ layer: "L2-criteria", ref: "야근/특근식대 중복 금지" }]);
  }
  if (has("사무용품", "문구", "프린터", "토너")) {
    return mk("집행가능", [
      { label: "[관련 근거]", text: "· [L2-매뉴얼] 연구개발비 사용 매뉴얼 — 연구실운영비 정의 — 사무용 기기·SW 구입·설치·임차·사용대차 (출처: 혁신법 매뉴얼)" },
      { label: "[해석]", text: "사무용품은 연구활동비-연구실운영비로 집행하며 내부결재·사용내역·지급증빙이 필요합니다. 영리기관의 소모성 비용은 불인정입니다." },
      { label: "[답변]", text: "비영리기관이라면 증빙을 갖춰 집행 가능합니다. 영리기관은 별지 제4호와 사전승인이 필요합니다." },
    ], [{ layer: "L2-criteria", ref: "연구실운영비 증빙기준" }]);
  }
  return mk(null, [
    { label: "[답변]", text: "이 과제는 국가연구개발혁신법 연구비 맥락에서만 답해 드립니다(보조금 사업과는 기준이 다릅니다). 국외출장·국내출장·회의비·연구재료비·연구실운영비·야근/특근식대 중 어떤 집행인지 구체적으로 말씀해 주시면, 혁신법 근거조문과 함께 알려드리겠습니다." },
  ], []);
}

async function fetchAnswer(q) {
  try {
    const r = await fetch("/api/chat", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ message: q }),
    });
    if (!r.ok) throw new Error("api");
    const d = await r.json();
    if (d && Array.isArray(d.sections) && d.sections.length) {
      return {
        verdict: d.verdict && d.verdict !== "안내" ? d.verdict : null,
        sections: d.sections,
        ref: Array.isArray(d.근거) ? d.근거.map((g) => ({ layer: g.layer, ref: g.ref })) : [],
      };
    }
    throw new Error("shape");
  } catch (_e) {
    return misoFallback(q);
  }
}

function Chatbot({ onClose, nav }) {
  const [msgs, setMsgs] = useState([
    { from: "bot", sections: [{ label: "[답변]", text: "안녕하세요, AI 회계사 미소입니다. 혁신법 연구비 집행을 [관련 근거]·[해석]·[답변] 3단으로 답해 드립니다. 무엇을 사도 될지 물어보세요." }], ref: [] },
  ]);
  const [val, setVal] = useState("");
  const [typing, setTyping] = useState(false);
  const logRef = useRef(null);

  useEffect(() => { if (logRef.current) logRef.current.scrollTop = logRef.current.scrollHeight; }, [msgs, typing]);

  const ask = async (q) => {
    if (!q.trim() || typing) return;
    setMsgs((m) => [...m, { from: "me", text: q }]);
    setVal("");
    setTyping(true);
    // ★AI가 실제로 추론하는 것처럼 — 최소 5초 사고 연출 + 실제 미소 응답을 병렬로(더 늦은 쪽까지 대기)
    const [a] = await Promise.all([
      fetchAnswer(q),
      new Promise((r) => setTimeout(r, 5000)),
    ]);
    setTyping(false);
    setMsgs((m) => [...m, { from: "bot", ...a }]);
  };

  return (
    <div className="chat-panel">
      <div className="chat-head">
        <div className="chat-ava">미소</div>
        <div>
          <div className="chat-name">미소 · AI 회계사</div>
          <div className="chat-status"><span className="dot" />혁신법 규정 DB 연결됨</div>
        </div>
        <button className="chat-x" onClick={onClose}><Icons.x size={18} /></button>
      </div>

      <div className="chat-log" ref={logRef}>
        {msgs.map((m, i) => (
          <div key={i} className={`msg ${m.from}`}>
            {m.from === "me" ? (
              <div style={{ whiteSpace: "pre-wrap" }}>{m.text}</div>
            ) : (
              <div>
                {Array.isArray(m.sections) ? (
                  m.sections.map((s, k) => (
                    <div key={k} style={{ marginBottom: k < m.sections.length - 1 ? 8 : 0 }}>
                      <div style={{ fontWeight: 700, fontSize: 12, opacity: 0.7, marginBottom: 2 }}>{s.label}</div>
                      <div style={{ whiteSpace: "pre-wrap" }}>{s.text}</div>
                    </div>
                  ))
                ) : (
                  <div style={{ whiteSpace: "pre-wrap" }}>{m.text}</div>
                )}
                {m.verdict && (
                  <div style={{ marginTop: 8 }}><VerdictBadge verdict={m.verdict} /></div>
                )}
                {m.ref && m.ref.length > 0 && (
                  <div className="ref">
                    {m.ref.map((r, j) => <div key={j} style={{ marginBottom: 2 }}>· <b>{r.layer}</b> {r.ref}</div>)}
                  </div>
                )}
              </div>
            )}
          </div>
        ))}
        {typing && <div className="msg bot"><div className="chat-typing"><span /><span /><span /></div></div>}
      </div>

      {msgs.length <= 1 && (
        <div className="chat-sugg">
          {SUGGESTS.map((s, i) => <div key={i} className="s" onClick={() => ask(s)}>{s}</div>)}
        </div>
      )}

      <div className="chat-input">
        <input
          value={val} onChange={(e) => setVal(e.target.value)}
          onKeyDown={(e) => e.key === "Enter" && ask(val)}
          placeholder="이거 사도 돼? 라고 물어보세요" />
        <button className="chat-send" onClick={() => ask(val)}><Icons.send size={18} /></button>
      </div>
    </div>
  );
}

window.Chatbot = Chatbot;
