// Accounting / 个人记账 Page
// 完整功能：账单 / 往来（应收应付/借入借出） / 统计 / 账户
// 绿色清新风格，数据按用户隔离

const { useState, useEffect, useCallback, useRef, useMemo } = React;

// ===== 颜色常量（绿色清新风格） =====
const ACC_COLORS = {
  primary: '#00B578',
  primaryLight: '#36D399',
  primarySoft: '#E6FFED',
  primaryDark: '#009665',
  expense: '#F53F3F',
  income: '#00B578',
  warn: '#FF7D00',
  danger: '#F53F3F',
  receivable: '#00B578',  // 别人欠我 - 绿色
  payable: '#F53F3F',     // 我欠别人 - 红色
  lend: '#0EA5E9',        // 借出 - 蓝
  borrow: '#F59E0B',      // 借入 - 橙
  bg: '#F7F9FA',
  card: '#FFFFFF',
  textPrimary: '#1D2129',
  textSecondary: '#4E5969',
  textTertiary: '#86909C',
  border: '#F2F3F5',
};

function fmt(n) { return parseFloat(n || 0).toFixed(2); }
function fmtDate(dateStr) {
  if (!dateStr) return '';
  const d = new Date(dateStr);
  const today = new Date();
  const yesterday = new Date(); yesterday.setDate(yesterday.getDate() - 1);
  const isToday = d.toDateString() === today.toDateString();
  const isYesterday = d.toDateString() === yesterday.toDateString();
  if (isToday) return '今天';
  if (isYesterday) return '昨天';
  return `${d.getMonth() + 1}月${d.getDate()}日`;
}
function daysUntil(dateStr) {
  if (!dateStr) return null;
  const d = new Date(dateStr);
  const today = new Date();
  today.setHours(0, 0, 0, 0);
  d.setHours(0, 0, 0, 0);
  return Math.round((d - today) / 86400000);
}

// ========== Category Picker ==========
function CategoryPicker({ categories, value, onChange }) {
  return (
    <div style={{ display: 'grid', gridTemplateColumns: 'repeat(5, 1fr)', gap: 8 }}>
      {categories.map(cat => {
        const active = value === cat.name;
        return (
          <div key={cat.id || cat.name} onClick={() => onChange(cat.name)}
            style={{
              display: 'flex', flexDirection: 'column', alignItems: 'center',
              padding: '10px 4px', borderRadius: 12,
              background: active ? ACC_COLORS.primarySoft : 'transparent',
              cursor: 'pointer', transition: 'all 0.2s',
              border: active ? `1.5px solid ${ACC_COLORS.primary}` : '1.5px solid transparent',
            }}>
            <div style={{ fontSize: 24, marginBottom: 4 }}>{cat.icon}</div>
            <div style={{
              fontSize: 11,
              color: active ? ACC_COLORS.primary : ACC_COLORS.textSecondary,
              fontWeight: active ? 600 : 400,
            }}>{cat.name}</div>
          </div>
        );
      })}
    </div>
  );
}

// ========== Account Picker ==========
function AccountPicker({ accounts, value, onChange }) {
  return (
    <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
      {accounts.map(acc => {
        const active = value === acc.name;
        return (
          <div key={acc.id} onClick={() => onChange(acc.name)}
            style={{
              display: 'flex', alignItems: 'center', gap: 6,
              padding: '8px 14px', borderRadius: 20,
              background: active ? ACC_COLORS.primarySoft : ACC_COLORS.bg,
              border: active ? `1.5px solid ${ACC_COLORS.primary}` : `1.5px solid transparent`,
              cursor: 'pointer', fontSize: 12,
              color: active ? ACC_COLORS.primary : ACC_COLORS.textSecondary,
              fontWeight: active ? 500 : 400, transition: 'all 0.2s',
            }}>
            <span style={{ fontSize: 16 }}>{acc.icon}</span>
            <span>{acc.name}</span>
          </div>
        );
      })}
    </div>
  );
}

// ========== Add/Edit Bill Sheet ==========
function BillSheet({ show, onClose, bill, categories, accounts, onSubmit, isEdit }) {
  const [type, setType] = useState('expense');
  const [amount, setAmount] = useState('');
  const [category, setCategory] = useState('');
  const [note, setNote] = useState('');
  const [date, setDate] = useState(new Date().toISOString().split('T')[0]);
  const [account, setAccount] = useState('微信');

  useEffect(() => {
    if (show) {
      if (bill) {
        setType(bill.type); setAmount(String(bill.amount));
        setCategory(bill.category); setNote(bill.note || '');
        setDate(bill.bill_date); setAccount(bill.account || '微信');
      } else {
        setType('expense'); setAmount(''); setCategory(''); setNote('');
        setDate(new Date().toISOString().split('T')[0]); setAccount('微信');
      }
    }
  }, [show, bill]);

  const catsByType = useMemo(() => categories.filter(c => c.type === type), [categories, type]);
  useEffect(() => {
    if (show && catsByType.length > 0 && !catsByType.find(c => c.name === category)) {
      setCategory(catsByType[0].name);
    }
  }, [type, show, catsByType, category]);

  const handleSubmit = () => {
    if (!amount || parseFloat(amount) <= 0) return;
    if (!category) return;
    const selectedCat = catsByType.find(c => c.name === category);
    onSubmit({
      id: bill?.id, type, amount: parseFloat(amount), category,
      category_icon: selectedCat?.icon || '', note, bill_date: date, account,
    });
  };

  if (!show) return null;

  return (
    <div style={{
      position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.4)', zIndex: 1000,
      display: 'flex', alignItems: 'flex-end',
    }} onClick={onClose}>
      <div style={{
        width: '100%', maxHeight: '90vh', overflowY: 'auto',
        background: '#fff', borderRadius: '20px 20px 0 0',
        padding: '20px 16px 24px',
      }} onClick={e => e.stopPropagation()}>
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 16 }}>
          <div style={{ fontSize: 17, fontWeight: 600, color: ACC_COLORS.textPrimary }}>{isEdit ? '编辑账单' : '记一笔'}</div>
          <div onClick={onClose} style={{ fontSize: 20, color: ACC_COLORS.textTertiary, cursor: 'pointer', padding: 4 }}>✕</div>
        </div>

        {/* Type switch */}
        <div style={{ display: 'flex', background: ACC_COLORS.bg, borderRadius: 10, padding: 4, marginBottom: 16 }}>
          <div onClick={() => setType('expense')}
            style={{
              flex: 1, textAlign: 'center', padding: '8px 0', borderRadius: 8,
              fontSize: 14, fontWeight: 500, cursor: 'pointer', transition: 'all 0.2s',
              background: type === 'expense' ? '#fff' : 'transparent',
              color: type === 'expense' ? ACC_COLORS.expense : ACC_COLORS.textTertiary,
              boxShadow: type === 'expense' ? '0 2px 8px rgba(0,0,0,0.06)' : 'none',
            }}>支出</div>
          <div onClick={() => setType('income')}
            style={{
              flex: 1, textAlign: 'center', padding: '8px 0', borderRadius: 8,
              fontSize: 14, fontWeight: 500, cursor: 'pointer', transition: 'all 0.2s',
              background: type === 'income' ? '#fff' : 'transparent',
              color: type === 'income' ? ACC_COLORS.income : ACC_COLORS.textTertiary,
              boxShadow: type === 'income' ? '0 2px 8px rgba(0,0,0,0.06)' : 'none',
            }}>收入</div>
        </div>

        {/* Amount */}
        <div style={{ marginBottom: 16 }}>
          <div style={{ fontSize: 12, color: ACC_COLORS.textTertiary, marginBottom: 8 }}>金额</div>
          <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '16px 0', background: ACC_COLORS.bg, borderRadius: 12 }}>
            <span style={{ fontSize: 28, fontWeight: 600, color: type === 'expense' ? ACC_COLORS.expense : ACC_COLORS.income, marginRight: 4 }}>¥</span>
            <input type="number" placeholder="0.00" value={amount}
              onChange={e => setAmount(e.target.value)} autoFocus
              style={{
                fontSize: 32, fontWeight: 700,
                color: type === 'expense' ? ACC_COLORS.expense : ACC_COLORS.income,
                background: 'transparent', border: 'none', outline: 'none',
                width: 'auto', textAlign: 'center', minWidth: 120,
              }} />
          </div>
        </div>

        {/* Category */}
        <div style={{ marginBottom: 16 }}>
          <div style={{ fontSize: 12, color: ACC_COLORS.textTertiary, marginBottom: 10 }}>选择分类</div>
          <CategoryPicker categories={catsByType} value={category} onChange={setCategory} />
        </div>

        {/* Account */}
        <div style={{ marginBottom: 16 }}>
          <div style={{ fontSize: 12, color: ACC_COLORS.textTertiary, marginBottom: 10 }}>入账账户</div>
          <AccountPicker accounts={accounts} value={account} onChange={setAccount} />
        </div>

        {/* Date */}
        <div style={{ marginBottom: 16 }}>
          <div style={{ fontSize: 12, color: ACC_COLORS.textTertiary, marginBottom: 8 }}>消费时间</div>
          <input type="date" value={date} onChange={e => setDate(e.target.value)}
            style={{
              width: '100%', padding: '10px 14px', fontSize: 14,
              border: `1px solid ${ACC_COLORS.border}`, borderRadius: 10, outline: 'none',
              color: ACC_COLORS.textPrimary, boxSizing: 'border-box',
            }} />
        </div>

        {/* Note */}
        <div style={{ marginBottom: 20 }}>
          <div style={{ fontSize: 12, color: ACC_COLORS.textTertiary, marginBottom: 8 }}>备注（选填）</div>
          <input type="text" placeholder="添加备注..." value={note} onChange={e => setNote(e.target.value)}
            style={{
              width: '100%', padding: '10px 14px', fontSize: 14,
              border: `1px solid ${ACC_COLORS.border}`, borderRadius: 10, outline: 'none',
              color: ACC_COLORS.textPrimary, boxSizing: 'border-box',
            }} />
        </div>

        <button onClick={handleSubmit}
          style={{
            width: '100%', padding: '14px 0', fontSize: 15, fontWeight: 600, color: '#fff',
            background: `linear-gradient(135deg, ${type === 'expense' ? ACC_COLORS.expense : ACC_COLORS.primary}, ${type === 'expense' ? '#FF7875' : ACC_COLORS.primaryLight})`,
            border: 'none', borderRadius: 12, cursor: 'pointer',
          }}>
          {isEdit ? '保存修改' : '确认记账'}
        </button>
      </div>
    </div>
  );
}

// ========== Receivable Sheet ==========
function ReceivableSheet({ show, onClose, item, onSubmit, isEdit }) {
  const [type, setType] = useState('receivable');
  const [person, setPerson] = useState('');
  const [amount, setAmount] = useState('');
  const [date, setDate] = useState(new Date().toISOString().split('T')[0]);
  const [dueDate, setDueDate] = useState('');
  const [note, setNote] = useState('');

  useEffect(() => {
    if (show) {
      if (item) {
        setType(item.type); setPerson(item.person); setAmount(String(item.amount));
        setDate(item.date); setDueDate(item.due_date || ''); setNote(item.note || '');
      } else {
        setType('receivable'); setPerson(''); setAmount('');
        setDate(new Date().toISOString().split('T')[0]); setDueDate(''); setNote('');
      }
    }
  }, [show, item]);

  const typeOptions = [
    { key: 'receivable', label: '应收', desc: '别人欠我', color: ACC_COLORS.receivable, icon: '📥' },
    { key: 'payable', label: '应付', desc: '我欠别人', color: ACC_COLORS.payable, icon: '📤' },
    { key: 'lend', label: '借出', desc: '我借出的', color: ACC_COLORS.lend, icon: '💸' },
    { key: 'borrow', label: '借入', desc: '我借入的', color: ACC_COLORS.borrow, icon: '💰' },
  ];

  const activeType = typeOptions.find(t => t.key === type);

  const handleSubmit = () => {
    if (!amount || parseFloat(amount) <= 0) return;
    if (!person.trim()) return;
    onSubmit({
      id: item?.id, type, person: person.trim(),
      amount: parseFloat(amount), date, due_date: dueDate, note,
    });
  };

  if (!show) return null;

  return (
    <div style={{
      position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.4)', zIndex: 1000,
      display: 'flex', alignItems: 'flex-end',
    }} onClick={onClose}>
      <div style={{
        width: '100%', maxHeight: '90vh', overflowY: 'auto',
        background: '#fff', borderRadius: '20px 20px 0 0',
        padding: '20px 16px 24px',
      }} onClick={e => e.stopPropagation()}>
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 16 }}>
          <div style={{ fontSize: 17, fontWeight: 600, color: ACC_COLORS.textPrimary }}>{isEdit ? '编辑往来' : '新增往来'}</div>
          <div onClick={onClose} style={{ fontSize: 20, color: ACC_COLORS.textTertiary, cursor: 'pointer', padding: 4 }}>✕</div>
        </div>

        {/* Type grid */}
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 8, marginBottom: 16 }}>
          {typeOptions.map(opt => {
            const active = type === opt.key;
            return (
              <div key={opt.key} onClick={() => setType(opt.key)}
                style={{
                  display: 'flex', flexDirection: 'column', alignItems: 'center',
                  padding: '12px 4px', borderRadius: 12,
                  background: active ? `${opt.color}15` : ACC_COLORS.bg,
                  border: active ? `1.5px solid ${opt.color}` : '1.5px solid transparent',
                  cursor: 'pointer', transition: 'all 0.2s',
                }}>
                <div style={{ fontSize: 22, marginBottom: 4 }}>{opt.icon}</div>
                <div style={{ fontSize: 12, fontWeight: active ? 600 : 500, color: active ? opt.color : ACC_COLORS.textSecondary }}>
                  {opt.label}
                </div>
                <div style={{ fontSize: 10, color: ACC_COLORS.textTertiary, marginTop: 2 }}>{opt.desc}</div>
              </div>
            );
          })}
        </div>

        {/* Amount */}
        <div style={{ marginBottom: 16 }}>
          <div style={{ fontSize: 12, color: ACC_COLORS.textTertiary, marginBottom: 8 }}>金额</div>
          <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '16px 0', background: ACC_COLORS.bg, borderRadius: 12 }}>
            <span style={{ fontSize: 28, fontWeight: 600, color: activeType?.color, marginRight: 4 }}>¥</span>
            <input type="number" placeholder="0.00" value={amount}
              onChange={e => setAmount(e.target.value)} autoFocus
              style={{
                fontSize: 32, fontWeight: 700, color: activeType?.color,
                background: 'transparent', border: 'none', outline: 'none',
                width: 'auto', textAlign: 'center', minWidth: 120,
              }} />
          </div>
        </div>

        {/* Person */}
        <div style={{ marginBottom: 16 }}>
          <div style={{ fontSize: 12, color: ACC_COLORS.textTertiary, marginBottom: 8 }}>对方姓名</div>
          <input type="text" placeholder="请输入对方姓名" value={person} onChange={e => setPerson(e.target.value)}
            style={{
              width: '100%', padding: '12px 14px', fontSize: 14,
              border: `1px solid ${ACC_COLORS.border}`, borderRadius: 10, outline: 'none',
              color: ACC_COLORS.textPrimary, boxSizing: 'border-box',
            }} />
        </div>

        {/* Date */}
        <div style={{ display: 'flex', gap: 12, marginBottom: 16 }}>
          <div style={{ flex: 1 }}>
            <div style={{ fontSize: 12, color: ACC_COLORS.textTertiary, marginBottom: 8 }}>发生日期</div>
            <input type="date" value={date} onChange={e => setDate(e.target.value)}
              style={{
                width: '100%', padding: '10px 14px', fontSize: 13,
                border: `1px solid ${ACC_COLORS.border}`, borderRadius: 10, outline: 'none',
                boxSizing: 'border-box',
              }} />
          </div>
          <div style={{ flex: 1 }}>
            <div style={{ fontSize: 12, color: ACC_COLORS.textTertiary, marginBottom: 8 }}>预计还款</div>
            <input type="date" value={dueDate} onChange={e => setDueDate(e.target.value)}
              style={{
                width: '100%', padding: '10px 14px', fontSize: 13,
                border: `1px solid ${ACC_COLORS.border}`, borderRadius: 10, outline: 'none',
                boxSizing: 'border-box',
              }} />
          </div>
        </div>

        {/* Note */}
        <div style={{ marginBottom: 20 }}>
          <div style={{ fontSize: 12, color: ACC_COLORS.textTertiary, marginBottom: 8 }}>备注（选填）</div>
          <input type="text" placeholder="添加备注..." value={note} onChange={e => setNote(e.target.value)}
            style={{
              width: '100%', padding: '10px 14px', fontSize: 14,
              border: `1px solid ${ACC_COLORS.border}`, borderRadius: 10, outline: 'none',
              color: ACC_COLORS.textPrimary, boxSizing: 'border-box',
            }} />
        </div>

        <button onClick={handleSubmit}
          style={{
            width: '100%', padding: '14px 0', fontSize: 15, fontWeight: 600, color: '#fff',
            background: `linear-gradient(135deg, ${activeType?.color || ACC_COLORS.primary}, ${ACC_COLORS.primaryLight})`,
            border: 'none', borderRadius: 12, cursor: 'pointer',
          }}>
          {isEdit ? '保存修改' : '确认添加'}
        </button>
      </div>
    </div>
  );
}

// ========== Budget Modal ==========
function BudgetModal({ show, onClose, currentBudget, onSave }) {
  const [value, setValue] = useState('');
  useEffect(() => { if (show) setValue(String(currentBudget || '')); }, [show, currentBudget]);
  if (!show) return null;
  return (
    <div style={{
      position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.4)', zIndex: 1001,
      display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 32,
    }} onClick={onClose}>
      <div style={{ background: '#fff', borderRadius: 16, padding: 24, width: '100%', maxWidth: 320 }} onClick={e => e.stopPropagation()}>
        <div style={{ fontSize: 16, fontWeight: 600, marginBottom: 16 }}>设置每月预算</div>
        <input type="number" placeholder="请输入预算金额" value={value}
          onChange={e => setValue(e.target.value)} autoFocus
          style={{
            width: '100%', padding: '12px 14px', fontSize: 15,
            border: `1px solid ${ACC_COLORS.border}`, borderRadius: 10,
            outline: 'none', boxSizing: 'border-box', marginBottom: 20,
          }} />
        <div style={{ display: 'flex', gap: 10 }}>
          <button onClick={onClose} style={{
            flex: 1, padding: '10px 0', borderRadius: 10,
            border: `1px solid ${ACC_COLORS.border}`, background: '#fff',
            fontSize: 14, color: ACC_COLORS.textSecondary, cursor: 'pointer',
          }}>取消</button>
          <button onClick={() => { onSave(parseFloat(value) || 0); }} style={{
            flex: 1, padding: '10px 0', borderRadius: 10,
            border: 'none', background: ACC_COLORS.primary,
            fontSize: 14, color: '#fff', fontWeight: 500, cursor: 'pointer',
          }}>确定</button>
        </div>
      </div>
    </div>
  );
}

// ========== Bill Item ==========
function BillItem({ bill, onEdit, onDelete }) {
  const [translateX, setTranslateX] = useState(0);
  const [startX, setStartX] = useState(null);
  const [isDragging, setIsDragging] = useState(false);
  const handleTouchStart = e => { setStartX(e.touches[0].clientX); setIsDragging(true); };
  const handleTouchMove = e => {
    if (!isDragging || startX === null) return;
    setTranslateX(Math.max(-80, Math.min(0, e.touches[0].clientX - startX)));
  };
  const handleTouchEnd = () => {
    setIsDragging(false); setStartX(null);
    setTranslateX(translateX < -40 ? -80 : 0);
  };
  const isExpense = bill.type === 'expense';
  return (
    <div style={{ position: 'relative', overflow: 'hidden' }}>
      <div style={{
        position: 'absolute', right: 0, top: 0, bottom: 0, width: 80,
        background: ACC_COLORS.danger, display: 'flex', alignItems: 'center',
        justifyContent: 'center', color: '#fff', fontSize: 13, fontWeight: 500, cursor: 'pointer',
      }} onClick={onDelete}>删除</div>
      <div style={{
        display: 'flex', alignItems: 'center', padding: '12px 16px', background: '#fff',
        transform: `translateX(${translateX}px)`,
        transition: isDragging ? 'none' : 'transform 0.2s ease',
        cursor: 'pointer', borderBottom: `1px solid ${ACC_COLORS.border}`,
      }}
        onClick={onEdit}
        onTouchStart={handleTouchStart} onTouchMove={handleTouchMove} onTouchEnd={handleTouchEnd}>
        <div style={{
          width: 40, height: 40, borderRadius: 12, flexShrink: 0,
          background: isExpense ? '#FFF1F0' : ACC_COLORS.primarySoft,
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          fontSize: 20, marginRight: 12,
        }}>{bill.category_icon || '📝'}</div>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ fontSize: 14, fontWeight: 500, color: ACC_COLORS.textPrimary }}>{bill.category}</div>
          <div style={{ fontSize: 11, color: ACC_COLORS.textTertiary, marginTop: 2 }}>
            {bill.note || '无备注'} · {bill.account || '微信'}
          </div>
        </div>
        <div style={{
          fontSize: 16, fontWeight: 600,
          color: isExpense ? ACC_COLORS.expense : ACC_COLORS.income,
        }}>{isExpense ? '-' : '+'}¥{fmt(bill.amount)}</div>
      </div>
    </div>
  );
}

// ========== Receivable Item ==========
function ReceivableItem({ item, onSettle, onEdit, onDelete }) {
  const isMyInflow = item.type === 'receivable' || item.type === 'lend';
  const typeMap = {
    receivable: { label: '应收', icon: '📥', color: ACC_COLORS.receivable },
    payable: { label: '应付', icon: '📤', color: ACC_COLORS.payable },
    lend: { label: '借出', icon: '💸', color: ACC_COLORS.lend },
    borrow: { label: '借入', icon: '💰', color: ACC_COLORS.borrow },
  };
  const t = typeMap[item.type] || typeMap.receivable;
  const days = daysUntil(item.due_date);
  const isOverdue = item.status === 'pending' && days !== null && days < 0;
  const isSettled = item.status === 'settled';

  return (
    <div style={{
      background: '#fff', borderRadius: 12, padding: '14px 16px', marginBottom: 10,
      boxShadow: '0 2px 8px rgba(0,0,0,0.03)',
      opacity: isSettled ? 0.6 : 1,
    }}>
      <div style={{ display: 'flex', alignItems: 'center', marginBottom: 10 }}>
        <div style={{
          width: 38, height: 38, borderRadius: 10, flexShrink: 0,
          background: `${t.color}15`,
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          fontSize: 18, marginRight: 12,
        }}>{t.icon}</div>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
            <span style={{ fontSize: 15, fontWeight: 600, color: ACC_COLORS.textPrimary }}>{item.person}</span>
            <span style={{
              fontSize: 10, padding: '2px 6px', borderRadius: 4,
              background: `${t.color}15`, color: t.color, fontWeight: 500,
            }}>{t.label}</span>
            {isSettled && (
              <span style={{
                fontSize: 10, padding: '2px 6px', borderRadius: 4,
                background: ACC_COLORS.border, color: ACC_COLORS.textTertiary,
              }}>已结清</span>
            )}
          </div>
          <div style={{ fontSize: 11, color: ACC_COLORS.textTertiary, marginTop: 2 }}>
            {fmtDate(item.date)} {item.note ? `· ${item.note}` : ''}
          </div>
        </div>
        <div style={{
          fontSize: 17, fontWeight: 700,
          color: isMyInflow ? ACC_COLORS.receivable : ACC_COLORS.payable,
        }}>
          {isMyInflow ? '+' : '-'}¥{fmt(item.amount)}
        </div>
      </div>

      {/* Bottom row: due date + action buttons */}
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
        <div style={{ fontSize: 11, color: ACC_COLORS.textTertiary }}>
          {item.due_date ? (
            isOverdue ? (
              <span style={{ color: ACC_COLORS.danger, fontWeight: 500 }}>
                已逾期 {Math.abs(days)} 天
              </span>
            ) : days === 0 ? (
              <span style={{ color: ACC_COLORS.warn, fontWeight: 500 }}>今天到期</span>
            ) : days <= 3 ? (
              <span style={{ color: ACC_COLORS.warn }}>
                还有 {days} 天到期
              </span>
            ) : (
              `预计 ${fmtDate(item.due_date)} 还款`
            )
          ) : '未设置还款日期'}
        </div>
        <div style={{ display: 'flex', gap: 8 }}>
          {!isSettled && (
            <button onClick={() => onSettle(item)}
              style={{
                padding: '5px 12px', fontSize: 12, borderRadius: 14,
                border: 'none', background: ACC_COLORS.primary,
                color: '#fff', fontWeight: 500, cursor: 'pointer',
              }}>标记已结清</button>
          )}
          <button onClick={() => onEdit(item)}
            style={{
              padding: '5px 12px', fontSize: 12, borderRadius: 14,
              border: `1px solid ${ACC_COLORS.border}`, background: '#fff',
              color: ACC_COLORS.textSecondary, cursor: 'pointer',
            }}>编辑</button>
          <button onClick={() => onDelete(item)}
            style={{
              padding: '5px 12px', fontSize: 12, borderRadius: 14,
              border: `1px solid #FFECEC`, background: '#FFF5F5',
              color: ACC_COLORS.danger, cursor: 'pointer',
            }}>删除</button>
        </div>
      </div>
    </div>
  );
}

// ========== Main Page ==========
function AccountingPage({ activeTab = 'bills', setActiveTab }) {
  const { navigate, showToast } = useApp();

  // Bill sheet state
  const [showBillSheet, setShowBillSheet] = useState(false);
  const [editingBill, setEditingBill] = useState(null);
  const [showBudgetModal, setShowBudgetModal] = useState(false);

  // Receivable state
  const [showReceivableSheet, setShowReceivableSheet] = useState(false);
  const [editingReceivable, setEditingReceivable] = useState(null);
  const [receivableFilter, setReceivableFilter] = useState('pending'); // pending / settled

  // Data state
  const [categories, setCategories] = useState([]);
  const [accounts, setAccounts] = useState([]);
  const [bills, setBills] = useState([]);
  const [billStats, setBillStats] = useState({ totalIncome: 0, totalExpense: 0, balance: 0 });
  const [statsData, setStatsData] = useState({ expenseByCat: [], dailyStats: [], lastMonth: {} });
  const [budget, setBudget] = useState(3000);
  const [loading, setLoading] = useState(true);

  const [receivables, setReceivables] = useState([]);
  const [receivableSummary, setReceivableSummary] = useState({
    totalReceivable: 0, totalPayable: 0, totalLend: 0, totalBorrow: 0, netAssets: 0, pendingCount: 0,
  });

  // Month selector
  const [currentMonth, setCurrentMonth] = useState(new Date().toISOString().slice(0, 7));

  // Chart refs
  const pieChartRef = useRef(null);
  const lineChartRef = useRef(null);
  const pieChartInstance = useRef(null);
  const lineChartInstance = useRef(null);

  // ===== Load data =====
  const loadBills = useCallback(async () => {
    setLoading(true);
    const res = await API.get('/bills', { month: currentMonth });
    if (res.success || res.data) {
      setBills(res.data.list || []);
      setBillStats({
        totalIncome: res.data.totalIncome || 0,
        totalExpense: res.data.totalExpense || 0,
        balance: res.data.balance || 0,
      });
    }
    setLoading(false);
  }, [currentMonth]);

  const loadStats = useCallback(async () => {
    const res = await API.get('/bills/stats', { month: currentMonth });
    if (res.success || res.data) setStatsData(res.data || { expenseByCat: [], dailyStats: [], lastMonth: {} });
  }, [currentMonth]);

  const loadAccounts = useCallback(async () => {
    const res = await API.get('/bill-accounts');
    if (res.data) setAccounts(res.data || []);
  }, []);

  const loadBudget = useCallback(async () => {
    const res = await API.get('/bill-budget');
    if (res.data) setBudget(res.data.amount || 3000);
  }, []);

  const loadReceivables = useCallback(async () => {
    const res = await API.get('/bill-receivables', { status: receivableFilter });
    if (res.data) setReceivables(res.data.list || []);
  }, [receivableFilter]);

  const loadReceivableSummary = useCallback(async () => {
    const res = await API.get('/bill-receivables/summary');
    if (res.data) setReceivableSummary(res.data || {});
  }, []);

  // Initial loads
  useEffect(() => {
    API.get('/bill-categories', { type: 'expense' }).then(res => {
      API.get('/bill-categories', { type: 'income' }).then(res2 => {
        setCategories([...(res.data || []), ...(res2.data || [])]);
      });
    });
    loadAccounts();
    loadBudget();
  }, []);

  useEffect(() => { loadBills(); }, [loadBills]);
  useEffect(() => { if (activeTab === 'stats') loadStats(); }, [activeTab, loadStats]);
  useEffect(() => {
    if (activeTab === 'receivables' || activeTab === 'stats') {
      loadReceivableSummary();
    }
  }, [activeTab, loadReceivableSummary]);
  useEffect(() => {
    if (activeTab === 'receivables') loadReceivables();
  }, [activeTab, loadReceivables]);

  // ===== Pie chart =====
  useEffect(() => {
    if (activeTab !== 'stats') return;
    if (!pieChartRef.current || typeof echarts === 'undefined') return;
    if (!pieChartInstance.current) pieChartInstance.current = echarts.init(pieChartRef.current);
    const chart = pieChartInstance.current;
    const pieColors = ['#00B578', '#4ECDC4', '#45B7D1', '#FFD93D', '#FF6B6B', '#A78BFA', '#FB923C', '#F472B6', '#60A5FA'];
    const pieData = (statsData.expenseByCat || []).map((item, idx) => ({
      value: item.total, name: item.category,
      itemStyle: { color: pieColors[idx % pieColors.length] },
    }));
    chart.setOption({
      tooltip: { trigger: 'item', formatter: '{b}: ¥{c} ({d}%)' },
      legend: { bottom: 0, itemWidth: 10, itemHeight: 10, textStyle: { fontSize: 11, color: ACC_COLORS.textSecondary }, type: 'scroll' },
      series: [{
        type: 'pie', radius: ['45%', '70%'], center: ['50%', '42%'],
        avoidLabelOverlap: true,
        itemStyle: { borderRadius: 6, borderColor: '#fff', borderWidth: 2 },
        label: { show: false }, labelLine: { show: false },
        data: pieData.length ? pieData : [{ value: 1, name: '暂无数据', itemStyle: { color: '#E5E6EB' } }],
      }],
    });
  }, [activeTab, statsData.expenseByCat]);

  // ===== Line chart =====
  useEffect(() => {
    if (activeTab !== 'stats') return;
    if (!lineChartRef.current || typeof echarts === 'undefined') return;
    if (!lineChartInstance.current) lineChartInstance.current = echarts.init(lineChartRef.current);
    const chart = lineChartInstance.current;
    const daily = statsData.dailyStats || [];
    const dates = daily.map(d => d.bill_date?.slice(5) || '');
    const expenses = daily.map(d => d.expense || 0);
    chart.setOption({
      tooltip: { trigger: 'axis', valueFormatter: v => '¥' + v, backgroundColor: '#fff', borderColor: ACC_COLORS.border, textStyle: { color: ACC_COLORS.textPrimary, fontSize: 12 } },
      grid: { left: 50, right: 16, top: 20, bottom: 30 },
      xAxis: {
        type: 'category', boundaryGap: false,
        data: dates.length ? dates : ['01', '05', '10', '15', '20', '25', '30'],
        axisLine: { lineStyle: { color: '#E5E6EB' } },
        axisLabel: { fontSize: 10, color: '#86909C' }, axisTick: { show: false },
      },
      yAxis: {
        type: 'value',
        splitLine: { lineStyle: { color: '#F2F3F5', type: 'dashed' } },
        axisLabel: { fontSize: 10, color: '#86909C', formatter: v => v >= 1000 ? (v / 1000).toFixed(1) + 'k' : v },
        axisLine: { show: false }, axisTick: { show: false },
      },
      series: [{
        name: '支出', type: 'line', smooth: true, symbol: 'circle', symbolSize: 6,
        data: expenses,
        lineStyle: { color: ACC_COLORS.primary, width: 2 },
        itemStyle: { color: ACC_COLORS.primary, borderWidth: 2, borderColor: '#fff' },
        areaStyle: {
          color: {
            type: 'linear', x: 0, y: 0, x2: 0, y2: 1,
            colorStops: [{ offset: 0, color: 'rgba(0,181,120,0.25)' }, { offset: 1, color: 'rgba(0,181,120,0.02)' }],
          },
        },
      }],
    });
  }, [activeTab, statsData.dailyStats]);

  // ===== Bill actions =====
  const handleSubmitBill = async (data) => {
    if (editingBill) {
      const res = await API.put('/bills', data);
      if (res.success) { showToast('修改成功'); setShowBillSheet(false); setEditingBill(null); loadBills(); if (activeTab === 'stats') loadStats(); }
      else showToast(res.message || '修改失败');
    } else {
      const res = await API.post('/bills', data);
      if (res.success || res.data) { showToast('记账成功'); setShowBillSheet(false); loadBills(); if (activeTab === 'stats') loadStats(); }
      else showToast(res.message || '记账失败');
    }
  };
  const handleDeleteBill = async (bill) => {
    if (!window.confirm('确定删除这笔记账吗？')) return;
    const res = await API.del('/bills', { id: bill.id });
    if (res.success) { showToast('删除成功'); loadBills(); if (activeTab === 'stats') loadStats(); }
  };
  const handleSaveBudget = async (amount) => {
    const res = await API.put('/bill-budget', { amount });
    if (res.success) { setBudget(amount); setShowBudgetModal(false); showToast('预算已更新'); }
  };

  // ===== Receivable actions =====
  const handleSubmitReceivable = async (data) => {
    if (editingReceivable) {
      const res = await API.put('/bill-receivables', data);
      if (res.success) {
        showToast('修改成功'); setShowReceivableSheet(false); setEditingReceivable(null);
        loadReceivables(); loadReceivableSummary();
      } else showToast(res.message || '修改失败');
    } else {
      const res = await API.post('/bill-receivables', data);
      if (res.success) {
        showToast('添加成功'); setShowReceivableSheet(false);
        loadReceivables(); loadReceivableSummary();
      } else showToast(res.message || '添加失败');
    }
  };
  const handleSettleReceivable = async (item) => {
    if (!window.confirm(`确定标记「${item.person}」的¥${fmt(item.amount)}为已结清吗？`)) return;
    const res = await API.put('/bill-receivables', { id: item.id, status: 'settled' });
    if (res.success) { showToast('已结清'); loadReceivables(); loadReceivableSummary(); }
  };
  const handleDeleteReceivable = async (item) => {
    if (!window.confirm('确定删除这笔往来记录吗？')) return;
    const res = await API.del('/bill-receivables', { id: item.id });
    if (res.success) { showToast('删除成功'); loadReceivables(); loadReceivableSummary(); }
  };

  // ===== Month nav =====
  const prevMonth = () => {
    const [y, m] = currentMonth.split('-').map(Number);
    setCurrentMonth(new Date(y, m - 2, 1).toISOString().slice(0, 7));
  };
  const nextMonth = () => {
    const [y, m] = currentMonth.split('-').map(Number);
    const d = new Date(y, m, 1);
    if (d > new Date()) return;
    setCurrentMonth(d.toISOString().slice(0, 7));
  };

  // ===== Grouped bills =====
  const groupedBills = useMemo(() => {
    const groups = {};
    bills.forEach(b => {
      if (!groups[b.bill_date]) groups[b.bill_date] = { bills: [], dayExpense: 0, dayIncome: 0 };
      groups[b.bill_date].bills.push(b);
      if (b.type === 'expense') groups[b.bill_date].dayExpense += b.amount;
      else groups[b.bill_date].dayIncome += b.amount;
    });
    return Object.entries(groups).sort((a, b) => b[0].localeCompare(a[0]));
  }, [bills]);

  const totalBalance = useMemo(() => accounts.reduce((s, a) => s + (a.balance || 0), 0), [accounts]);
  const monthLabel = `${currentMonth.split('-')[0]}年${parseInt(currentMonth.split('-')[1])}月`;

  // ============ RENDER BILLS ============
  const renderBills = () => (
    <div style={{ paddingBottom: 100 }}>
      <div style={{
        background: `linear-gradient(135deg, ${ACC_COLORS.primary} 0%, ${ACC_COLORS.primaryLight} 100%)`,
        margin: '12px 16px 16px', borderRadius: 16, padding: '18px 20px',
        color: '#fff', boxShadow: '0 8px 24px rgba(0,181,120,0.25)',
      }}>
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 14 }}>
          <div onClick={prevMonth} style={{ cursor: 'pointer', padding: '4px 8px', fontSize: 18 }}>‹</div>
          <div style={{ fontSize: 15, fontWeight: 600 }}>{monthLabel}</div>
          <div onClick={nextMonth} style={{ cursor: 'pointer', padding: '4px 8px', fontSize: 18, opacity: currentMonth === new Date().toISOString().slice(0, 7) ? 0.3 : 1 }}>›</div>
        </div>
        <div style={{ fontSize: 12, opacity: 0.85, marginBottom: 2 }}>本月结余</div>
        <div style={{ fontSize: 32, fontWeight: 700, marginBottom: 14, letterSpacing: 0.5 }}>¥{fmt(billStats.balance)}</div>
        <div style={{ display: 'flex', gap: 16, marginBottom: 14 }}>
          <div style={{ flex: 1 }}>
            <div style={{ fontSize: 11, opacity: 0.85 }}>收入</div>
            <div style={{ fontSize: 17, fontWeight: 600, marginTop: 2 }}>¥{fmt(billStats.totalIncome)}</div>
          </div>
          <div style={{ flex: 1 }}>
            <div style={{ fontSize: 11, opacity: 0.85 }}>支出</div>
            <div style={{ fontSize: 17, fontWeight: 600, marginTop: 2 }}>¥{fmt(billStats.totalExpense)}</div>
          </div>
        </div>
        <div onClick={() => setShowBudgetModal(true)} style={{ cursor: 'pointer' }}>
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 6 }}>
            <span style={{ fontSize: 11, opacity: 0.9 }}>本月预算</span>
            <span style={{ fontSize: 11, opacity: 0.9 }}>¥{fmt(billStats.totalExpense)} / ¥{fmt(budget)}</span>
          </div>
          <div style={{ height: 6, background: 'rgba(255,255,255,0.25)', borderRadius: 3, overflow: 'hidden' }}>
            <div style={{
              height: '100%', width: `${budget > 0 ? Math.min((billStats.totalExpense / budget) * 100, 100) : 0}%`,
              background: billStats.totalExpense > budget ? '#FF4757' : '#fff',
              borderRadius: 3, transition: 'width 0.5s',
            }}></div>
          </div>
        </div>
      </div>

      {loading ? (
        <div style={{ padding: 60, textAlign: 'center', color: ACC_COLORS.textTertiary, fontSize: 13 }}>加载中...</div>
      ) : bills.length === 0 ? (
        <div style={{ padding: '60px 20px', textAlign: 'center', color: ACC_COLORS.textTertiary }}>
          <div style={{ fontSize: 48, marginBottom: 12 }}>📝</div>
          <div style={{ fontSize: 14, marginBottom: 4 }}>暂无账单</div>
          <div style={{ fontSize: 12 }}>点击右下角 + 记一笔</div>
        </div>
      ) : groupedBills.map(([date, group]) => (
        <div key={date} style={{ marginBottom: 12 }}>
          <div style={{
            display: 'flex', alignItems: 'center', justifyContent: 'space-between',
            padding: '8px 20px', fontSize: 12, color: ACC_COLORS.textTertiary,
          }}>
            <span>{fmtDate(date)} · {date.slice(5)}</span>
            <span>支 ¥{fmt(group.dayExpense)}
              {group.dayIncome > 0 && <span style={{ marginLeft: 8 }}>收 ¥{fmt(group.dayIncome)}</span>}
            </span>
          </div>
          {group.bills.map(bill => (
            <BillItem key={bill.id} bill={bill}
              onEdit={() => { setEditingBill(bill); setShowBillSheet(true); }}
              onDelete={() => handleDeleteBill(bill)} />
          ))}
        </div>
      ))}

      {activeTab === 'bills' && (
        <div onClick={() => { setEditingBill(null); setShowBillSheet(true); }}
          style={{
            position: 'fixed', right: 20, bottom: 80,
            width: 56, height: 56, borderRadius: '50%',
            background: `linear-gradient(135deg, ${ACC_COLORS.primary}, ${ACC_COLORS.primaryLight})`,
            color: '#fff', fontSize: 28, display: 'flex', alignItems: 'center', justifyContent: 'center',
            boxShadow: '0 6px 20px rgba(0,181,120,0.4)', cursor: 'pointer', zIndex: 50,
          }}>+</div>
      )}
    </div>
  );

  // ============ RENDER RECEIVABLES ============
  const renderReceivables = () => (
    <div style={{ paddingBottom: 100 }}>
      {/* Summary cards */}
      <div style={{ padding: '12px 16px 4px' }}>
        <div style={{
          background: `linear-gradient(135deg, ${ACC_COLORS.primary} 0%, ${ACC_COLORS.primaryDark} 100%)`,
          borderRadius: 16, padding: '18px 20px', color: '#fff',
          boxShadow: '0 6px 20px rgba(0,181,120,0.2)', marginBottom: 12,
        }}>
          <div style={{ fontSize: 12, opacity: 0.85, marginBottom: 4 }}>往来净额（别人欠我 - 我欠别人）</div>
          <div style={{ fontSize: 28, fontWeight: 700, letterSpacing: 0.5 }}>
            {receivableSummary.netAssets >= 0 ? '+' : ''}¥{fmt(receivableSummary.netAssets)}
          </div>
          <div style={{ fontSize: 11, opacity: 0.75, marginTop: 6 }}>
            {receivableSummary.pendingCount || 0} 笔未结清
          </div>
        </div>

        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10, marginBottom: 12 }}>
          <div style={{
            background: '#fff', borderRadius: 12, padding: '14px 14px',
            boxShadow: '0 2px 8px rgba(0,0,0,0.03)',
            borderLeft: `3px solid ${ACC_COLORS.receivable}`,
          }}>
            <div style={{ fontSize: 11, color: ACC_COLORS.textTertiary, marginBottom: 4 }}>总应收（别人欠我）</div>
            <div style={{ fontSize: 18, fontWeight: 700, color: ACC_COLORS.receivable }}>
              ¥{fmt(receivableSummary.totalReceivable)}
            </div>
            <div style={{ fontSize: 10, color: ACC_COLORS.textTertiary, marginTop: 4 }}>
              应收 ¥{fmt(receivableSummary.totalReceivableOnly)} + 借出 ¥{fmt(receivableSummary.totalLend)}
            </div>
          </div>
          <div style={{
            background: '#fff', borderRadius: 12, padding: '14px 14px',
            boxShadow: '0 2px 8px rgba(0,0,0,0.03)',
            borderLeft: `3px solid ${ACC_COLORS.payable}`,
          }}>
            <div style={{ fontSize: 11, color: ACC_COLORS.textTertiary, marginBottom: 4 }}>总应付（我欠别人）</div>
            <div style={{ fontSize: 18, fontWeight: 700, color: ACC_COLORS.payable }}>
              ¥{fmt(receivableSummary.totalPayable)}
            </div>
            <div style={{ fontSize: 10, color: ACC_COLORS.textTertiary, marginTop: 4 }}>
              应付 ¥{fmt(receivableSummary.totalPayableOnly)} + 借入 ¥{fmt(receivableSummary.totalBorrow)}
            </div>
          </div>
        </div>
      </div>

      {/* Filter tabs */}
      <div style={{ padding: '8px 16px 4px', display: 'flex', gap: 10 }}>
        {[
          { key: 'pending', label: '未结清' },
          { key: 'settled', label: '已结清' },
        ].map(f => (
          <div key={f.key} onClick={() => setReceivableFilter(f.key)}
            style={{
              padding: '6px 16px', fontSize: 13, borderRadius: 16,
              background: receivableFilter === f.key ? ACC_COLORS.primary : '#fff',
              color: receivableFilter === f.key ? '#fff' : ACC_COLORS.textSecondary,
              fontWeight: receivableFilter === f.key ? 600 : 400,
              cursor: 'pointer', transition: 'all 0.2s',
              boxShadow: '0 1px 4px rgba(0,0,0,0.04)',
            }}>
            {f.label}
          </div>
        ))}
      </div>

      {/* List */}
      <div style={{ padding: '12px 16px' }}>
        {receivables.length === 0 ? (
          <div style={{ padding: '50px 20px', textAlign: 'center', color: ACC_COLORS.textTertiary }}>
            <div style={{ fontSize: 42, marginBottom: 12 }}>{receivableFilter === 'pending' ? '📋' : '✅'}</div>
            <div style={{ fontSize: 14, marginBottom: 4 }}>
              {receivableFilter === 'pending' ? '暂无未结清往来' : '暂无已结清记录'}
            </div>
            <div style={{ fontSize: 12 }}>
              {receivableFilter === 'pending' ? '点击右下角 + 添加' : '结清的往来会在这里归档'}
            </div>
          </div>
        ) : (
          receivables.map(item => (
            <ReceivableItem key={item.id} item={item}
              onSettle={handleSettleReceivable}
              onEdit={(it) => { setEditingReceivable(it); setShowReceivableSheet(true); }}
              onDelete={handleDeleteReceivable} />
          ))
        )}
      </div>

      {/* Floating + button */}
      <div onClick={() => { setEditingReceivable(null); setShowReceivableSheet(true); }}
        style={{
          position: 'fixed', right: 20, bottom: 80,
          width: 56, height: 56, borderRadius: '50%',
          background: `linear-gradient(135deg, ${ACC_COLORS.primary}, ${ACC_COLORS.primaryLight})`,
          color: '#fff', fontSize: 28, display: 'flex', alignItems: 'center', justifyContent: 'center',
          boxShadow: '0 6px 20px rgba(0,181,120,0.4)', cursor: 'pointer', zIndex: 50,
        }}>+</div>
    </div>
  );

  // ============ RENDER STATS ============
  const renderStats = () => {
    const last = statsData.lastMonth || {};
    const expenseChange = last.totalExpense > 0
      ? ((billStats.totalExpense - last.totalExpense) / last.totalExpense * 100).toFixed(1) : 0;
    const incomeChange = last.totalIncome > 0
      ? ((billStats.totalIncome - last.totalIncome) / last.totalIncome * 100).toFixed(1) : 0;

    return (
      <div style={{ padding: '12px 16px 100px' }}>
        {/* Month selector */}
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', marginBottom: 12, gap: 24 }}>
          <div onClick={prevMonth} style={{ cursor: 'pointer', padding: '4px 12px', fontSize: 18, color: ACC_COLORS.textSecondary }}>‹</div>
          <div style={{ fontSize: 16, fontWeight: 600, color: ACC_COLORS.textPrimary }}>{monthLabel}</div>
          <div onClick={nextMonth} style={{
            cursor: 'pointer', padding: '4px 12px', fontSize: 18,
            color: currentMonth === new Date().toISOString().slice(0, 7) ? '#ccc' : ACC_COLORS.textSecondary,
          }}>›</div>
        </div>

        {/* Summary cards */}
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 10, marginBottom: 16 }}>
          <div style={{ background: '#fff', borderRadius: 12, padding: '14px 12px', boxShadow: '0 2px 12px rgba(0,0,0,0.04)' }}>
            <div style={{ fontSize: 11, color: ACC_COLORS.textTertiary, marginBottom: 4 }}>总支出</div>
            <div style={{ fontSize: 17, fontWeight: 700, color: ACC_COLORS.expense }}>¥{fmt(billStats.totalExpense)}</div>
            <div style={{ fontSize: 10, color: expenseChange > 0 ? ACC_COLORS.danger : ACC_COLORS.primary, marginTop: 4 }}>
              较上月 {expenseChange > 0 ? '↑' : '↓'} {Math.abs(expenseChange)}%
            </div>
          </div>
          <div style={{ background: '#fff', borderRadius: 12, padding: '14px 12px', boxShadow: '0 2px 12px rgba(0,0,0,0.04)' }}>
            <div style={{ fontSize: 11, color: ACC_COLORS.textTertiary, marginBottom: 4 }}>总收入</div>
            <div style={{ fontSize: 17, fontWeight: 700, color: ACC_COLORS.income }}>¥{fmt(billStats.totalIncome)}</div>
            <div style={{ fontSize: 10, color: incomeChange > 0 ? ACC_COLORS.primary : ACC_COLORS.danger, marginTop: 4 }}>
              较上月 {incomeChange > 0 ? '↑' : '↓'} {Math.abs(incomeChange)}%
            </div>
          </div>
          <div style={{ background: '#fff', borderRadius: 12, padding: '14px 12px', boxShadow: '0 2px 12px rgba(0,0,0,0.04)' }}>
            <div style={{ fontSize: 11, color: ACC_COLORS.textTertiary, marginBottom: 4 }}>结余</div>
            <div style={{ fontSize: 17, fontWeight: 700, color: billStats.balance >= 0 ? ACC_COLORS.primary : ACC_COLORS.danger }}>¥{fmt(billStats.balance)}</div>
            <div style={{ fontSize: 10, color: ACC_COLORS.textTertiary, marginTop: 4 }}>本月</div>
          </div>
        </div>

        {/* Pie chart */}
        <div style={{
          background: '#fff', borderRadius: 16, padding: '16px 16px 8px',
          boxShadow: '0 2px 12px rgba(0,0,0,0.04)', marginBottom: 12,
        }}>
          <div style={{ fontSize: 14, fontWeight: 600, color: ACC_COLORS.textPrimary, marginBottom: 4 }}>支出分类占比</div>
          <div ref={pieChartRef} style={{ width: '100%', height: 260 }}></div>
        </div>

        {/* Line chart */}
        <div style={{
          background: '#fff', borderRadius: 16, padding: '16px 16px 8px',
          boxShadow: '0 2px 12px rgba(0,0,0,0.04)', marginBottom: 12,
        }}>
          <div style={{ fontSize: 14, fontWeight: 600, color: ACC_COLORS.textPrimary, marginBottom: 4 }}>每日支出趋势</div>
          <div ref={lineChartRef} style={{ width: '100%', height: 200 }}></div>
        </div>

        {/* Category ranking */}
        <div style={{
          background: '#fff', borderRadius: 16, padding: 16,
          boxShadow: '0 2px 12px rgba(0,0,0,0.04)', marginBottom: 12,
        }}>
          <div style={{ fontSize: 14, fontWeight: 600, color: ACC_COLORS.textPrimary, marginBottom: 14 }}>支出排行榜</div>
          {(statsData.expenseByCat || []).map((item, idx) => {
            const max = statsData.expenseByCat[0]?.total || 1;
            const pct = (item.total / max * 100).toFixed(0);
            return (
              <div key={idx} style={{ marginBottom: idx < (statsData.expenseByCat?.length - 1) ? 12 : 0 }}>
                <div style={{ display: 'flex', alignItems: 'center', marginBottom: 6 }}>
                  <span style={{ width: 20, fontSize: 11, fontWeight: 600, color: idx < 3 ? ACC_COLORS.primary : ACC_COLORS.textTertiary }}>{idx + 1}</span>
                  <span style={{ fontSize: 18, marginRight: 8 }}>{item.category_icon || '📝'}</span>
                  <span style={{ fontSize: 13, flex: 1, color: ACC_COLORS.textPrimary }}>{item.category}</span>
                  <span style={{ fontSize: 13, fontWeight: 600, color: ACC_COLORS.textPrimary }}>¥{fmt(item.total)}</span>
                </div>
                <div style={{ height: 6, marginLeft: 28, background: ACC_COLORS.border, borderRadius: 3, overflow: 'hidden' }}>
                  <div style={{
                    height: '100%', width: `${pct}%`,
                    background: `linear-gradient(90deg, ${ACC_COLORS.primary}, ${ACC_COLORS.primaryLight})`,
                    borderRadius: 3, transition: 'width 0.5s',
                  }}></div>
                </div>
              </div>
            );
          })}
          {(!statsData.expenseByCat || statsData.expenseByCat.length === 0) && (
            <div style={{ textAlign: 'center', color: ACC_COLORS.textTertiary, fontSize: 12, padding: '30px 0' }}>本月暂无支出</div>
          )}
        </div>

        {/* Receivables summary on stats page */}
        <div style={{
          background: '#fff', borderRadius: 16, padding: 16,
          boxShadow: '0 2px 12px rgba(0,0,0,0.04)',
        }}>
          <div style={{ fontSize: 14, fontWeight: 600, color: ACC_COLORS.textPrimary, marginBottom: 12 }}>
            往来账款（未结清）
          </div>
          <div style={{
            display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10, marginBottom: 12,
          }}>
            <div style={{
              padding: '12px 14px', borderRadius: 10,
              background: `${ACC_COLORS.receivable}10`,
              border: `1px solid ${ACC_COLORS.receivable}25`,
            }}>
              <div style={{ fontSize: 11, color: ACC_COLORS.textSecondary, marginBottom: 4 }}>总应收</div>
              <div style={{ fontSize: 18, fontWeight: 700, color: ACC_COLORS.receivable }}>
                +¥{fmt(receivableSummary.totalReceivable)}
              </div>
            </div>
            <div style={{
              padding: '12px 14px', borderRadius: 10,
              background: `${ACC_COLORS.payable}10`,
              border: `1px solid ${ACC_COLORS.payable}25`,
            }}>
              <div style={{ fontSize: 11, color: ACC_COLORS.textSecondary, marginBottom: 4 }}>总应付</div>
              <div style={{ fontSize: 18, fontWeight: 700, color: ACC_COLORS.payable }}>
                -¥{fmt(receivableSummary.totalPayable)}
              </div>
            </div>
          </div>
          <div style={{
            display: 'flex', justifyContent: 'space-between', alignItems: 'center',
            padding: '10px 14px', background: ACC_COLORS.bg, borderRadius: 10,
          }}>
            <div style={{ fontSize: 12, color: ACC_COLORS.textSecondary }}>往来净额</div>
            <div style={{ fontSize: 15, fontWeight: 600, color: (receivableSummary.netAssets || 0) >= 0 ? ACC_COLORS.primary : ACC_COLORS.danger }}>
              {(receivableSummary.netAssets || 0) >= 0 ? '+' : ''}¥{fmt(receivableSummary.netAssets)}
            </div>
          </div>
          <div style={{ marginTop: 10, fontSize: 11, color: ACC_COLORS.textTertiary, lineHeight: 1.5 }}>
            💡 应收/借出不计入当月收入，应付/借入不计入当月支出。<br/>
            实际收到/还款时再记一笔收支。
          </div>
        </div>
      </div>
    );
  };

  // ============ RENDER ACCOUNTS ============
  const renderAccounts = () => {
    const netWorth = totalBalance + (receivableSummary.netAssets || 0);
    return (
      <div style={{ padding: '12px 16px 100px' }}>
        <div style={{
          background: `linear-gradient(135deg, ${ACC_COLORS.primary} 0%, ${ACC_COLORS.primaryDark} 100%)`,
          borderRadius: 16, padding: '20px 24px',
          color: '#fff', marginBottom: 16,
          boxShadow: '0 8px 24px rgba(0,181,120,0.25)',
        }}>
          <div style={{ fontSize: 12, opacity: 0.85, marginBottom: 6 }}>账户总资产</div>
          <div style={{ fontSize: 32, fontWeight: 700, letterSpacing: 0.5 }}>¥{fmt(totalBalance)}</div>
          <div style={{
            marginTop: 12, paddingTop: 12,
            borderTop: '1px solid rgba(255,255,255,0.2)',
            display: 'flex', justifyContent: 'space-between',
          }}>
            <div>
              <div style={{ fontSize: 11, opacity: 0.85 }}>含往来净额</div>
              <div style={{ fontSize: 15, fontWeight: 600, marginTop: 2 }}>
                ¥{fmt(netWorth)}
              </div>
            </div>
            <div style={{ textAlign: 'right' }}>
              <div style={{ fontSize: 11, opacity: 0.85 }}>账户数</div>
              <div style={{ fontSize: 15, fontWeight: 600, marginTop: 2 }}>{accounts.length} 个</div>
            </div>
          </div>
        </div>

        <div style={{
          background: '#fff', borderRadius: 16, overflow: 'hidden',
          boxShadow: '0 2px 12px rgba(0,0,0,0.04)',
        }}>
          {accounts.map((acc, idx) => (
            <div key={acc.id} style={{
              display: 'flex', alignItems: 'center',
              padding: '16px 20px',
              borderBottom: idx < accounts.length - 1 ? `1px solid ${ACC_COLORS.border}` : 'none',
            }}>
              <div style={{
                width: 44, height: 44, borderRadius: 12,
                background: ACC_COLORS.primarySoft,
                display: 'flex', alignItems: 'center', justifyContent: 'center',
                fontSize: 22, marginRight: 14,
              }}>{acc.icon}</div>
              <div style={{ flex: 1 }}>
                <div style={{ fontSize: 15, fontWeight: 500, color: ACC_COLORS.textPrimary }}>{acc.name}</div>
                <div style={{ fontSize: 11, color: ACC_COLORS.textTertiary, marginTop: 2 }}>余额</div>
              </div>
              <div style={{ fontSize: 17, fontWeight: 600, color: ACC_COLORS.textPrimary }}>¥{fmt(acc.balance)}</div>
            </div>
          ))}
        </div>

        <div style={{ marginTop: 16, textAlign: 'center', fontSize: 11, color: ACC_COLORS.textTertiary }}>
          账户余额仅供参考，实际金额以各平台为准
        </div>
      </div>
    );
  };

  // ============ MAIN RETURN ============
  return (
    <PageWrapper>
      <div style={{ background: ACC_COLORS.bg, minHeight: '100%' }}>
        <AppHeader
          title="久账"
          subtitle={<span style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}>
            个人记账
            <span style={{
              display: 'inline-block', padding: '1px 6px',
              fontSize: 10, fontWeight: 600,
              background: '#FFECEC', color: '#F53F3F',
              borderRadius: 4, letterSpacing: 0.5,
            }}>v4往来版</span>
          </span>}
          showBack
          onBack={() => navigate('home')}
        />

        {activeTab === 'bills' && renderBills()}
        {activeTab === 'receivables' && renderReceivables()}
        {activeTab === 'stats' && renderStats()}
        {activeTab === 'accounts' && renderAccounts()}

        {/* Bottom tab bar — handled by global BottomNav (NAV_CONFIGS.accounting) */}

        {/* Bill Sheet */}
        <BillSheet
          show={showBillSheet}
          onClose={() => { setShowBillSheet(false); setEditingBill(null); }}
          bill={editingBill} categories={categories} accounts={accounts}
          onSubmit={handleSubmitBill} isEdit={!!editingBill}
        />

        {/* Receivable Sheet */}
        <ReceivableSheet
          show={showReceivableSheet}
          onClose={() => { setShowReceivableSheet(false); setEditingReceivable(null); }}
          item={editingReceivable}
          onSubmit={handleSubmitReceivable} isEdit={!!editingReceivable}
        />

        {/* Budget Modal */}
        <BudgetModal
          show={showBudgetModal} onClose={() => setShowBudgetModal(false)}
          currentBudget={budget} onSave={handleSaveBudget}
        />
      </div>
    </PageWrapper>
  );
}

Object.assign(window, { AccountingPage });
