const $ = (selector) => document.querySelector(selector);
const $$ = (selector) => [...document.querySelectorAll(selector)];

const state = { caseId: null, providerMode: "sample", busy: false };
const stateLabels = {
  NEEDS_INFORMATION: "필수 정보가 부족합니다",
  MANUAL_REVIEW: "사람의 추가 검토가 필요합니다",
  APPROVAL_PENDING: "문서 분석 완료 - 승인 대기",
  COMPLETED: "안전하게 기록 완료",
  PERMANENT_FAILURE: "안전하게 실패 처리됨",
};
const fieldLabels = {
  vendor: "공급자",
  invoice_number: "청구번호",
  amount_krw: "금액",
  document_date: "작성일",
  requested_by: "요청자",
  purpose: "사용목적",
};

async function request(path, body) {
  const options = body === undefined ? {} : {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(body),
  };
  const response = await fetch(path, options);
  const payload = await response.json();
  if (!response.ok || !payload.ok) throw new Error(payload.error || `HTTP ${response.status}`);
  return payload.data;
}

function toast(message, error = false) {
  const node = $("#toast");
  node.textContent = message;
  node.className = `toast is-visible${error ? " is-error" : ""}`;
  window.clearTimeout(toast.timer);
  toast.timer = window.setTimeout(() => { node.className = "toast"; }, 2600);
}

function setBusy(value, label) {
  state.busy = value;
  ["#analyzeButton", "#approveButton", "#replayButton"].forEach((selector) => {
    const button = $(selector);
    if (button) button.disabled = value;
  });
  if (value && label) toast(label);
}

function formatValue(name, value) {
  if (value === null || value === undefined || value === "") return "확인 필요";
  if (name === "amount_krw") return `${Number(value).toLocaleString("ko-KR")}원`;
  return String(value);
}

function renderWorkflow(data) {
  const reached = new Set(data.transitions.map((row) => row.to));
  if (data.state === "COMPLETED") reached.add("COMPLETED");
  $$(".workflow-track div").forEach((node) => {
    const required = node.dataset.state;
    const done = required === "PARSING" ? data.transitions.length > 0 : reached.has(required);
    node.classList.toggle("is-done", done);
  });
}

function renderExtraction(extraction) {
  const grid = $("#extractionGrid");
  grid.replaceChildren();
  Object.entries(fieldLabels).forEach(([name, label]) => {
    const wrapper = document.createElement("div");
    const dt = document.createElement("dt");
    const dd = document.createElement("dd");
    dt.textContent = label;
    dd.textContent = formatValue(name, extraction[name]);
    dd.title = dd.textContent;
    wrapper.append(dt, dd);
    grid.append(wrapper);
  });
  const risks = $("#riskBox");
  risks.replaceChildren();
  const items = [...(extraction.risk_flags || []), ...(extraction.missing_fields || []).map((name) => `누락: ${fieldLabels[name] || name}`)];
  if (!items.length) items.push("추가 위험 신호 없음");
  items.forEach((text, index) => {
    const chip = document.createElement("span");
    chip.textContent = text;
    if (items.length === 1 && index === 0 && text.includes("없음")) chip.className = "is-clear";
    risks.append(chip);
  });
}

function renderLog(data) {
  const log = $("#eventLog");
  const rows = [];
  data.transitions.forEach((row) => rows.push({ phase: row.to, detail: row.reason }));
  data.journal.filter((row) => ["AGENT_ACTION", "COMMITTED", "FAILED", "RESULT_REUSED"].includes(row.phase))
    .forEach((row) => rows.push({ phase: row.phase, detail: row.tool || row.request_id || "event" }));
  log.replaceChildren();
  rows.slice(-40).forEach((row) => {
    const li = document.createElement("li");
    const phase = document.createElement("b");
    const detail = document.createElement("span");
    phase.textContent = row.phase;
    detail.textContent = row.detail;
    li.append(phase, detail);
    log.append(li);
  });
  $("#logCount").textContent = String(rows.length);
}

function render(data) {
  state.caseId = data.case_id;
  $("#emptyState").classList.add("is-hidden");
  $("#resultContent").classList.remove("is-hidden");
  $("#caseLabel").textContent = `${data.case_id} · ${data.resume_boundary}`;
  $("#stateText").textContent = stateLabels[data.state] || data.state;
  $("#stateBadge").textContent = data.state;
  $("#modelTag").textContent = data.provider_mode === "live" ? data.model : "SAMPLE MODE";
  renderWorkflow(data);
  renderExtraction(data.extraction);
  renderLog(data);

  const awaiting = data.state === "APPROVAL_PENDING";
  const completed = data.state === "COMPLETED";
  $("#approvalBox").classList.toggle("is-hidden", !awaiting);
  $("#completionBox").classList.toggle("is-hidden", !completed);
  const business = data.business_state || {};
  $("#updateCount").textContent = String(business.update_count || 0);
  $("#duplicateCount").textContent = String(data.duplicate_effect_count || 0);
  $("#reuseCount").textContent = String(data.result_reuse_count || 0);
  $("#retryCount").textContent = String(data.retry_event_count || 0);
}

async function boot() {
  try {
    const data = await request("/api/status");
    state.providerMode = data.provider_mode;
    $("#documentInput").value = data.sample_document;
    const pill = $("#providerPill");
    pill.className = `provider-pill${data.provider_mode === "sample" ? " is-sample" : ""}`;
    pill.innerHTML = `<span class="pulse"></span>${data.provider_mode === "live" ? "Solar Pro 3 연결됨" : "샘플 모드"}`;
    $("#modeNotice").textContent = data.provider_mode === "live"
      ? "API 키는 서버에만 있으며 브라우저로 전달되지 않습니다."
      : "현재는 화면 검증용 샘플 분석기입니다. UPSTAGE_API_KEY를 설정하면 실제 Solar를 호출합니다.";
    const requestedCase = new URLSearchParams(window.location.search).get("case_id");
    if (requestedCase) {
      const existing = await request(`/api/cases/${encodeURIComponent(requestedCase)}`);
      render(existing);
      toast(existing.provider_mode === "live" ? "실제 Solar 자동 검증 결과를 불러왔습니다" : "검증 결과를 불러왔습니다");
    }
  } catch (error) {
    toast(error.message, true);
  }
}

$("#analyzeButton").addEventListener("click", async () => {
  if (state.busy) return;
  const documentText = $("#documentInput").value.trim();
  const faultMode = $("input[name='faultMode']:checked").value;
  try {
    setBusy(true, state.providerMode === "live" ? "Solar가 문서를 분석하고 있습니다" : "샘플 문서를 분석하고 있습니다");
    const data = await request("/api/analyze", { document_text: documentText, fault_mode: faultMode });
    render(data);
    toast(data.state === "APPROVAL_PENDING" ? "분석 완료 - 사람 승인을 기다립니다" : stateLabels[data.state] || data.state);
  } catch (error) {
    toast(error.message, true);
  } finally {
    setBusy(false);
  }
});

$("#approveButton").addEventListener("click", async () => {
  if (state.busy || !state.caseId) return;
  try {
    setBusy(true, "새 실행기가 checkpoint에서 업무를 재개합니다");
    const data = await request("/api/approve", { case_id: state.caseId });
    render(data);
    toast(data.state === "COMPLETED" ? "승인된 기록이 안전하게 완료됐습니다" : stateLabels[data.state] || data.state);
  } catch (error) {
    toast(error.message, true);
  } finally {
    setBusy(false);
  }
});

$("#replayButton").addEventListener("click", async () => {
  if (state.busy || !state.caseId) return;
  try {
    setBusy(true, "같은 실행 요청을 다시 보내는 중입니다");
    const data = await request("/api/replay", { case_id: state.caseId });
    render(data);
    toast("기존 결과를 재사용했습니다. 실제 기록은 한 번입니다.");
  } catch (error) {
    toast(error.message, true);
  } finally {
    setBusy(false);
  }
});

boot();
