/* =========================================================================
   债务明细清单 · 通用组件库
   ========================================================================= */
const { money, fmtDate, fmtDateTime, STATUS_TONE } = window.Ledger;

/* ---------- 线性图标（统一线宽 1.7，尺寸 by font） ---------- */
function Icon({ name, size = 18, className = "", style = {} }) {
  const common = { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.7, strokeLinecap: "round", strokeLinejoin: "round", className: "ic " + className, style };
  const P = {
    home: <><path d="M3 10.5 12 4l9 6.5" /><path d="M5 9.5V20h14V9.5" /></>,
    users: <><circle cx="9" cy="8" r="3.2" /><path d="M3.5 19c0-3 2.5-5 5.5-5s5.5 2 5.5 5" /><path d="M16 5.2a3 3 0 0 1 0 5.6" /><path d="M17.5 14c2 .4 3.5 2 3.5 4.5" /></>,
    debt: <><path d="M5 4h11l3 3v13H5z" /><path d="M9 9h6M9 13h6M9 17h4" /></>,
    receipt: <><path d="M6 3h12v18l-3-1.6L12 21l-3-1.6L6 21z" /><path d="M9 8h6M9 12h6" /></>,
    chart: <><path d="M4 20V4" /><path d="M4 20h16" /><rect x="7" y="12" width="3" height="5" /><rect x="12" y="8" width="3" height="9" /><rect x="17" y="5" width="3" height="12" /></>,
    settings: <><circle cx="12" cy="12" r="3" /><path d="M12 2v3M12 19v3M2 12h3M19 12h3M5 5l2 2M17 17l2 2M19 5l-2 2M7 17l-2 2" /></>,
    plus: <><path d="M12 5v14M5 12h14" /></>,
    search: <><circle cx="11" cy="11" r="7" /><path d="m20 20-3.2-3.2" /></>,
    chevR: <><path d="m9 6 6 6-6 6" /></>,
    chevD: <><path d="m6 9 6 6 6-6" /></>,
    arrowUp: <><path d="M12 19V5M6 11l6-6 6 6" /></>,
    arrowDown: <><path d="M12 5v14M6 13l6 6 6-6" /></>,
    clock: <><circle cx="12" cy="12" r="8" /><path d="M12 8v4l2.5 2" /></>,
    alert: <><path d="M12 3 2 20h20z" /><path d="M12 10v4M12 17.5v.5" /></>,
    check: <><path d="M5 12.5 10 17 19 7" /></>,
    checkCircle: <><circle cx="12" cy="12" r="9" /><path d="m8 12 2.5 2.5L16 9" /></>,
    x: <><path d="M6 6l12 12M18 6 6 18" /></>,
    edit: <><path d="M4 20h4L19 9l-4-4L4 16z" /><path d="M14 6l4 4" /></>,
    trash: <><path d="M4 7h16M9 7V4h6v3M6 7l1 13h10l1-13" /></>,
    phone: <><path d="M5 4h4l2 5-2.5 1.5a11 11 0 0 0 5 5L16 13l5 2v4a2 2 0 0 1-2 2A16 16 0 0 1 3 6a2 2 0 0 1 2-2z" /></>,
    wechat: <><circle cx="12" cy="12" r="9" /><path d="M8 11h.01M12 11h.01M16 13h.01M13 15h.01" /></>,
    file: <><path d="M6 3h8l4 4v14H6z" /><path d="M14 3v4h4" /></>,
    image: <><rect x="4" y="5" width="16" height="14" rx="2" /><circle cx="9" cy="10" r="1.5" /><path d="m5 17 4-4 3 3 3-3 4 4" /></>,
    download: <><path d="M12 4v10M8 11l4 4 4-4" /><path d="M5 19h14" /></>,
    upload: <><path d="M12 16V6M8 9l4-4 4 4" /><path d="M5 19h14" /></>,
    filter: <><path d="M4 5h16l-6 7v6l-4 2v-8z" /></>,
    more: <><circle cx="6" cy="12" r="1.3" /><circle cx="12" cy="12" r="1.3" /><circle cx="18" cy="12" r="1.3" /></>,
    archive: <><rect x="3" y="4" width="18" height="4" rx="1" /><path d="M5 8v12h14V8" /><path d="M10 12h4" /></>,
    back: <><path d="M15 6l-6 6 6 6" /></>,
    lock: <><rect x="5" y="11" width="14" height="9" rx="2" /><path d="M8 11V8a4 4 0 0 1 8 0v3" /></>,
    logout: <><path d="M14 4h4a1 1 0 0 1 1 1v14a1 1 0 0 1-1 1h-4" /><path d="M9 12h11M16 8l4 4-4 4" /></>,
    bell: <><path d="M6 9a6 6 0 0 1 12 0c0 5 2 6 2 6H4s2-1 2-6z" /><path d="M10 19a2 2 0 0 0 4 0" /></>,
    calendar: <><rect x="4" y="5" width="16" height="16" rx="2" /><path d="M4 9h16M8 3v4M16 3v4" /></>,
    coins: <><ellipse cx="9" cy="7" rx="5" ry="2.5" /><path d="M4 7v5c0 1.4 2.2 2.5 5 2.5s5-1.1 5-2.5V7" /><ellipse cx="15" cy="14" rx="5" ry="2.5" /><path d="M10 14.5V17c0 1.4 2.2 2.5 5 2.5s5-1.1 5-2.5v-5" /></>,
    db: <><ellipse cx="12" cy="5" rx="8" ry="3" /><path d="M4 5v14c0 1.7 3.6 3 8 3s8-1.3 8-3V5" /><path d="M4 12c0 1.7 3.6 3 8 3s8-1.3 8-3" /></>,
    history: <><path d="M3 12a9 9 0 1 0 3-6.7L3 8" /><path d="M3 4v4h4" /><path d="M12 8v4l3 2" /></>,
  };
  return <svg {...common} aria-hidden="true">{P[name] || null}</svg>;
}

/* ---------- 状态标签：文字 + 颜色双重表达 ---------- */
function StatusBadge({ status, size = "md" }) {
  const tone = STATUS_TONE[status] || "neutral";
  return <span className={`badge badge-${tone} badge-${size}`}><span className="badge-dot" />{status}</span>;
}

/* ---------- 头像 ---------- */
function Avatar({ name, size = 38 }) {
  const ch = (name || "?").trim().slice(0, 1);
  // 依据名字生成稳定的中性色
  let h = 0; for (const c of name || "") h = (h * 31 + c.charCodeAt(0)) % 360;
  const bg = `oklch(0.93 0.03 ${h})`, fg = `oklch(0.45 0.08 ${h})`;
  return <span className="avatar" style={{ width: size, height: size, background: bg, color: fg, fontSize: size * 0.42 }}>{ch}</span>;
}

/* ---------- 金额数字（等宽对齐） ---------- */
function Amount({ fen, className = "", sign = false }) {
  const neg = fen < 0;
  return <span className={"num " + className}>{sign && !neg ? "" : ""}{money(fen)}</span>;
}

/* ---------- 金额汇总卡 ---------- */
function AmountCard({ label, fen, display, hint, tone = "neutral", primary = false, onClick, sub }) {
  return (
    <div className={`amt-card ${primary ? "amt-primary" : ""} amt-${tone} ${onClick ? "clickable" : ""}`} onClick={onClick}>
      <div className="amt-label">{label}</div>
      <div className="amt-value num">{display || money(fen)}</div>
      {hint && <div className="amt-hint">{hint}</div>}
      {sub}
    </div>
  );
}

/* ---------- 统计小卡（计数类） ---------- */
function StatCard({ label, value, tone = "neutral", icon, onClick }) {
  return (
    <div className={`stat-card stat-${tone} ${onClick ? "clickable" : ""}`} onClick={onClick}>
      <div className="stat-top">
        <span className="stat-label">{label}</span>
        {icon && <span className={`stat-ic stat-ic-${tone}`}><Icon name={icon} size={16} /></span>}
      </div>
      <div className="stat-value num">{value}</div>
    </div>
  );
}

/* ---------- 进度条（颜色 + 数字） ---------- */
function Progress({ value, paid, due, tone = "blue", showText = true }) {
  const pct = Math.round((value || 0) * 100);
  return (
    <div className="progress-wrap">
      <div className="progress-track"><div className={`progress-fill pf-${tone}`} style={{ width: Math.min(100, pct) + "%" }} /></div>
      {showText && (
        <div className="progress-text">
          <span>已还 {pct}%</span>
          {paid !== undefined && <span className="num muted">{money(paid)} / {money(due)}</span>}
        </div>
      )}
    </div>
  );
}

/* ---------- 债务卡片 ---------- */
function DebtCard({ debt, calc, onClick, onPay }) {
  return (
    <div className="debt-card clickable" onClick={onClick}>
      <div className="debt-card-head">
        <div className="debt-card-title">{debt.title}</div>
        <StatusBadge status={calc.status} size="sm" />
      </div>
      <div className="debt-card-meta">
        <span className="tag-soft">{debt.type}</span>
        <span className="muted">发生 {fmtDate(debt.occurDate)}</span>
        {debt.dueDate && <span className="muted">约定 {fmtDate(debt.dueDate)}</span>}
      </div>
      <div className="debt-card-amts">
        <div><div className="mini-label">剩余待还</div><div className="num strong">{calc.amountPending ? "待补充" : money(calc.remaining)}</div></div>
        <div><div className="mini-label">当前应还</div><div className="num">{money(calc.currentDue)}</div></div>
        <div><div className="mini-label">累计已还</div><div className="num green">{money(calc.paid)}</div></div>
      </div>
      <Progress value={calc.progress} tone={calc.status === "已逾期" ? "red" : calc.status === "已结清" ? "green" : "blue"} showText={false} />
      <div className="debt-card-foot">
        <span className="progress-mini">已还 {Math.round(calc.progress * 100)}%</span>
        {onPay && <button className="btn btn-ghost btn-sm" onClick={(e) => { e.stopPropagation(); onPay(); }}><Icon name="plus" size={14} />记还款</button>}
      </div>
    </div>
  );
}

/* ---------- 进度环 / 甜甜圈图 ---------- */
function Donut({ data, size = 160, thickness = 22 }) {
  const total = data.reduce((s, d) => s + d.value, 0) || 1;
  const r = (size - thickness) / 2;
  const c = 2 * Math.PI * r;
  let offset = 0;
  return (
    <svg width={size} height={size} viewBox={`0 0 ${size} ${size}`} className="donut">
      <g transform={`rotate(-90 ${size / 2} ${size / 2})`}>
        {data.map((d, i) => {
          const frac = d.value / total;
          const len = frac * c;
          const el = (
            <circle key={i} cx={size / 2} cy={size / 2} r={r} fill="none" stroke={d.color} strokeWidth={thickness}
              strokeDasharray={`${len} ${c - len}`} strokeDashoffset={-offset} />
          );
          offset += len;
          return el;
        })}
      </g>
    </svg>
  );
}

/* ---------- 柱状趋势图（月度回款） ---------- */
function BarChart({ data, height = 180, fmt }) {
  const max = Math.max(...data.map((d) => d.fen), 1);
  return (
    <div className="barchart" style={{ height }}>
      {data.map((d, i) => {
        const hPct = (d.fen / max) * 100;
        return (
          <div className="bar-col" key={i} title={fmt ? fmt(d.fen) : d.fen}>
            <div className="bar-val num">{d.fen > 0 ? money(d.fen).replace("¥ ", "¥") : ""}</div>
            <div className="bar-track">
              <div className="bar-fill" style={{ height: Math.max(hPct, d.fen > 0 ? 4 : 0) + "%" }} />
            </div>
            <div className="bar-label">{d.label}</div>
          </div>
        );
      })}
    </div>
  );
}

/* ---------- 时间线 ---------- */
function Timeline({ items }) {
  if (!items.length) return <EmptyState compact icon="history" title="暂无记录" desc="还款、调整与状态变化将在此按时间展示" />;
  return (
    <div className="timeline">
      {items.map((it, i) => (
        <div className={`tl-item tl-${it.tone || "neutral"} ${it.void ? "tl-void" : ""}`} key={i}>
          <div className="tl-marker"><Icon name={it.icon || "clock"} size={14} /></div>
          <div className="tl-body">
            <div className="tl-row">
              <span className="tl-title">{it.title}</span>
              {it.amount !== undefined && <span className={"num tl-amount " + (it.amountClass || "")}>{money(it.amount)}</span>}
            </div>
            <div className="tl-sub muted">{it.sub}</div>
            {it.note && <div className="tl-note">{it.note}</div>}
          </div>
        </div>
      ))}
    </div>
  );
}

/* ---------- 空状态 ---------- */
function EmptyState({ icon = "coins", title, desc, action, compact }) {
  return (
    <div className={`empty ${compact ? "empty-compact" : ""}`}>
      <div className="empty-ic"><Icon name={icon} size={compact ? 22 : 30} /></div>
      <div className="empty-title">{title}</div>
      {desc && <div className="empty-desc">{desc}</div>}
      {action && <div className="empty-action">{action}</div>}
    </div>
  );
}

/* ---------- 骨架屏 ---------- */
function Skeleton({ w = "100%", h = 16, r = 6, style = {} }) {
  return <span className="skeleton" style={{ width: w, height: h, borderRadius: r, ...style }} />;
}
function SkeletonCards({ n = 4 }) {
  return (
    <div className="amt-row">
      {Array.from({ length: n }).map((_, i) => (
        <div className="amt-card" key={i}>
          <Skeleton w="40%" h={12} />
          <div style={{ height: 12 }} />
          <Skeleton w="70%" h={30} />
        </div>
      ))}
    </div>
  );
}
function SkeletonRows({ n = 6, cols = 5 }) {
  return (
    <div className="sk-table">
      {Array.from({ length: n }).map((_, i) => (
        <div className="sk-row" key={i}>
          {Array.from({ length: cols }).map((_, j) => <Skeleton key={j} w={j === 0 ? "22%" : "14%"} h={14} />)}
        </div>
      ))}
    </div>
  );
}

/* ---------- 按钮 ---------- */
function Btn({ kind = "default", size, icon, children, onClick, type = "button", disabled, danger, full }) {
  const cls = `btn btn-${kind} ${size ? "btn-" + size : ""} ${danger ? "btn-danger" : ""} ${full ? "btn-full" : ""}`;
  return <button type={type} className={cls} onClick={onClick} disabled={disabled}>{icon && <Icon name={icon} size={size === "sm" ? 14 : 16} />}{children}</button>;
}

/* ---------- 页面标题区 ---------- */
function PageHeader({ title, desc, actions, back, onBack }) {
  return (
    <div className="page-head">
      <div className="page-head-left">
        {back && <button className="iconbtn" onClick={onBack}><Icon name="back" size={20} /></button>}
        <div>
          <h1 className="page-title">{title}</h1>
          {desc && <div className="page-desc">{desc}</div>}
        </div>
      </div>
      {actions && <div className="page-actions">{actions}</div>}
    </div>
  );
}

/* ---------- 筛选标签（已选条件） ---------- */
function FilterChip({ label, onClear }) {
  return <span className="fchip">{label}{onClear && <button onClick={onClear}><Icon name="x" size={12} /></button>}</span>;
}

/* ---------- 弹窗外壳 ---------- */
function Modal({ title, desc, onClose, children, footer, size = "md", danger }) {
  React.useEffect(() => {
    const h = (e) => { if (e.key === "Escape") onClose(); };
    window.addEventListener("keydown", h);
    document.body.style.overflow = "hidden";
    return () => { window.removeEventListener("keydown", h); document.body.style.overflow = ""; };
  }, []);
  return (
    <div className="modal-overlay" onMouseDown={(e) => { if (e.target === e.currentTarget) onClose(); }}>
      <div className={`modal modal-${size} ${danger ? "modal-danger" : ""}`} role="dialog">
        <div className="modal-head">
          <div>
            <div className="modal-title">{title}</div>
            {desc && <div className="modal-desc">{desc}</div>}
          </div>
          <button className="iconbtn" onClick={onClose}><Icon name="x" size={20} /></button>
        </div>
        <div className="modal-body">{children}</div>
        {footer && <div className="modal-foot">{footer}</div>}
      </div>
    </div>
  );
}

/* ---------- 表单字段 ---------- */
function Field({ label, required, hint, error, children }) {
  return (
    <div className={`field ${error ? "field-error" : ""}`}>
      {label && <label className="field-label">{label}{required && <span className="req">必填</span>}</label>}
      {children}
      {error ? <div className="field-msg err">{error}</div> : hint ? <div className="field-msg">{hint}</div> : null}
    </div>
  );
}

/* ---------- Toast ---------- */
function Toast({ toast }) {
  if (!toast) return null;
  return (
    <div className={`toast toast-${toast.tone || "success"}`}>
      <Icon name={toast.tone === "error" ? "alert" : "checkCircle"} size={18} />
      <span>{toast.msg}</span>
    </div>
  );
}

Object.assign(window, {
  Icon, StatusBadge, Avatar, Amount, AmountCard, StatCard, Progress, DebtCard,
  Donut, BarChart, Timeline, EmptyState, Skeleton, SkeletonCards, SkeletonRows,
  Btn, PageHeader, FilterChip, Modal, Field, Toast,
});
