/* ============================================================
   Main App — state machine for 기안 → 결재 → 피드백 → 재요청
              → 최종확정 → 종결
   ============================================================ */
const { useState, useRef, useEffect } = React;

const BASE = new Date(2026, 4, 26, 10, 15);
function fmt(min) {
  const d = new Date(BASE.getTime() + min * 60000);
  const p = (n) => String(n).padStart(2, "0");
  return `${d.getFullYear()}.${p(d.getMonth() + 1)}.${p(d.getDate())} ${p(d.getHours())}:${p(d.getMinutes())}`;
}

function labelFor(i) { return ["1차 결재", "2차 결재", "3차 결재", "4차 결재"][i] || `${i + 1}차 결재`; }

function App() {
  const [perspective, setPerspective] = useState("ljh");
  const [tab, setTab] = useState("chat");
  const [started, setStarted] = useState(false);
  const [closed, setClosed] = useState(false);
  const [phases, setPhases] = useState([]);
  const [messages, setMessages] = useState([]);
  const [modal, setModal] = useState(null); // {type, phase}
  const [composerMenu, setComposerMenu] = useState(false);
  const [draft, setDraftText] = useState("");
  const minsRef = useRef(0);
  const feedRef = useRef(null);

  const nextMin = (step = 0) => { minsRef.current += step; return fmt(minsRef.current); };

  useEffect(() => {
    if (feedRef.current) feedRef.current.scrollTop = feedRef.current.scrollHeight;
  }, [messages]);

  // ----- helpers -----
  const addMsg = (m) => setMessages((p) => [...p, { id: Math.random(), ...m }]);
  const sys = (tag, html, tone = "info", icon = "info") =>
    addMsg({ type: "system", tag, html, tone, icon });

  const activeId = (() => {
    const f = phases.find((p) => ["requested", "reviewing", "rejected", "upload"].includes(p.status));
    return f ? f.id : null;
  })();

  // ----- reset -----
  const reset = () => {
    setStarted(false); setClosed(false); setPhases([]); setMessages([]); setModal(null);
    setPerspective("ljh"); minsRef.current = 0;
  };

  // ----- draft submit -----
  const submitDraft = ({ title, files, line }) => {
    minsRef.current = 0;
    const t0 = nextMin(0);
    const ph = [{ id: "draft", kind: "draft", label: "기안", user: "ljh", status: "approved", time: t0,
      log: [{ icon: "checkCircle", color: "var(--success)", text: "<b>기안 등록</b> · 결재 요청 발송", time: t0 }] }];
    line.forEach((uid, i) => {
      const isComp = uid === "kms";
      ph.push({
        id: "ap" + i, kind: isComp ? "compliance" : "approve", label: labelFor(i), user: uid,
        status: i === 0 ? "requested" : "locked",
        note: isComp ? "컴플라이언스 심의 · 심의번호 필수" : "내부 검토",
        log: [],
      });
    });
    ph.push({ id: "final", kind: "final", label: "최종확정", user: "ljh", status: "locked",
      note: "심의번호 반영 최종본 업로드", log: [] });
    setPhases(ph);
    setStarted(true);
    setModal(null);
    addMsg({ type: "chat", dir: "out", userId: "ljh", time: t0,
      text: "이번에 기획한 KODEX 반도체 레버리지 상품 리플렛 기획 문서입니다.\n확인해보시고 의견 있으시면 주시고 컨펌 부탁드립니다.",
      file: files[0], fileKind: "p" });
    const first = window.USERS[line[0]];
    sys("기안", `<b>이정훈</b>님이 기안을 등록하고 <b>${first.name}</b>님에게 결재를 요청했습니다.`, "info", "flag");
  };

  // ----- approval: open (start review) -----
  const openApproval = (phase) => {
    const t = nextMin(40 + Math.floor(Math.random() * 30));
    setPhases((ps) => ps.map((p) => p.id === phase.id ? {
      ...p, status: "reviewing",
      log: [...p.log, { icon: "clock", color: "var(--primary)", text: "<b>검토 시작</b>", time: t }],
    } : p));
    sys("검토중", `<b>${window.USERS[phase.user].name}</b>님이 ${phase.label} 검토를 시작했습니다.`, "info", "clock");
    setModal({ type: "approval", phaseId: phase.id });
  };

  // ----- approval: submit -----
  const submitApproval = ({ choice, comment, reviewNo }) => {
    const phase = phases.find((p) => p.id === modal.phaseId);
    const t = nextMin(25 + Math.floor(Math.random() * 20));
    if (choice === "reject") {
      setPhases((ps) => ps.map((p) => p.id === phase.id ? {
        ...p, status: "rejected", rejectNote: comment,
        log: [...p.log, { icon: "flag", color: "var(--danger)", text: `<b>반려</b> · ${comment}`, time: t }],
      } : p));
      sys("반려", `<b>${window.USERS[phase.user].name}</b>님이 반려했습니다. — “${comment}”`, "reject", "flag");
    } else {
      setPhases((ps) => {
        const idx = ps.findIndex((p) => p.id === phase.id);
        return ps.map((p, i) => {
          if (p.id === phase.id) return {
            ...p, status: "approved", time: t, reviewNo: reviewNo || p.reviewNo,
            log: [...p.log, { icon: "checkCircle", color: "var(--success)",
              text: reviewNo ? `<b>최종 승인</b> · 심의번호 ${reviewNo}` : "<b>승인</b>", time: t }],
          };
          if (i === idx + 1) return { ...p, status: p.kind === "final" ? "upload" : "requested" };
          return p;
        });
      });
      const isComp = phase.kind === "compliance";
      sys(isComp ? "최종 승인" : "승인",
        `<b>${window.USERS[phase.user].name}</b>님이 ${phase.label}를 승인했습니다.${reviewNo ? ` 심의번호 <b>${reviewNo}</b> 부여.` : ""}`,
        "approve", "checkCircle");
    }
    setModal(null);
  };

  // ----- re-request after reject -----
  const submitRedo = ({ file, comment }) => {
    const phase = phases.find((p) => p.id === modal.phaseId);
    const t = nextMin(60 + Math.floor(Math.random() * 40));
    setPhases((ps) => ps.map((p) => p.id === phase.id ? {
      ...p, status: "requested", revisedFile: file, rejectNote: null,
      log: [...p.log, { icon: "refresh", color: "var(--warn)", text: "<b>재요청</b> · 수정본 반영", time: t }],
    } : p));
    addMsg({ type: "chat", dir: "out", userId: "ljh", time: t,
      text: comment || "수정사항 반영하여 다시 올려드립니다.", file, fileKind: "p" });
    sys("재요청", `<b>이정훈</b>님이 수정본을 올리고 <b>${window.USERS[phase.user].name}</b>님에게 재요청했습니다.`, "redo", "refresh");
    setModal(null);
  };

  // ----- final upload -----
  const submitFinal = ({ file }) => {
    const comp = phases.find((p) => p.kind === "compliance");
    const reviewNo = comp ? comp.reviewNo : "";
    const t = nextMin(120);
    setPhases((ps) => ps.map((p) => p.id === "final" ? {
      ...p, status: "done", finalFile: file, reviewNo, time: t,
      log: [{ icon: "upload", color: "var(--success)", text: "<b>최종본 업로드</b>", time: t }],
    } : p));
    addMsg({ type: "chat", dir: "out", userId: "ljh", time: t,
      text: "심의 완료된 최종본 업로드합니다. 감사합니다.", file, fileKind: "p" });
    sys("종결", `최종본이 업로드되어 채널이 <b>종결</b>되었습니다. 심의번호 <b>${reviewNo}</b>`, "approve", "checkCircle");
    setClosed(true);
    setModal(null);
  };

  const onCardAction = (type, phase) => {
    if (type === "approve-open") openApproval(phase);
    if (type === "redo-open") setModal({ type: "redo", phaseId: phase.id });
    if (type === "final-open") setModal({ type: "final", phaseId: phase.id });
  };

  const sendText = () => {
    if (!draft.trim() || closed) return;
    addMsg({ type: "chat", dir: "out", userId: perspective, time: nextMin(2), text: draft.trim() });
    setDraftText("");
  };

  // ----- next-step hint -----
  const hint = (() => {
    if (!started || closed) return null;
    const ap = phases.find((p) => p.id === activeId);
    if (!ap) return null;
    if (ap.status === "rejected")
      return perspective === "ljh"
        ? <>반려된 카드에서 <b>수정본을 올리고 재요청</b>하세요.</>
        : <>기안자 <b>이정훈</b>으로 전환하면 수정·재요청할 수 있습니다.</>;
    if (ap.kind === "final")
      return perspective === "ljh"
        ? <><b>최종본 업로드</b>로 채널을 종결하세요.</>
        : <>기안자 <b>이정훈</b>으로 전환하면 최종본을 업로드할 수 있습니다.</>;
    const u = window.USERS[ap.user];
    return perspective === ap.user
      ? <><b>{ap.label}</b> 카드에서 결재를 진행하세요.</>
      : <><b>{u.name} {u.role}</b>의 결재 차례입니다. 해당 인물로 전환해보세요.</>;
  })();

  const modalPhase = modal ? phases.find((p) => p.id === modal.phaseId) : null;
  const compNo = (phases.find((p) => p.kind === "compliance") || {}).reviewNo || "";

  return (
    <div className="app">
      <window.Nav />
      <window.ChannelList />

      {/* ---- chat column ---- */}
      <main className="chat">
        <window.ChatHeader tab={tab} setTab={setTab} closed={closed} />
        <div className="feed" ref={feedRef}>
          {!started && (
            <div style={{ margin: "auto", textAlign: "center", maxWidth: 360 }}>
              <div style={{ width: 64, height: 64, borderRadius: 18, background: "var(--primary-weak)", display: "grid", placeItems: "center", margin: "0 auto 18px" }}>
                <window.Icon name="flag" size={28} color="var(--primary)" />
              </div>
              <div style={{ fontSize: 17, fontWeight: 700, marginBottom: 8 }}>아직 기안이 없습니다</div>
              <div style={{ fontSize: 14, color: "var(--text-2)", lineHeight: 1.6, marginBottom: 20 }}>
                기안하기로 결재 플로우를 시작하세요.<br />기안 → 결재 → 최종확정 흐름이 우측 진행 현황에 카드로 쌓입니다.
              </div>
              <button className="btn btn--dark" onClick={() => setModal({ type: "draft" })}>
                <window.Icon name="flag" size={16} /> 기안하기
              </button>
            </div>
          )}
          {messages.map((m) => (
            <window.ChatMessage key={m.id} m={m} user={window.USERS[m.userId]} />
          ))}
        </div>

        {/* composer */}
        <div className="composer">
          {composerMenu && (
            <div className="composer__menu" onMouseLeave={() => setComposerMenu(false)}>
              <button onClick={() => { setComposerMenu(false); setModal({ type: "draft" }); }}>
                <span className="ic"><window.Icon name="flag" size={18} /></span> 기안하기
              </button>
              <button onClick={() => setComposerMenu(false)}>
                <span className="ic"><window.Icon name="paperclip" size={18} /></span> 파일 첨부
              </button>
            </div>
          )}
          <div className={`composer__box ${closed ? "disabled" : ""}`}>
            <input className="composer__input" placeholder={closed ? "종결된 채널입니다." : "채널에서 나누실 대화를 입력해주세요."}
              value={draft} disabled={closed} onChange={(e) => setDraftText(e.target.value)}
              onKeyDown={(e) => { if (e.key === "Enter") sendText(); }} />
            <div className="composer__btns">
              <button className="composer__plus" disabled={closed} onClick={() => setComposerMenu((v) => !v)}>
                <window.Icon name="plus" size={22} />
              </button>
              <button className="composer__send" disabled={closed} onClick={sendText}>
                <window.Icon name="send" size={18} />
              </button>
            </div>
          </div>
        </div>
      </main>

      {/* ---- progress panel ---- */}
      <aside className="side">
        <div className="panel">
          <div className="panel__head">
            <div className="panel__title">진행 현황</div>
            <div className="panel__sel"><span className="txt">KODEX 반도체레버리지…</span><window.Icon name="chevDown" size={14} /></div>
          </div>

          {closed && (
            <div className="closebanner">
              <div className="t"><window.Icon name="checkCircle" size={17} color="#fff" /> 진행 종결 · 산출물 보관 완료</div>
              <div className="num">심의번호<b>{compNo}</b></div>
              {(() => { const f = phases.find((p) => p.id === "final"); return f && f.finalFile
                ? <window.FileChip name={f.finalFile} /> : null; })()}
            </div>
          )}

          {started && hint && !closed && (
            <div className="hint"><span className="ic"><window.Icon name="arrowRight" size={16} /></span><span>{hint}</span></div>
          )}

          {!started ? (
            <div className="pempty">
              <div className="big">진행 중인 기안이 없습니다</div>
              <div className="sm">기안하기를 누르면 결재 카드가<br />여기에 순서대로 쌓입니다.</div>
              <button className="btn btn--dark" onClick={() => setModal({ type: "draft" })}>
                <window.Icon name="flag" size={16} /> 기안하기
              </button>
            </div>
          ) : (
            <div className="stack">
              {phases.map((p, i) => (
                <window.ProgressCard key={p.id} phase={p} isFirst={i === 0}
                  isActive={p.id === activeId} perspective={perspective} onAction={onCardAction} />
              ))}
            </div>
          )}
        </div>

        <window.RecentFiles />
      </aside>

      {/* persona demo control */}
      <window.Persona value={perspective} onChange={setPerspective} onReset={reset} />

      {/* modals */}
      {modal && modal.type === "draft" && <window.DraftModal onClose={() => setModal(null)} onSubmit={submitDraft} />}
      {modal && modal.type === "approval" && modalPhase &&
        <window.ApprovalModal phase={modalPhase} onClose={() => setModal(null)} onSubmit={submitApproval} />}
      {modal && modal.type === "redo" && modalPhase &&
        <window.RedoModal phase={modalPhase} onClose={() => setModal(null)} onSubmit={submitRedo} />}
      {modal && modal.type === "final" &&
        <window.FinalUploadModal reviewNo={compNo} onClose={() => setModal(null)} onSubmit={submitFinal} />}
    </div>
  );
}

ReactDOM.createRoot(document.getElementById("root")).render(<App />);
