/* =========================================================================
   债务明细清单 · 页面（四）2.0 日常记账
   ========================================================================= */
const { dailySummary, dailyCategoryBreakdown, dailyMonthlyTrend, dailyEntryLabel, money, fmtDate, fmtDateTime, yuanToFen, fenToYuanNum } = window.Ledger;

const DAILY_TYPE_LABEL = { expense: "支出", income: "收入", refund: "退款", transfer: "转账" };

function DailyLedgerPage({ state, actions, go, openModal, toast, loading, initialTab }) {
  const [tab, setTab] = React.useState(initialTab || "overview");
  const [q, setQ] = React.useState("");
  const [cat, setCat] = React.useState("");
  const [method, setMethod] = React.useState("");
  const [status, setStatus] = React.useState("all");
  const [exporting, setExporting] = React.useState(false);
  const summary = dailySummary(state);
  const cats = topLevelDailyCategories(state);
  const methods = (state.dailyPaymentMethods || []).slice().sort((a, b) => (a.sortOrder || 0) - (b.sortOrder || 0));
  const rows = filteredDailyEntries(state, { q, cat, method, status });

  React.useEffect(() => { if (initialTab) setTab(initialTab); }, [initialTab]);

  function exportDaily() {
    setExporting(true);
    setTimeout(() => {
      downloadDailyCsv(state, rows);
      setExporting(false);
      toast({ msg: "日常明细已导出", tone: "success" });
    }, 650);
  }

  return (
    <div className="page">
      <PageHeader title="日常记账" desc="2.0 新增模块 · 不影响 1.0 债务计算"
        actions={<>
          <Btn kind="primary" icon="daily" onClick={() => openModal({ type: "dailyEntry" })}>记一笔日常账</Btn>
          <button className={`btn btn-outline ${exporting ? "daily-exporting" : ""}`} onClick={exportDaily} disabled={exporting}><Icon name={exporting ? "clock" : "download"} size={16} />{exporting ? "导出中" : "导出"}</button>
          <Btn kind="outline" icon="x" onClick={() => actions.toggleDailyEnabled()}>{summary.enabled ? "关闭 2.0 入口" : "开启 2.0 入口"}</Btn>
        </>} />

      {!summary.enabled && (
        <div className="daily-off"><Icon name="alert" size={16} />2.0 日常记账入口已关闭。债务 1.0 页面、还款记录和剩余待还计算仍保持可用。</div>
      )}

      <div className="rollback-note"><Icon name="checkCircle" size={15} />可独立关闭，回滚到 1.0 时债务数据保持可用。</div>

      <div className="tabs">
        {[["overview", "总览"], ["list", "明细"], ["stats", "统计报表"], ["categories", "分类管理"], ["methods", "支付方式管理"]].map(([k, l]) => (
          <button key={k} className={"tab " + (tab === k ? "active" : "")} onClick={() => setTab(k)}>{l}</button>
        ))}
      </div>

      {loading ? <DailyLoadingState /> : (
        tab === "overview" ? <DailyOverview state={state} actions={actions} go={go} openModal={openModal} summary={summary} /> :
        tab === "list" ? <DailyList state={state} actions={actions} go={go} openModal={openModal} rows={rows} q={q} setQ={setQ} cat={cat} setCat={setCat} method={method} setMethod={setMethod} status={status} setStatus={setStatus} cats={cats} methods={methods} /> :
        tab === "stats" ? <DailyStats state={state} go={go} /> :
        tab === "categories" ? <DailyCategoryManager state={state} actions={actions} /> :
        <DailyMethodManager state={state} actions={actions} />
      )}
    </div>
  );
}

function DailyOverview({ state, actions, go, openModal, summary }) {
  const trend = dailyMonthlyTrend(state);
  const breakdown = dailyCategoryBreakdown(state);
  const recent = recentDailyEntries(state, 5);
  return (
    <div className="daily-main">
      <DailyKpis summary={summary} />
      <div className="daily-panels">
        <DailyCategoryRank data={breakdown} title="本月分类支出排行" />
        <div className="card">
          <div className="card-head"><div className="card-title">本月支出趋势</div><span className="muted">近 6 个月</span></div>
          <BarChart data={trend} />
        </div>
      </div>
      <div className="card">
        <div className="card-head"><div className="card-title">最近日常记录</div><button className="link" onClick={() => go({ page: "daily", tab: "list" })}>查看全部</button></div>
        <DailyRows state={state} actions={actions} rows={recent} go={go} openModal={openModal} />
      </div>
    </div>
  );
}

function DailyKpis({ summary }) {
  return (
    <div className="daily-kpi-row">
      <DailyKpi label="今日支出" value={money(summary.todayExpense)} icon="calendar" />
      <DailyKpi label="本月支出" value={money(summary.monthExpense)} icon="wallet" />
      <DailyKpi label="本年支出" value={money(summary.yearExpense)} icon="chart" />
      <DailyKpi label="本月记录" value={`${summary.monthCount} 笔`} icon="daily" />
    </div>
  );
}
function DailyKpi({ label, value, icon }) {
  return <div className="daily-kpi"><div><div className="daily-kpi-label">{label}</div><div className="daily-kpi-value num">{value}</div></div><span className="daily-kpi-ic"><Icon name={icon} size={19} /></span></div>;
}

function DailyCategoryRank({ data, title }) {
  const rows = data.length ? data : [];
  return (
    <div className="card">
      <div className="card-head"><div className="card-title">{title}</div><span className="muted">本月</span></div>
      {rows.length === 0 ? <EmptyState compact icon="daily" title="暂无分类支出" desc="记第一笔日常账后会显示排行" /> : (
        <div className="daily-rank">
          {rows.slice(0, 12).map((r, i) => (
            <div className="daily-rank-row" key={r.id}>
              <span className="rank-no">{i + 1}</span>
              <span className="daily-rank-name">{r.name}</span>
              <span className="daily-rank-track"><span className="daily-rank-fill" style={{ width: Math.max(2, r.pct * 100) + "%", background: r.color }} /></span>
              <span className="daily-rank-amt num">{money(r.fen)}</span>
              <span className="daily-rank-pct num">{Math.round(r.pct * 1000) / 10}%</span>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

function DailyList({ state, actions, go, openModal, rows, q, setQ, cat, setCat, method, setMethod, status, setStatus, cats, methods }) {
  const total = rows.filter((e) => e.status !== "void" && e.type === "expense").reduce((s, e) => s + e.amountFen, 0);
  return (
    <div className="daily-main">
      <div className="filterbar">
        <div className="search search-wide">
          <Icon name="search" size={16} className="muted" />
          <input placeholder="搜索商家或对象、标签备注..." value={q} onChange={(e) => setQ(e.target.value)} />
          {q && <button className="iconbtn-xs" onClick={() => setQ("")}><Icon name="x" size={14} /></button>}
        </div>
        <select className="inp-sm" value={cat} onChange={(e) => setCat(e.target.value)}><option value="">全部分类</option>{cats.map((c) => <option key={c.id} value={c.id}>{c.name}</option>)}</select>
        <select className="inp-sm" value={method} onChange={(e) => setMethod(e.target.value)}><option value="">全部支付方式</option>{methods.map((m) => <option key={m.id} value={m.id}>{m.name}</option>)}</select>
        <select className="inp-sm" value={status} onChange={(e) => setStatus(e.target.value)}><option value="all">全部状态</option><option value="active">有效</option><option value="void">已作废</option></select>
      </div>
      <div className="summary-strip">
        <div><span className="ss-label">当前筛选支出</span><span className="ss-amt num">{money(total)}</span></div>
        <span className="ss-div" />
        <div><span className="ss-label">记录条数</span><span className="ss-n num">{rows.length}</span></div>
        <span className="ss-div" />
        <div><span className="ss-label">移动端展示</span><span className="muted">窄屏自动转换为卡片</span></div>
      </div>
      {rows.length === 0 ? (
        <EmptyState icon="search" title="未找到相关记录" desc="请尝试调整搜索条件或分类筛选" action={<Btn kind="outline" size="sm" onClick={() => { setQ(""); setCat(""); setMethod(""); setStatus("all"); }}>清空筛选</Btn>} />
      ) : <DailyRows state={state} actions={actions} rows={rows} go={go} openModal={openModal} />}
    </div>
  );
}

function DailyRows({ state, actions, rows, go, openModal }) {
  return (
    <>
      <div className="card no-pad daily-table-wrap">
        <table className="dtable daily-table">
          <thead><tr><th>发生时间</th><th>分类</th><th>商家或对象</th><th>支付方式</th><th className="ta-r">金额</th><th>标签</th><th className="ta-c">凭证</th><th className="ta-c">状态</th><th className="ta-r">操作</th></tr></thead>
          <tbody>
            {rows.map((e) => <DailyTableRow key={e.id} state={state} actions={actions} entry={e} go={go} openModal={openModal} />)}
          </tbody>
        </table>
      </div>
      <div className="daily-mobile-list">
        {rows.map((e) => <DailyMobileCard key={e.id} state={state} entry={e} go={go} openModal={openModal} />)}
      </div>
    </>
  );
}
function DailyTableRow({ state, actions, entry, go, openModal }) {
  const label = dailyEntryLabel(state, entry);
  const tags = tagNames(state, entry.tags);
  const isVoid = entry.status === "void";
  return (
    <tr className={(isVoid ? "daily-row-void " : "") + "clickable"} onClick={() => go({ page: "dailyDetail", id: entry.id })}>
      <td className="num muted">{fmtDateTime(entry.occurredAt)}</td>
      <td><span className="tag-soft" style={{ borderColor: label.color, color: label.color }}>{label.category}{label.subcategory ? " > " + label.subcategory : ""}</span></td>
      <td>{entry.merchant || "—"}</td>
      <td className="muted">{label.method}</td>
      <td className="ta-r num amount-expense">{money(entry.amountFen)}</td>
      <td>{tags.length ? tags.map((t) => <span className="tag-soft xs" key={t}>{t}</span>) : <span className="muted">—</span>}</td>
      <td className="ta-c">{(entry.attachments || []).length ? <Icon name="image" size={15} className="muted" /> : <span className="muted">—</span>}</td>
      <td className="ta-c"><StatusBadge status={isVoid ? "已作废" : "有效"} size="sm" /></td>
      <td className="ta-r" onClick={(ev) => ev.stopPropagation()}>
        <div className="row-actions">
          <button className="link" onClick={() => go({ page: "dailyDetail", id: entry.id })}>查看</button>
          <button className="link" onClick={() => openModal({ type: "dailyEntry", edit: entry })}>编辑</button>
          {isVoid ? <button className="link" onClick={() => window.confirm("确认恢复该日常账记录？") && actions.restoreDailyEntry(entry.id)}>还原</button> : <button className="link danger" onClick={() => openModal({ type: "dailyVoid", entry })}>作废</button>}
        </div>
      </td>
    </tr>
  );
}
function DailyMobileCard({ state, entry, go, openModal }) {
  const label = dailyEntryLabel(state, entry);
  const isVoid = entry.status === "void";
  return (
    <div className="daily-card" onClick={() => go({ page: "dailyDetail", id: entry.id })}>
      <div className="daily-card-top">
        <div><div className="daily-card-title">{entry.merchant || label.category}</div><div className="daily-card-meta"><span>{label.category}{label.subcategory ? " > " + label.subcategory : ""}</span><span>{label.method}</span><span>{fmtDateTime(entry.occurredAt)}</span></div></div>
        <div className="daily-card-amt num">{money(entry.amountFen)}</div>
      </div>
      <div className="daily-card-meta"><StatusBadge status={isVoid ? "已作废" : "有效"} size="sm" />{(entry.attachments || []).length ? <span><Icon name="image" size={13} /> 有凭证</span> : <span>无凭证</span>}</div>
    </div>
  );
}

function DailyStats({ state, go }) {
  const breakdown = dailyCategoryBreakdown(state);
  const trend = dailyMonthlyTrend(state);
  const methodData = paymentMethodBreakdown(state);
  return (
    <div className="daily-main">
      <div className="daily-panels">
        <DailyCategoryRank data={breakdown} title="分类支出占比" />
        <div className="card"><div className="card-head"><div className="card-title">月度支出趋势</div></div><BarChart data={trend} /></div>
      </div>
      <div className="grid-2">
        <div className="card">
          <div className="card-head"><div className="card-title">支付方式占比</div></div>
          {methodData.length ? <div className="donut-block"><Donut data={methodData.map((m) => ({ value: m.fen, color: m.color }))} /><div className="donut-legend">{methodData.map((m) => <div className="legend-row" key={m.id}><span className="legend-dot" style={{ background: m.color }} /><span className="legend-name">{m.name}</span><span className="num legend-pct">{Math.round(m.pct * 100)}%</span><span className="num muted legend-amt">{money(m.fen)}</span></div>)}</div></div> : <EmptyState compact title="暂无支付数据" />}
        </div>
        <div className="card">
          <div className="card-head"><div className="card-title">可核对明细入口</div></div>
          <div className="info-list">
            {breakdown.slice(0, 6).map((b) => <button className="info-row clickable" key={b.id} onClick={() => go({ page: "daily", tab: "list" })}><span className="info-k">{b.name}</span><span className="info-v num">{money(b.fen)}</span></button>)}
          </div>
        </div>
      </div>
    </div>
  );
}

function DailyCategoryManager({ state, actions }) {
  return (
    <div className="grid-2">
      <div className="card">
        <div className="card-head"><div className="card-title">一级分类</div><span className="muted">默认分类可停用</span></div>
        <div className="manage-list">{topLevelDailyCategories(state).map((c) => <ManageRow key={c.id} item={c} icon={c.icon} color={c.color} onToggle={() => actions.toggleDailyCategory(c.id)} />)}</div>
      </div>
      <div className="card">
        <div className="card-head"><div className="card-title">二级分类</div><span className="muted">历史记录保留原分类</span></div>
        <div className="manage-list">{(state.dailyCategories || []).filter((c) => c.parentId).map((c) => <ManageRow key={c.id} item={c} color="#94A3B8" sub={(state.dailyCategories || []).find((p) => p.id === c.parentId)?.name} onToggle={() => actions.toggleDailyCategory(c.id)} />)}</div>
      </div>
    </div>
  );
}
function DailyMethodManager({ state, actions }) {
  return (
    <div className="card">
      <div className="card-head"><div className="card-title">支付方式管理</div><span className="muted">停用后不影响历史记录</span></div>
      <div className="manage-list">{(state.dailyPaymentMethods || []).map((m) => <ManageRow key={m.id} item={m} icon={m.icon} color="#0F9488" onToggle={() => actions.toggleDailyPaymentMethod(m.id)} />)}</div>
    </div>
  );
}
function ManageRow({ item, icon, color, sub, onToggle }) {
  const disabled = item.status === "disabled";
  return <div className="manage-row"><span className="manage-color" style={{ background: color }} />{icon && <Icon name={icon} size={16} className="muted" />}<div className="manage-name">{item.name}<div className="manage-sub">{sub || (disabled ? "已停用" : "启用中")}</div></div><Btn kind="outline" size="sm" onClick={onToggle}>{disabled ? "启用" : "停用"}</Btn></div>;
}

function DailyEntryDetailPage({ state, id, go, openModal, actions }) {
  const entry = (state.dailyEntries || []).find((e) => e.id === id);
  if (!entry) return <div className="page"><EmptyState title="日常记录不存在" action={<Btn onClick={() => go({ page: "daily" })}>返回日常记账</Btn>} /></div>;
  const label = dailyEntryLabel(state, entry);
  const tags = tagNames(state, entry.tags);
  const isVoid = entry.status === "void";
  return (
    <div className="page">
      <button className="breadcrumb" onClick={() => go({ page: "daily" })}><Icon name="back" size={15} />日常记账</button>
      <div className="detail-head">
        <div className="dh-left">
          <span className="daily-kpi-ic" style={{ background: label.color + "22", color: label.color }}><Icon name={label.icon} size={22} /></span>
          <div><div className="dh-name">{entry.merchant || label.category}<StatusBadge status={isVoid ? "已作废" : "有效"} size="sm" /></div><div className="dh-contacts"><span>{label.category}{label.subcategory ? " > " + label.subcategory : ""}</span><span>{label.method}</span><span className="num">{fmtDateTime(entry.occurredAt)}</span></div>{isVoid && <div className="dh-note red">作废原因：{entry.voidReason}</div>}</div>
        </div>
        <div className="dh-actions">
          <Btn kind="outline" icon="edit" onClick={() => openModal({ type: "dailyEntry", edit: entry })}>编辑</Btn>
          {isVoid ? <Btn kind="outline" icon="check" onClick={() => actions.restoreDailyEntry(entry.id)}>恢复</Btn> : <Btn kind="ghost" danger icon="trash" onClick={() => openModal({ type: "dailyVoid", entry })}>作废</Btn>}
        </div>
      </div>
      <div className="amt-row">
        <AmountCard primary label="记录金额" fen={entry.amountFen} />
        <StatCard label="记账类型" value={DAILY_TYPE_LABEL[entry.type] || "支出"} icon="daily" />
        <StatCard label="附件" value={`${(entry.attachments || []).length} 个`} icon="image" />
        <StatCard label="更新时间" value={fmtDate(entry.updatedAt)} icon="clock" />
      </div>
      <div className="grid-2">
        <div className="card">
          <div className="card-head"><div className="card-title">记录详情</div></div>
          <div className="daily-detail-grid">
            {[["金额", money(entry.amountFen)], ["发生时间", fmtDateTime(entry.occurredAt)], ["一级分类", label.category], ["二级分类", label.subcategory || "—"], ["支付方式", label.method], ["商家或对象", entry.merchant || "—"], ["标签", tags.join("、") || "—"], ["备注", entry.note || "—"], ["创建时间", fmtDateTime(entry.createdAt)], ["更新时间", fmtDateTime(entry.updatedAt)]].map(([k, v]) => <div className="daily-detail-item" key={k}><div className="daily-detail-k">{k}</div><div className="daily-detail-v">{v}</div></div>)}
          </div>
        </div>
        <div className="card">
          <div className="card-head"><div className="card-title">凭证附件</div></div>
          {(entry.attachments || []).length ? <div className="attach-list">{entry.attachments.map((a, i) => <div className="attach-item" key={i}><span className="attach-thumb"><Icon name="image" size={18} /></span><div className="attach-info"><div className="attach-name">{a.name}</div><div className="muted xs">{a.size || "凭证"}</div></div></div>)}</div> : <EmptyState compact icon="image" title="暂无凭证" desc="可在编辑时补充支付截图、发票或缴费截图" />}
        </div>
      </div>
    </div>
  );
}

function DailyEntryModal({ state, actions, edit, toast, onClose }) {
  const nowLocal = toLocalInput(new Date());
  const [form, setForm] = React.useState(() => edit ? {
    ...edit,
    amount: fenToYuanNum(edit.amountFen),
    occurredAtLocal: toLocalInput(edit.occurredAt),
  } : {
    type: "expense", amount: "", occurredAtLocal: nowLocal, categoryId: "dc_food", subcategoryId: "dsc_lunch", paymentMethodId: "dpm_wechat", merchant: "", tags: [], note: "", attachments: [],
  });
  const [err, setErr] = React.useState("");
  const cats = topLevelDailyCategories(state).filter((c) => c.status !== "disabled");
  const subs = (state.dailyCategories || []).filter((c) => c.parentId === form.categoryId && c.status !== "disabled");
  const methods = (state.dailyPaymentMethods || []).filter((m) => m.status !== "disabled");
  const tags = (state.dailyTags || []).filter((t) => t.status !== "disabled");

  function set(k, v) { setForm((f) => ({ ...f, [k]: v })); }
  function toggleTag(id) { setForm((f) => ({ ...f, tags: (f.tags || []).includes(id) ? f.tags.filter((x) => x !== id) : [...(f.tags || []), id] })); }
  function submit(e) {
    if (e) e.preventDefault();
    const amountFen = yuanToFen(form.amount);
    if (amountFen <= 0) { setErr("保存失败：金额必须大于 0"); return; }
    if (!form.categoryId || !form.paymentMethodId || !form.occurredAtLocal) { setErr("保存失败：请检查必填项"); return; }
    actions.upsertDailyEntry({ ...form, amountFen, occurredAt: new Date(form.occurredAtLocal).toISOString(), attachments: form.attachments || [] });
    toast({ msg: edit ? "日常账已更新" : "日常账已保存", tone: "success" });
    onClose();
  }
  return (
    <Modal title={edit ? "编辑日常账" : "新增日常账"} desc="日常支出独立于 1.0 债务计算" onClose={onClose} size="lg"
      footer={<><div className="foot-info">{err ? <span className="red">{err}</span> : "保存后会立即刷新日常统计"}</div><div className="foot-btns"><Btn kind="outline" onClick={onClose}>取消</Btn><Btn kind="primary" icon="check" onClick={submit}>保存</Btn></div></>}>
      <form onSubmit={submit} className="form-grid">
        <div className={`daily-amount-box ${err ? "error" : ""}`} style={{ gridColumn: "1/-1" }}>
          <div className="daily-amount-label">金额 <span className="req">必填</span></div>
          <div className="daily-amount-row"><span>¥</span><input value={form.amount} onChange={(e) => { set("amount", e.target.value); setErr(""); }} placeholder="0.00" inputMode="decimal" /></div>
          {err && <div className="field-msg err">{err}</div>}
        </div>
        <Field label="发生时间" required><input className="inp" type="datetime-local" value={form.occurredAtLocal} onChange={(e) => set("occurredAtLocal", e.target.value)} /></Field>
        <Field label="支付方式" required><select className="inp" value={form.paymentMethodId} onChange={(e) => set("paymentMethodId", e.target.value)}>{methods.map((m) => <option key={m.id} value={m.id}>{m.name}</option>)}</select></Field>
        <Field label="一级分类" required><select className="inp" value={form.categoryId} onChange={(e) => setForm((f) => ({ ...f, categoryId: e.target.value, subcategoryId: "" }))}>{cats.map((c) => <option key={c.id} value={c.id}>{c.name}</option>)}</select></Field>
        <Field label="二级分类"><select className="inp" value={form.subcategoryId || ""} onChange={(e) => set("subcategoryId", e.target.value)}><option value="">不选择</option>{subs.map((c) => <option key={c.id} value={c.id}>{c.name}</option>)}</select></Field>
        <Field label="商家或对象"><input className="inp" value={form.merchant || ""} onChange={(e) => set("merchant", e.target.value)} placeholder="如：南方电网、房东张先生" /></Field>
        <Field label="标签"><div className="chips-row">{tags.map((t) => <button type="button" key={t.id} className={"tag-soft " + ((form.tags || []).includes(t.id) ? "tag-blue" : "")} onClick={() => toggleTag(t.id)}>{t.name}</button>)}</div></Field>
        <Field label="备注"><textarea className="inp" style={{ height: 86, paddingTop: 10 }} value={form.note || ""} onChange={(e) => set("note", e.target.value)} placeholder="可选，输入备注信息..." /></Field>
        <Field label="凭证附件"><button type="button" className="upload-zone uploaded"><Icon name="image" size={16} />{(form.attachments || []).length ? `${form.attachments.length} 个附件` : "添加附件（设计态）"}</button></Field>
      </form>
    </Modal>
  );
}

function DailyVoidModal({ entry, actions, toast, onClose }) {
  const [reason, setReason] = React.useState("");
  return (
    <Modal title="作废日常账" desc="作废后不参与日常统计，但保留历史记录" danger onClose={onClose}
      footer={<><div className="foot-info red">必须填写作废原因</div><div className="foot-btns"><Btn kind="outline" onClick={onClose}>取消</Btn><Btn danger icon="trash" disabled={!reason.trim()} onClick={() => { actions.voidDailyEntry(entry.id, reason.trim()); toast({ msg: "日常账已作废", tone: "success" }); onClose(); }}>确认作废</Btn></div></>}>
      <div className="danger-box"><Icon name="alert" size={18} /><div><div className="db-title">影响范围</div><div className="db-list"><span>该记录金额 {money(entry.amountFen)} 将不再参与日常统计。</span><span>1.0 债务和还款汇总不受影响。</span></div></div></div>
      <Field label="作废原因" required><textarea className="inp" style={{ height: 86, paddingTop: 10 }} value={reason} onChange={(e) => setReason(e.target.value)} placeholder="例如：重复录入、金额录错" /></Field>
    </Modal>
  );
}

function DailyLoadingState() {
  return <div className="daily-main"><SkeletonCards n={4} /><div className="grid-2"><div className="card"><SkeletonRows n={8} cols={4} /></div><div className="card"><SkeletonRows n={8} cols={4} /></div></div></div>;
}

function topLevelDailyCategories(state) {
  return (state.dailyCategories || []).filter((c) => !c.parentId).slice().sort((a, b) => (a.sortOrder || 0) - (b.sortOrder || 0));
}
function recentDailyEntries(state, n) {
  return (state.dailyEntries || []).slice().sort((a, b) => new Date(b.occurredAt) - new Date(a.occurredAt)).slice(0, n || 10);
}
function filteredDailyEntries(state, filters) {
  let rows = (state.dailyEntries || []).slice();
  if (filters.status !== "all") rows = rows.filter((e) => filters.status === "void" ? e.status === "void" : e.status !== "void");
  if (filters.cat) rows = rows.filter((e) => e.categoryId === filters.cat);
  if (filters.method) rows = rows.filter((e) => e.paymentMethodId === filters.method);
  if (filters.q) {
    const q = filters.q.toLowerCase();
    rows = rows.filter((e) => {
      const label = dailyEntryLabel(state, e);
      return [e.merchant, e.note, label.category, label.subcategory, label.method, ...tagNames(state, e.tags)].join(" ").toLowerCase().includes(q);
    });
  }
  return rows.sort((a, b) => new Date(b.occurredAt) - new Date(a.occurredAt));
}
function tagNames(state, ids) {
  return (ids || []).map((id) => (state.dailyTags || []).find((t) => t.id === id)?.name).filter(Boolean);
}
function paymentMethodBreakdown(state) {
  const active = window.Ledger.dailyActiveEntries(state).filter((e) => e.type === "expense");
  const map = {};
  active.forEach((e) => { map[e.paymentMethodId] = (map[e.paymentMethodId] || 0) + e.amountFen; });
  const colors = ["#0F9488", "#2F6BD8", "#6B5BD2", "#D98C2B", "#1F8A52", "#94A3B8"];
  const total = Object.values(map).reduce((s, v) => s + v, 0) || 1;
  return Object.entries(map).map(([id, fen], i) => ({ id, fen, pct: fen / total, color: colors[i % colors.length], name: (state.dailyPaymentMethods || []).find((m) => m.id === id)?.name || "其他" })).sort((a, b) => b.fen - a.fen);
}
function toLocalInput(v) {
  const d = typeof v === "string" ? new Date(v) : v;
  const pad = (n) => String(n).padStart(2, "0");
  return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}`;
}
function downloadDailyCsv(state, rows) {
  const esc = (v) => `"${String(v == null ? "" : v).replace(/"/g, '""')}"`;
  const lines = [["发生时间", "类型", "一级分类", "二级分类", "支付方式", "商家或对象", "金额", "标签", "备注", "附件名", "状态", "作废原因", "创建时间", "更新时间"].map(esc).join(",")];
  rows.forEach((e) => {
    const label = dailyEntryLabel(state, e);
    lines.push([fmtDateTime(e.occurredAt), DAILY_TYPE_LABEL[e.type] || "支出", label.category, label.subcategory, label.method, e.merchant, (e.amountFen / 100).toFixed(2), tagNames(state, e.tags).join("；"), e.note, (e.attachments || []).map((a) => a.name).join("；"), e.status === "void" ? "已作废" : "有效", e.voidReason || "", fmtDateTime(e.createdAt), fmtDateTime(e.updatedAt)].map(esc).join(","));
  });
  const blob = new Blob(["\ufeff" + lines.join("\n")], { type: "text/csv;charset=utf-8" });
  const url = URL.createObjectURL(blob);
  const a = document.createElement("a");
  a.href = url; a.download = `日常记账明细_${fmtDate(new Date())}.csv`; a.click();
  URL.revokeObjectURL(url);
}

Object.assign(window, { DailyLedgerPage, DailyEntryDetailPage, DailyEntryModal, DailyVoidModal });
