/* =========================================================================
   债务明细清单 · 应用外壳 + 路由 + 数据操作
   ========================================================================= */
const { uid, money, fmtDate, fmtDateTime } = window.Ledger;

const NAV = [
  { key: "home", label: "首页总览", icon: "home" },
  { key: "debtors", label: "欠款人", icon: "users" },
  { key: "debts", label: "债务", icon: "debt" },
  { key: "payments", label: "还款明细", icon: "receipt" },
  { key: "stats", label: "统计报表", icon: "chart" },
  { key: "audit", label: "操作记录", icon: "history" },
  { key: "settings", label: "设置", icon: "settings" },
];
const MOBILE_NAV = ["home", "debtors", "payments", "more"];

/* CSV 导出构建 */
window.buildExportCSV = function (state, sel) {
  const L = window.Ledger;
  const lines = [];
  const esc = (v) => `"${String(v == null ? "" : v).replace(/"/g, '""')}"`;
  const yuan = (f) => (f / 100).toFixed(2);
  if (sel.debtors) {
    lines.push("【欠款人汇总】");
    lines.push(["姓名", "关系", "手机号", "债务笔数", "当前应还", "累计已还", "剩余待还", "状态"].map(esc).join(","));
    state.debtors.forEach((d) => { const c = L.debtorCalc(state, d.id); lines.push([d.name, d.relation, d.phone, c.debtCount, yuan(c.currentDue), yuan(c.paid), yuan(c.remaining), c.status].map(esc).join(",")); });
    lines.push("");
  }
  if (sel.debts) {
    lines.push("【债务汇总】");
    lines.push(["债务标题", "欠款人", "类型", "发生日期", "约定日期", "原始应还", "当前应还", "累计已还", "剩余待还", "状态"].map(esc).join(","));
    state.debts.forEach((d) => { const c = L.debtCalc(state, d.id); const dn = state.debtors.find((x) => x.id === d.debtorId).name; lines.push([d.title, dn, d.type, d.occurDate, d.dueDate, yuan(d.principalFen), yuan(c.currentDue), yuan(c.paid), yuan(c.remaining), c.status].map(esc).join(",")); });
    lines.push("");
  }
  if (sel.payments) {
    lines.push("【还款明细】");
    lines.push(["日期时间", "欠款人", "债务", "途径", "流水号", "收款账户", "金额", "状态", "备注"].map(esc).join(","));
    state.payments.forEach((p) => { const dn = state.debtors.find((x) => x.id === p.debtorId).name; const tt = state.debts.find((x) => x.id === p.debtId).title; lines.push([L.fmtDateTime(p.datetime), dn, tt, p.channel, p.txnNo, p.account, yuan(p.amountFen), p.status === "void" ? "已作废" : "有效", p.status === "void" ? p.voidReason : p.note].map(esc).join(",")); });
    lines.push("");
  }
  if (sel.adjustments) {
    lines.push("【金额调整明细】");
    lines.push(["日期", "债务", "类型", "金额", "原因", "状态"].map(esc).join(","));
    state.adjustments.forEach((a) => { const tt = state.debts.find((x) => x.id === a.debtId).title; lines.push([a.date, tt, a.type === "increase" ? "增加" : "减免", yuan(a.amountFen), a.reason, a.status === "void" ? "已作废" : "有效"].map(esc).join(",")); });
  }
  return lines.join("\n");
};

window.downloadLedgerAttachment = function (att) {
  if (!att) return;
  if (att.dataUrl) {
    const a = document.createElement("a");
    a.href = att.dataUrl;
    a.download = att.name || "attachment";
    a.click();
    return;
  }
  alert(`该附件来自历史凭证清单，当前只有文件名记录：${att.name || "未命名附件"}`);
};

function App() {
  const [authed, setAuthed] = React.useState(() => window.Ledger.isAuthSessionValid());
  const [state, setState] = React.useState(() => window.Ledger.load());
  const [route, setRoute] = React.useState({ page: "home" });
  const [modal, setModal] = React.useState(null);
  const [toast, setToast] = React.useState(null);
  const [loading, setLoading] = React.useState(true);
  const [mobileMore, setMobileMore] = React.useState(false);
  const toastTimer = React.useRef(null);

  // 首屏骨架屏演示
  React.useEffect(() => { const t = setTimeout(() => setLoading(false), 650); return () => clearTimeout(t); }, []);
  React.useEffect(() => { if (!loading) { setLoading(true); const t = setTimeout(() => setLoading(false), 350); return () => clearTimeout(t); } }, [route.page]);
  React.useEffect(() => {
    if (!authed) return;
    const events = ["click", "keydown", "mousemove", "touchstart"];
    const touch = () => window.Ledger.touchAuthSession();
    events.forEach((e) => window.addEventListener(e, touch, { passive: true }));
    const timer = setInterval(() => {
      if (!window.Ledger.isAuthSessionValid()) {
        window.Ledger.clearAuthSession();
        setAuthed(false);
        showToast({ msg: "登录已超时，请重新登录", tone: "error" });
      }
    }, 60000);
    return () => {
      events.forEach((e) => window.removeEventListener(e, touch));
      clearInterval(timer);
    };
  }, [authed]);

  function persist(next) { window.Ledger.save(next); setState({ ...next }); }
  function showToast(t) { setToast(t); clearTimeout(toastTimer.current); toastTimer.current = setTimeout(() => setToast(null), 2600); }
  function go(r) { setRoute(typeof r === "string" ? { page: r } : r); setMobileMore(false); window.scrollTo(0, 0); const main = document.querySelector(".main-scroll"); if (main) main.scrollTop = 0; }

  function logAudit(next, type, target, summary) {
    next.auditLog.unshift({ id: uid("l"), time: window.Ledger.TODAY.toISOString(), type, target, summary });
  }

  const actions = {
    addPayment(pay) {
      const next = { ...state };
      const p = { id: uid("p"), ...pay, status: "valid", createdAt: window.Ledger.TODAY.toISOString(), updatedAt: window.Ledger.TODAY.toISOString() };
      next.payments = [...next.payments, p];
      const debtor = next.debtors.find((x) => x.id === pay.debtorId), debt = next.debts.find((x) => x.id === pay.debtId);
      logAudit(next, "新增还款", `${debtor.name} · ${debt.title}`, `新增还款 ${money(pay.amountFen)}（${pay.channel}）`);
      persist(next);
    },
    updatePayment(pay) {
      const next = { ...state };
      next.payments = next.payments.map((p) => p.id === pay.id ? { ...p, ...pay, updatedAt: new Date().toISOString() } : p);
      const debtor = next.debtors.find((x) => x.id === pay.debtorId), debt = next.debts.find((x) => x.id === pay.debtId);
      logAudit(next, "编辑还款", `${debtor.name} · ${debt.title}`, `更新还款记录 ${money(pay.amountFen)}（${pay.channel}）`);
      persist(next);
    },
    voidPayment(id, reason) {
      const next = { ...state };
      next.payments = next.payments.map((p) => p.id === id ? { ...p, status: "void", voidReason: reason, updatedAt: window.Ledger.TODAY.toISOString() } : p);
      const p = next.payments.find((x) => x.id === id);
      const debtor = next.debtors.find((x) => x.id === p.debtorId), debt = next.debts.find((x) => x.id === p.debtId);
      logAudit(next, "作废还款", `${debtor.name} · ${debt.title}`, `作废还款 ${money(p.amountFen)}（${reason}）`);
      persist(next);
    },
    restorePayment(id) {
      const next = { ...state };
      next.payments = next.payments.map((p) => p.id === id ? { ...p, status: "valid", voidReason: "", updatedAt: new Date().toISOString() } : p);
      const p = next.payments.find((x) => x.id === id);
      const debtor = next.debtors.find((x) => x.id === p.debtorId), debt = next.debts.find((x) => x.id === p.debtId);
      logAudit(next, "恢复还款", `${debtor.name} · ${debt.title}`, `恢复还款 ${money(p.amountFen)}`);
      persist(next);
    },
    upsertDebtor(f) {
      const next = { ...state };
      if (f.id) { next.debtors = next.debtors.map((d) => d.id === f.id ? { ...d, ...f } : d); logAudit(next, "编辑", f.name, "更新欠款人资料"); }
      else { const nd = { ...f, id: uid("d"), status: "active", createdAt: window.Ledger.TODAY.toISOString() }; next.debtors = [...next.debtors, nd]; logAudit(next, "新增欠款人", f.name, "新增欠款人"); }
      persist(next);
    },
    upsertDebt(f) {
      const next = { ...state };
      if (f.id) { next.debts = next.debts.map((d) => d.id === f.id ? { ...d, ...f } : d); logAudit(next, "编辑", f.title, "更新债务信息"); }
      else { const nd = { ...f, id: uid("b"), archived: false, attachments: f.attachments || [], createdAt: window.Ledger.TODAY.toISOString() }; next.debts = [...next.debts, nd]; const dn = next.debtors.find((x) => x.id === f.debtorId).name; logAudit(next, "新增债务", `${dn} · ${f.title}`, `新增债务，原始应还 ${money(f.principalFen)}`); }
      persist(next);
    },
    addAdjustment(a) {
      const next = { ...state };
      next.adjustments = [...next.adjustments, { id: uid("a"), ...a, status: "valid", createdAt: window.Ledger.TODAY.toISOString() }];
      const debt = next.debts.find((x) => x.id === a.debtId), dn = next.debtors.find((x) => x.id === debt.debtorId).name;
      logAudit(next, "金额调整", `${dn} · ${debt.title}`, `${a.type === "increase" ? "增加" : "减免"}应还 ${money(a.amountFen)}（${a.reason}）`);
      persist(next);
    },
    voidAdjustment(id, reason) {
      const next = { ...state };
      next.adjustments = next.adjustments.map((a) => a.id === id ? { ...a, status: "void", voidReason: reason, updatedAt: new Date().toISOString() } : a);
      const adj = next.adjustments.find((a) => a.id === id);
      const debt = next.debts.find((x) => x.id === adj.debtId), dn = next.debtors.find((x) => x.id === debt.debtorId).name;
      logAudit(next, "作废调整", `${dn} · ${debt.title}`, `作废${adj.type === "increase" ? "增加" : "减免"}应还 ${money(adj.amountFen)}（${reason}）`);
      persist(next);
    },
    restoreAdjustment(id) {
      const next = { ...state };
      next.adjustments = next.adjustments.map((a) => a.id === id ? { ...a, status: "valid", voidReason: "", updatedAt: new Date().toISOString() } : a);
      const adj = next.adjustments.find((a) => a.id === id);
      const debt = next.debts.find((x) => x.id === adj.debtId), dn = next.debtors.find((x) => x.id === debt.debtorId).name;
      logAudit(next, "恢复调整", `${dn} · ${debt.title}`, `恢复金额调整 ${money(adj.amountFen)}`);
      persist(next);
    },
    archiveDebt(id) { const next = { ...state }; next.debts = next.debts.map((d) => d.id === id ? { ...d, archived: !d.archived } : d); persist(next); showToast({ msg: "已更新归档状态", tone: "success" }); },
    addChannel(c) { const next = { ...state }; if (!next.channels.includes(c)) next.channels = [...next.channels, c]; persist(next); },
    removeChannel(c) { const next = { ...state }; next.channels = next.channels.filter((x) => x !== c); persist(next); showToast({ msg: "已停用该途径", tone: "success" }); },
    addRelation(v) { const next = { ...state }; if (!next.relations.includes(v)) next.relations = [...next.relations, v]; persist(next); },
    removeRelation(v) { const next = { ...state }; next.relations = next.relations.filter((x) => x !== v); persist(next); },
    addDebtType(v) { const next = { ...state }; if (!next.debtTypes.includes(v)) next.debtTypes = [...next.debtTypes, v]; persist(next); },
    removeDebtType(v) { const next = { ...state }; next.debtTypes = next.debtTypes.filter((x) => x !== v); persist(next); },
    setRemind(v) { const next = { ...state }; next.settings = { ...next.settings, remindDays: v }; persist(next); },
    backupData() {
      const blob = new Blob([JSON.stringify(state, null, 2)], { type: "application/json;charset=utf-8" });
      const url = URL.createObjectURL(blob);
      const a = document.createElement("a");
      a.href = url;
      a.download = `债务明细备份_${window.Ledger.fmtDate(new Date())}.json`;
      a.click();
      URL.revokeObjectURL(url);
      showToast({ msg: "完整数据备份已下载", tone: "success" });
    },
    restoreData(data) {
      const valid = data && Array.isArray(data.debtors) && Array.isArray(data.debts) && Array.isArray(data.payments) && Array.isArray(data.adjustments) && Array.isArray(data.auditLog);
      if (!valid) throw new Error("备份文件结构不正确");
      persist(data);
      setRoute({ page: "home" });
    },
    resetData() { const fresh = window.Ledger.reset(); setState(fresh); setRoute({ page: "home" }); },
    changePassword(oldPassword, newPassword) { return window.Ledger.changePassword(oldPassword, newPassword); },
  };

  function openModal(m) { setModal(m); }
  function closeModal() { setModal(null); }

  if (!authed) return <LoginPage onLogin={() => { window.Ledger.setAuthSession(); setAuthed(true); }} />;

  const pageProps = { state, actions, go, openModal, toast: showToast, loading };
  let Page;
  switch (route.page) {
    case "home": Page = <HomePage {...pageProps} />; break;
    case "debtors": Page = <DebtorListPage {...pageProps} />; break;
    case "debtor": Page = <DebtorDetailPage {...pageProps} id={route.id} />; break;
    case "debts": Page = <DebtListPage {...pageProps} initialFilter={route.filter} />; break;
    case "debt": Page = <DebtDetailPage {...pageProps} id={route.id} />; break;
    case "payments": Page = <PaymentListPage {...pageProps} />; break;
    case "stats": Page = <StatsPage {...pageProps} />; break;
    case "audit": Page = <AuditPage {...pageProps} />; break;
    case "settings": Page = <SettingsPage {...pageProps} />; break;
    default: Page = <HomePage {...pageProps} />;
  }

  const curNav = NAV.find((n) => n.key === route.page) || (["debtor"].includes(route.page) ? NAV[1] : ["debt"].includes(route.page) ? NAV[2] : NAV[0]);

  return (
    <div className="app">
      {/* 侧边导航（桌面） */}
      <aside className="sidebar">
        <div className="logo"><span className="brand-mark"><Icon name="coins" size={20} /></span><div className="logo-text"><div className="logo-name">债务明细清单</div><div className="logo-sub">别人欠我的钱</div></div></div>
        <nav className="nav">
          {NAV.map((n) => (
            <button key={n.key} className={"nav-item " + (curNav.key === n.key ? "active" : "")} onClick={() => go({ page: n.key })}>
              <Icon name={n.icon} size={19} /><span>{n.label}</span>
            </button>
          ))}
        </nav>
        <div className="sidebar-foot">
          <button className="nav-item nav-cta" onClick={() => openModal({ type: "payment" })}><Icon name="plus" size={19} /><span>记一笔还款</span></button>
          <button className="nav-item subtle" onClick={() => { window.Ledger.clearAuthSession(); setAuthed(false); }}><Icon name="logout" size={18} /><span>退出登录</span></button>
        </div>
      </aside>

      {/* 主区 */}
      <main className="main">
        <div className="main-scroll">{Page}</div>
      </main>

      {/* 移动端底部导航 */}
      <nav className="mobile-nav">
        <button className={"mn-item " + (curNav.key === "home" ? "active" : "")} onClick={() => go({ page: "home" })}><Icon name="home" size={20} /><span>首页</span></button>
        <button className={"mn-item " + (["debtors", "debtor"].includes(route.page) ? "active" : "")} onClick={() => go({ page: "debtors" })}><Icon name="users" size={20} /><span>欠款人</span></button>
        <button className="mn-fab" onClick={() => openModal({ type: "payment" })}><Icon name="plus" size={24} /></button>
        <button className={"mn-item " + (route.page === "payments" ? "active" : "")} onClick={() => go({ page: "payments" })}><Icon name="receipt" size={20} /><span>明细</span></button>
        <button className={"mn-item " + (mobileMore ? "active" : "")} onClick={() => setMobileMore(!mobileMore)}><Icon name="more" size={20} /><span>更多</span></button>
      </nav>
      {mobileMore && (
        <div className="mobile-sheet" onClick={() => setMobileMore(false)}>
          <div className="ms-panel" onClick={(e) => e.stopPropagation()}>
            <div className="ms-grip" />
            {NAV.filter((n) => ["debts", "stats", "audit", "settings"].includes(n.key)).map((n) => (
              <button key={n.key} className="ms-item" onClick={() => go({ page: n.key })}><Icon name={n.icon} size={20} />{n.label}</button>
            ))}
            <button className="ms-item danger" onClick={() => { window.Ledger.clearAuthSession(); setAuthed(false); }}><Icon name="logout" size={20} />退出登录</button>
          </div>
        </div>
      )}

      {/* 弹窗 */}
      {modal && modal.type === "payment" && <PaymentModal state={state} actions={actions} preset={modal.preset || {}} edit={modal.edit} toast={showToast} onClose={() => closeModal()} />}
      {modal && modal.type === "debtor" && <DebtorModal state={state} actions={actions} edit={modal.edit} toast={showToast} onClose={closeModal} />}
      {modal && modal.type === "debt" && <DebtModal state={state} actions={actions} presetDebtorId={modal.presetDebtorId} edit={modal.edit} toast={showToast} onClose={closeModal} />}
      {modal && modal.type === "adjust" && <AdjustModal state={state} actions={actions} debtId={modal.debtId} toast={showToast} onClose={closeModal} />}
      {modal && modal.type === "void" && <VoidModal state={state} actions={actions} payment={modal.payment} toast={showToast} onClose={closeModal} />}
      {modal && modal.type === "export" && <ExportModal state={modal.data || state} scope={modal.scope} toast={showToast} onClose={closeModal} />}
      {modal && modal.type === "restore" && <RestoreModal actions={actions} toast={showToast} onClose={closeModal} />}
      {modal && modal.type === "password" && <PasswordModal actions={actions} toast={showToast} onClose={closeModal} />}

      <Toast toast={toast} />
    </div>
  );
}

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