// Finance — چرتکه. Personal financial events tracker.

const FIN_CATS = {
  salary:    { label: 'حقوق',     icon: 'Briefcase', color: '#16A34A', bg: '#DCFCE7' },
  freelance: { label: 'فریلنس',  icon: 'TrendUp',   color: '#2A9D8F', bg: '#DDF3F0' },
  rent:      { label: 'کرایه',   icon: 'Home',      color: '#DC2626', bg: '#FEE2E2' },
  loan:      { label: 'قسط وام', icon: 'Wallet',    color: '#7C3AED', bg: '#EDE9FE' },
  utilities: { label: 'قبوض',    icon: 'Bolt',      color: '#D97706', bg: '#FEF3C7' },
  food:      { label: 'خوراک',   icon: 'Heart',     color: '#DB2777', bg: '#FCE7F3' },
  shop:      { label: 'خرید',    icon: 'Tag',       color: '#0284C7', bg: '#E0F2FE' },
  other:     { label: 'سایر',    icon: 'Hash',      color: '#64748B', bg: '#F1F5F9' },
};

const _finToday = () => {
  const d = new Date();
  return [d.getFullYear(), String(d.getMonth()+1).padStart(2,'0'), String(d.getDate()).padStart(2,'0')].join('-');
};

const _parseMoney = s =>
  Number(String(s).replace(/[,،٬]/g, '').replace(/[۰-۹]/g, d => '۰۱۲۳۴۵۶۷۸۹'.indexOf(d)));

const _fmtMoney = n => {
  const s = String(Math.round(Math.abs(n))).replace(/\B(?=(\d{3})+(?!\d))/g, ',');
  return s.replace(/\d/g, d => '۰۱۲۳۴۵۶۷۸۹'[d]);
};

const _faDt = iso =>
  new Intl.DateTimeFormat('fa-IR', { day: 'numeric', month: 'long' }).format(new Date(iso + 'T12:00:00'));

const _faMonth = () =>
  new Intl.DateTimeFormat('fa-IR', { month: 'long', year: 'numeric' }).format(new Date());

const _toFaF = n => String(n).replace(/\d/g, d => '۰۱۲۳۴۵۶۷۸۹'[d]);

const finStyles = {
  wrap: { height: '100%', overflow: 'auto', direction: 'rtl' },

  summary: {
    margin: '0 0 16px',
    background: 'var(--ink)', color: 'var(--paper)',
    borderRadius: 22, padding: '20px 20px 18px',
    position: 'relative', overflow: 'hidden',
    boxShadow: 'var(--shadow-float)',
  },
  summaryLabel: {
    font: "500 11px 'Estedad', sans-serif",
    letterSpacing: '0.06em', opacity: 0.55, marginBottom: 4, textTransform: 'uppercase',
  },
  summaryBalance: { font: "700 30px/1.2 'Estedad', sans-serif", marginBottom: 16 },
  summaryRow:  { display: 'flex', gap: 10 },
  summaryPill: {
    flex: 1, background: 'rgba(255,255,255,0.08)', borderRadius: 12,
    padding: '10px 12px', display: 'flex', flexDirection: 'column', gap: 3,
  },
  summaryPillLabel: { font: "400 11px 'Estedad', sans-serif", opacity: 0.55 },
  summaryPillVal:   { font: "700 15px 'Estedad', sans-serif" },

  segWrap: {
    display: 'flex', background: 'var(--paper-2)',
    borderRadius: 12, padding: 3, gap: 3, marginBottom: 16,
  },
  segBtn: {
    flex: 1, padding: '8px 12px', borderRadius: 9, border: 'none', cursor: 'pointer',
    font: "600 13px 'Estedad', sans-serif",
    background: 'transparent', color: 'var(--ink-3)', transition: 'all 140ms',
  },
  segBtnActive: {
    background: 'var(--surface)', color: 'var(--ink)',
    boxShadow: '0 1px 4px rgba(0,0,0,0.08)',
  },

  filterRow: { display: 'flex', gap: 6, marginBottom: 16 },
  chip: {
    flex: 'none', font: "500 12px 'Estedad', sans-serif",
    padding: '7px 14px', borderRadius: 999,
    background: 'var(--paper-2)', color: 'var(--ink-2)',
    border: '1px solid rgba(25,28,29,0.06)', cursor: 'pointer',
  },
  chipActive: { background: 'var(--ink)', color: 'var(--paper)', borderColor: 'transparent' },

  txCard: {
    background: 'var(--surface)', border: '1px solid rgba(25,28,29,0.06)',
    borderRadius: 16, padding: '14px 16px', marginBottom: 10,
    boxShadow: 'var(--shadow-lift)',
    display: 'flex', alignItems: 'center', gap: 12, cursor: 'pointer',
  },
  txIcon: { width: 40, height: 40, borderRadius: 12, display: 'grid', placeItems: 'center', flex: 'none' },
  txTitle: { font: "500 14px 'Estedad', sans-serif", color: 'var(--ink)' },
  txMeta:  { font: "400 12px 'Estedad', sans-serif", color: 'var(--ink-3)', marginTop: 2 },
  txAmount: { font: "700 15px/1 'Estedad', sans-serif", whiteSpace: 'nowrap' },

  empty: {
    textAlign: 'center', padding: '60px 16px',
    font: "400 14px 'Estedad', sans-serif", color: 'var(--ink-3)',
  },

  chartCard: {
    background: 'var(--surface)', border: '1px solid rgba(25,28,29,0.06)',
    borderRadius: 16, padding: '16px 16px 12px', marginBottom: 16,
    boxShadow: 'var(--shadow-lift)',
  },
  chartTitle: {
    display: 'flex', alignItems: 'center', justifyContent: 'space-between',
    marginBottom: 14, direction: 'rtl',
  },
  insightCard: {
    background: 'var(--firoozeh-soft)', border: '1px solid rgba(42,157,143,0.18)',
    borderRadius: 16, padding: '14px 16px', marginBottom: 16, direction: 'rtl',
  },
  insightItem: {
    display: 'flex', gap: 8, paddingTop: 8, marginTop: 8,
    borderTop: '1px solid rgba(42,157,143,0.10)', alignItems: 'flex-start',
  },
  insightDot: { width: 7, height: 7, borderRadius: '50%', flexShrink: 0, marginTop: 5 },

  // Add sheet
  overlay: {
    position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.45)',
    backdropFilter: 'blur(4px)', WebkitBackdropFilter: 'blur(4px)',
    zIndex: 200, display: 'flex', alignItems: 'flex-end', justifyContent: 'center',
    direction: 'rtl',
  },
  sheet: {
    width: '100%', maxWidth: 600,
    background: 'var(--paper)', borderRadius: '22px 22px 0 0',
    padding: '0 0 env(safe-area-inset-bottom)',
    boxShadow: '0 -8px 32px rgba(0,0,0,0.12)',
    maxHeight: '93vh', display: 'flex', flexDirection: 'column',
  },
  sheetHandle: { width: 36, height: 4, borderRadius: 99, background: 'rgba(25,28,29,0.15)', margin: '12px auto 0' },
  sheetHeader: {
    display: 'flex', alignItems: 'center', justifyContent: 'space-between',
    padding: '14px 20px 12px', borderBottom: '1px solid rgba(25,28,29,0.06)',
  },
  sheetTitle: { font: "600 17px 'Estedad', sans-serif", color: 'var(--ink)' },
  sheetClose: {
    width: 32, height: 32, borderRadius: 999, border: 'none', cursor: 'pointer',
    background: 'var(--paper-2)', color: 'var(--ink-2)', display: 'grid', placeItems: 'center',
  },
  sheetBody: { flex: 1, overflow: 'auto', padding: '20px 20px 32px' },

  typeToggle: {
    display: 'flex', background: 'var(--paper-2)',
    borderRadius: 14, padding: 4, gap: 4, marginBottom: 20,
  },
  typeBtn: {
    flex: 1, padding: '10px', borderRadius: 11, border: 'none', cursor: 'pointer',
    font: "600 14px 'Estedad', sans-serif",
    background: 'transparent', color: 'var(--ink-3)', transition: 'all 140ms',
  },

  fieldLabel: { font: "500 12px 'Estedad', sans-serif", color: 'var(--ink-3)', marginBottom: 8, letterSpacing: '0.02em' },
  amountWrap: {
    display: 'flex', alignItems: 'center', gap: 8,
    background: 'var(--surface)', border: '1px solid rgba(25,28,29,0.12)',
    borderRadius: 14, padding: '0 16px', marginBottom: 16,
  },
  amountInput: {
    flex: 1, padding: '14px 0', border: 'none', outline: 'none',
    background: 'transparent', color: 'var(--ink)',
    font: "600 22px 'Estedad', sans-serif", textAlign: 'center',
  },
  amountUnit: { font: "400 13px 'Estedad', sans-serif", color: 'var(--ink-3)', whiteSpace: 'nowrap' },
  titleInput: {
    width: '100%', padding: '12px 14px', borderRadius: 12,
    border: '1px solid rgba(25,28,29,0.12)',
    background: 'var(--surface)', color: 'var(--ink)',
    font: "400 15px 'Estedad', sans-serif", textAlign: 'right',
    outline: 'none', marginBottom: 16,
  },
  catGrid: { display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 8, marginBottom: 22 },
  catBtn: {
    display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 5,
    padding: '10px 4px', borderRadius: 12, border: '2px solid transparent',
    cursor: 'pointer', background: 'var(--paper-2)',
    font: "400 11px 'Estedad', sans-serif", color: 'var(--ink-2)', transition: 'all 100ms',
  },
  catIcon: { width: 32, height: 32, borderRadius: 9, display: 'grid', placeItems: 'center' },

  saveBtn: {
    width: '100%', padding: '15px', borderRadius: 999, border: 'none', cursor: 'pointer',
    background: 'var(--firoozeh)', color: '#fff',
    font: "600 16px 'Estedad', sans-serif",
  },
  saveBtnOff: { background: 'var(--ink-4)', cursor: 'not-allowed' },
};

// ── Recurring projection + cash-flow forecast ────────────────────
// Expand ONE recurring finance record into its future occurrences inside the
// inclusive ISO window [fromISO, toISO]. Stepping always moves forward first,
// so the original (real) record is never duplicated. Monthly/yearly steps use
// the Jalali calendar (consistent with task recurrence), clamping the day to
// the target month length.
function _finOccurrences(rec, fromISO, toISO) {
  if (!rec || !rec.recurrence || rec.recurrence === 'none') return [];
  const JU = window.JalaliUtils;
  if (!JU) return [];
  const { _toJalali, _toGregorian, _jDays, _toIso } = JU;
  const [gy, gm, gd] = rec.date.split('-').map(Number);
  let [jy, jm, jd] = _toJalali(gy, gm, gd);
  const out = [];
  let guard = 0;
  while (guard++ < 600) {
    if (rec.recurrence === 'yearly') {
      jy += 1;
    } else { // monthly
      jm += 1;
      if (jm > 12) { jm = 1; jy += 1; }
    }
    const day = Math.min(jd, _jDays(jy, jm));
    const [ngy, ngm, ngd] = _toGregorian(jy, jm, day);
    const iso = _toIso(ngy, ngm, ngd);
    if (iso > toISO) break;
    if (iso >= fromISO) out.push({ ...rec, date: iso, id: `${rec.id}~${iso}`, _virtual: true });
  }
  return out;
}

// Forward cash-flow forecast: N Jalali months starting NEXT month. Each row
// sums real future-dated records + projected recurring occurrences for that
// month, and carries a running cumulative balance (from today = 0).
function _buildForecast(finances, monthsAhead = 6) {
  const JU = window.JalaliUtils;
  if (!JU) return [];
  const { _toJalali, _toGregorian, _jDays, _toIso, J_MONTHS, _jn } = JU;
  const now = new Date();
  const [cjy, cjm] = _toJalali(now.getFullYear(), now.getMonth() + 1, now.getDate());

  const targets = [];
  for (let i = 1; i <= monthsAhead; i++) {
    let y = cjy, m = cjm + i;
    while (m > 12) { m -= 12; y += 1; }
    targets.push({ jy: y, jm: m });
  }
  const first = targets[0], last = targets[targets.length - 1];
  const [fgy, fgm, fgd] = _toGregorian(first.jy, first.jm, 1);
  const fromISO = _toIso(fgy, fgm, fgd);
  const [lgy, lgm, lgd] = _toGregorian(last.jy, last.jm, _jDays(last.jy, last.jm));
  const toISO = _toIso(lgy, lgm, lgd);

  const events = [];
  (finances || []).forEach(f => {
    if (f.date >= fromISO && f.date <= toISO) events.push(f);     // real future-dated
    _finOccurrences(f, fromISO, toISO).forEach(o => events.push(o)); // projected recurring
  });

  let cumulative = 0;
  return targets.map(({ jy, jm }) => {
    const [a, b, c] = _toGregorian(jy, jm, 1);
    const mStart = _toIso(a, b, c);
    const [d, e, f] = _toGregorian(jy, jm, _jDays(jy, jm));
    const mEnd = _toIso(d, e, f);
    let income = 0, expense = 0;
    events.forEach(ev => {
      if (ev.date >= mStart && ev.date <= mEnd) {
        if (ev.type === 'income') income += ev.amount;
        else expense += ev.amount;
      }
    });
    const net = income - expense;
    cumulative += net;
    return { jy, jm, label: J_MONTHS[jm - 1], yearLabel: _jn(jy), income, expense, net, cumulative };
  });
}

window._finForecast = _buildForecast;

// ── SVG bar chart: 6-month income vs expense ─────────────────────
function MonthlyBars({ finances }) {
  const months = [];
  const now = new Date();
  for (let i = 5; i >= 0; i--) {
    const d = new Date(now.getFullYear(), now.getMonth() - i, 1);
    const key = [d.getFullYear(), String(d.getMonth()+1).padStart(2,'0')].join('-');
    const label = new Intl.DateTimeFormat('fa-IR', { month: 'short' }).format(d);
    months.push({ key, label, income: 0, expense: 0, isCurrent: i === 0 });
  }
  finances.forEach(f => {
    const mk = f.date.slice(0, 7);
    const m = months.find(m => m.key === mk);
    if (!m) return;
    if (f.type === 'income') m.income += f.amount;
    else m.expense += f.amount;
  });

  const maxVal = Math.max(...months.flatMap(m => [m.income, m.expense]), 1);
  const BH = 72, BW = 11, BG = 4, GG = 14, PL = 8;
  const GW = BW * 2 + BG;
  const totalW = PL * 2 + months.length * GW + (months.length - 1) * GG;

  return (
    <svg viewBox={`0 0 ${totalW} ${BH + 22}`} width="100%" style={{ display: 'block', direction: 'ltr' }}>
      {months.map((m, i) => {
        const x = PL + i * (GW + GG);
        const incH = m.income > 0 ? Math.max((m.income / maxVal) * BH, 4) : 2;
        const expH = m.expense > 0 ? Math.max((m.expense / maxVal) * BH, 4) : 2;
        const op = m.isCurrent ? 1 : 0.55;
        return (
          <g key={m.key}>
            <rect x={x}        y={BH - incH} width={BW} height={incH} rx={3} fill="#2A9D8F" fillOpacity={op} />
            <rect x={x+BW+BG}  y={BH - expH} width={BW} height={expH} rx={3} fill="#EF4444" fillOpacity={op} />
            <text
              x={x + GW / 2} y={BH + 16} textAnchor="middle"
              fontSize={9} fontFamily="Estedad, sans-serif"
              fill={m.isCurrent ? '#2A9D8F' : '#6D7A77'}
              fontWeight={m.isCurrent ? '600' : '400'}
            >{m.label}</text>
          </g>
        );
      })}
    </svg>
  );
}

// ── Shared insights: used by AnalyticsView and window._finInsights ──
function _buildFinInsights(finances) {
  const now = new Date();
  const monthISO     = [now.getFullYear(), String(now.getMonth()+1).padStart(2,'0'), '01'].join('-');
  const lastMonthD   = new Date(now.getFullYear(), now.getMonth() - 1, 1);
  const lastMonthISO = [lastMonthD.getFullYear(), String(lastMonthD.getMonth()+1).padStart(2,'0'), '01'].join('-');
  const thisExp  = finances.filter(f => f.type === 'expense' && f.date >= monthISO);
  const lastExp  = finances.filter(f => f.type === 'expense' && f.date >= lastMonthISO && f.date < monthISO);
  const thisTotal = thisExp.reduce((s,f) => s + f.amount, 0);
  const lastTotal = lastExp.reduce((s,f) => s + f.amount, 0);
  const out = [];
  if (lastTotal > 0 && thisTotal > 0) {
    const pct = Math.round(((thisTotal - lastTotal) / lastTotal) * 100);
    if (Math.abs(pct) > 5) out.push({
      text: pct > 0
        ? `این ماه ${_toFaF(Math.abs(pct))}٪ بیشتر از ماه قبل هزینه کردی`
        : `این ماه ${_toFaF(Math.abs(pct))}٪ کمتر از ماه قبل هزینه کردی`,
      color: pct > 0 ? '#DC2626' : '#16A34A',
    });
  }
  const bycat = {};
  thisExp.forEach(f => { bycat[f.cat] = (bycat[f.cat] || 0) + f.amount; });
  const topCat = Object.entries(bycat).sort((a,b) => b[1]-a[1])[0];
  if (topCat && thisExp.length >= 2) {
    const c = FIN_CATS[topCat[0]] || FIN_CATS.other;
    out.push({ text: `بیشترین هزینه‌ات این ماه برای ${c.label} بوده`, color: c.color });
  }
  const nearPay = finances.find(f => {
    const diff = (new Date(f.date + 'T12:00:00') - now) / 86400000;
    return diff >= 0 && diff <= 7 && ['loan','rent','utilities'].includes(f.cat);
  });
  if (nearPay) {
    const day = new Intl.DateTimeFormat('fa-IR', { weekday: 'long' }).format(new Date(nearPay.date + 'T12:00:00'));
    const c = FIN_CATS[nearPay.cat] || FIN_CATS.other;
    out.push({ text: `${day} ${c.label} داری — ${_fmtMoney(nearPay.amount)} تومان`, color: '#D97706' });
  }
  return out;
}

window._finInsights = (finances) => {
  if (!finances || finances.length === 0) return [];
  return _buildFinInsights(finances).slice(0, 2);
};

// ── Analytics view: chart + category breakdown + insights ─────────
function AnalyticsView({ finances }) {
  const now = new Date();
  const monthISO     = [now.getFullYear(), String(now.getMonth()+1).padStart(2,'0'), '01'].join('-');
  const lastMonthD   = new Date(now.getFullYear(), now.getMonth() - 1, 1);
  const lastMonthISO = [lastMonthD.getFullYear(), String(lastMonthD.getMonth()+1).padStart(2,'0'), '01'].join('-');

  const thisExp  = finances.filter(f => f.type === 'expense' && f.date >= monthISO);
  const lastExp  = finances.filter(f => f.type === 'expense' && f.date >= lastMonthISO && f.date < monthISO);

  // Expense breakdown for current month
  const bycat = {};
  thisExp.forEach(f => { bycat[f.cat] = (bycat[f.cat] || 0) + f.amount; });
  const catRows = Object.entries(bycat).sort((a,b) => b[1]-a[1]);
  const totalExp = thisExp.reduce((s,f) => s + f.amount, 0) || 1;

  // Income breakdown for current month
  const thisInc  = finances.filter(f => f.type === 'income' && f.date >= monthISO);
  const incBycat = {};
  thisInc.forEach(f => { incBycat[f.cat] = (incBycat[f.cat] || 0) + f.amount; });
  const incRows  = Object.entries(incBycat).sort((a,b) => b[1]-a[1]);
  const totalInc = thisInc.reduce((s,f) => s + f.amount, 0) || 1;

  const insights = _buildFinInsights(finances);

  if (finances.length === 0) return (
    <div style={{ textAlign: 'center', padding: '48px 16px', color: 'var(--ink-3)', font: "400 14px 'Estedad', sans-serif" }}>
      برای نمایش نمودار ابتدا رویدادهای مالی ثبت کن
    </div>
  );

  return (
    <div>
      {/* Monthly bar chart */}
      <div style={finStyles.chartCard}>
        <div style={finStyles.chartTitle}>
          <span style={{ font: "600 13px 'Estedad', sans-serif", color: 'var(--ink)' }}>۶ ماه گذشته</span>
          <div style={{ display: 'flex', gap: 10 }}>
            {[['#2A9D8F','درآمد'],['#EF4444','هزینه']].map(([col,lbl]) => (
              <span key={lbl} style={{ display: 'flex', alignItems: 'center', gap: 4, font: "400 11px 'Estedad', sans-serif", color: 'var(--ink-3)' }}>
                <span style={{ width: 8, height: 8, borderRadius: 2, background: col, display: 'inline-block' }} />
                {lbl}
              </span>
            ))}
          </div>
        </div>
        <MonthlyBars finances={finances} />
      </div>

      {/* Expense breakdown */}
      {catRows.length > 0 && (
        <div style={finStyles.chartCard}>
          <div style={{ font: "600 13px 'Estedad', sans-serif", color: 'var(--ink)', marginBottom: 14, direction: 'rtl' }}>هزینه‌های این ماه</div>
          {catRows.slice(0, 5).map(([cat, amount]) => {
            const c = FIN_CATS[cat] || FIN_CATS.other;
            const pct = Math.round((amount / totalExp) * 100);
            return (
              <div key={cat} style={{ marginBottom: 12, direction: 'rtl' }}>
                <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 5, alignItems: 'center' }}>
                  <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
                    <span style={{ width: 7, height: 7, borderRadius: '50%', background: c.color, display: 'inline-block', flexShrink: 0 }} />
                    <span style={{ font: "500 13px 'Estedad', sans-serif", color: 'var(--ink-2)' }}>{c.label}</span>
                    <span style={{ font: "400 11px 'Estedad', sans-serif", color: 'var(--ink-4)' }}>{_toFaF(pct)}٪</span>
                  </div>
                  <span style={{ font: "600 13px 'Estedad', sans-serif", color: 'var(--ink)' }}>{_fmtMoney(amount)}</span>
                </div>
                <div style={{ height: 5, borderRadius: 999, background: 'var(--paper-2)' }}>
                  <div style={{ height: '100%', borderRadius: 999, background: c.color, width: `${pct}%`, opacity: 0.78 }} />
                </div>
              </div>
            );
          })}
          {catRows.length > 5 && (
            <div style={{ font: "400 12px 'Estedad', sans-serif", color: 'var(--ink-3)', textAlign: 'center', marginTop: 4 }}>
              و {_toFaF(catRows.length - 5)} دسته دیگر
            </div>
          )}
        </div>
      )}

      {/* Income breakdown */}
      {incRows.length > 0 && (
        <div style={finStyles.chartCard}>
          <div style={{ font: "600 13px 'Estedad', sans-serif", color: 'var(--ink)', marginBottom: 14, direction: 'rtl' }}>درآمدهای این ماه</div>
          {incRows.slice(0, 5).map(([cat, amount]) => {
            const c = FIN_CATS[cat] || FIN_CATS.other;
            const pct = Math.round((amount / totalInc) * 100);
            return (
              <div key={cat} style={{ marginBottom: 12, direction: 'rtl' }}>
                <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 5, alignItems: 'center' }}>
                  <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
                    <span style={{ width: 7, height: 7, borderRadius: '50%', background: c.color, display: 'inline-block', flexShrink: 0 }} />
                    <span style={{ font: "500 13px 'Estedad', sans-serif", color: 'var(--ink-2)' }}>{c.label}</span>
                    <span style={{ font: "400 11px 'Estedad', sans-serif", color: 'var(--ink-4)' }}>{_toFaF(pct)}٪</span>
                  </div>
                  <span style={{ font: "600 13px 'Estedad', sans-serif", color: '#16A34A' }}>{_fmtMoney(amount)}</span>
                </div>
                <div style={{ height: 5, borderRadius: 999, background: 'var(--paper-2)' }}>
                  <div style={{ height: '100%', borderRadius: 999, background: c.color, width: `${pct}%`, opacity: 0.78 }} />
                </div>
              </div>
            );
          })}
          {incRows.length > 5 && (
            <div style={{ font: "400 12px 'Estedad', sans-serif", color: 'var(--ink-3)', textAlign: 'center', marginTop: 4 }}>
              و {_toFaF(incRows.length - 5)} دسته دیگر
            </div>
          )}
        </div>
      )}

      {/* Insights */}
      {insights.length > 0 && (
        <div style={finStyles.insightCard}>
          <div style={{ font: "600 13px 'Estedad', sans-serif", color: 'var(--firoozeh-deep)', marginBottom: 4 }}>بینش مالی</div>
          {insights.map((ins, idx) => (
            <div key={idx} style={{ ...finStyles.insightItem, ...(idx === 0 ? { borderTop: 'none', marginTop: 0, paddingTop: 4 } : {}) }}>
              <span style={{ ...finStyles.insightDot, background: ins.color }} />
              <span style={{ font: "400 13px/1.5 'Estedad', sans-serif", color: 'var(--firoozeh-deep)', opacity: 0.85 }}>{ins.text}</span>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

// ── Forecast: monthly-net bars + cumulative-balance line ──────────
function ForecastChart({ rows }) {
  if (!rows.length) return null;
  const W = 320, H = 124, PT = 14, PB = 24, PL = 12, PR = 12;
  const innerW = W - PL - PR, innerH = H - PT - PB;
  const vals = rows.flatMap(r => [r.net, r.cumulative]).concat([0]);
  const vMax = Math.max(...vals), vMin = Math.min(...vals);
  const span = (vMax - vMin) || 1;
  const y = v => PT + (1 - (v - vMin) / span) * innerH;
  const zeroY = y(0);
  const n = rows.length;
  const slot = innerW / n;
  const bw = Math.min(20, slot * 0.46);
  const cx = i => PL + slot * i + slot / 2;
  const linePts = rows.map((r, i) => `${cx(i)},${y(r.cumulative)}`).join(' ');
  return (
    <svg viewBox={`0 0 ${W} ${H}`} width="100%" style={{ display: 'block', direction: 'ltr' }}>
      <line x1={PL} y1={zeroY} x2={W - PR} y2={zeroY} stroke="rgba(0,0,0,0.12)" strokeWidth="1" strokeDasharray="3 3" />
      {rows.map((r, i) => {
        const top = Math.min(zeroY, y(r.net));
        const h = Math.max(2, Math.abs(zeroY - y(r.net)));
        return <rect key={'b'+i} x={cx(i) - bw / 2} y={top} width={bw} height={h} rx={3}
          fill={r.net >= 0 ? '#16A34A' : '#DC2626'} fillOpacity={0.85} />;
      })}
      <polyline points={linePts} fill="none" stroke="#2A9D8F" strokeWidth="2" strokeLinejoin="round" strokeLinecap="round" />
      {rows.map((r, i) => <circle key={'c'+i} cx={cx(i)} cy={y(r.cumulative)} r={2.6} fill="#2A9D8F" />)}
      {rows.map((r, i) => (
        <text key={'t'+i} x={cx(i)} y={H - 8} textAnchor="middle"
          fontSize={9} fontFamily="Estedad, sans-serif" fill="#6D7A77">{r.label}</text>
      ))}
    </svg>
  );
}

// ── Forecast view: 6-month cash-flow projection from recurring items ──
function ForecastView({ finances }) {
  const { Icons } = window;
  const rows = _buildForecast(finances, 6);
  const totalIncome  = rows.reduce((s, r) => s + r.income, 0);
  const totalExpense = rows.reduce((s, r) => s + r.expense, 0);
  const totalNet = totalIncome - totalExpense;
  const recurring = (finances || []).filter(f => f.recurrence && f.recurrence !== 'none');
  const hasData = rows.some(r => r.income || r.expense);

  if (!hasData) return (
    <div style={finStyles.chartCard}>
      <div style={{ font: "600 13px 'Estedad', sans-serif", color: 'var(--ink)', marginBottom: 8, direction: 'rtl' }}>پیش‌بینی جریان نقدی</div>
      <div style={{ textAlign: 'center', padding: '20px 12px', color: 'var(--ink-3)', font: "400 13px/1.8 'Estedad', sans-serif", direction: 'rtl' }}>
        برای پیش‌بینی ۶ ماه آینده، رویدادهای تکرارشونده ثبت کن.<br />
        هنگام افزودن یک درآمد یا هزینه (مثل حقوق یا کرایه)، گزینهٔ تکرار «ماهانه» یا «سالانه» را انتخاب کن.
      </div>
    </div>
  );

  return (
    <div>
      {/* Headline + chart */}
      <div style={finStyles.chartCard}>
        <div style={{ font: "600 13px 'Estedad', sans-serif", color: 'var(--ink)', marginBottom: 12, direction: 'rtl' }}>پیش‌بینی ۶ ماه آینده</div>
        <div style={{ direction: 'rtl', font: "400 13px/1.7 'Estedad', sans-serif", color: 'var(--ink-2)', marginBottom: 14 }}>
          با ادامهٔ روند فعلی، خالص جریان نقدی ۶ ماه آینده‌ات
          <span style={{ font: "700 14px 'Estedad', sans-serif", color: totalNet >= 0 ? '#16A34A' : '#DC2626' }}> {totalNet < 0 ? '−' : '+'}{_fmtMoney(totalNet)} تومان </span>
          خواهد بود.
        </div>
        <ForecastChart rows={rows} />
        <div style={{ display: 'flex', gap: 12, justifyContent: 'center', marginTop: 8 }}>
          {[['#16A34A', 'خالص ماه'], ['#2A9D8F', 'مانده تجمعی']].map(([col, lbl]) => (
            <span key={lbl} style={{ display: 'flex', alignItems: 'center', gap: 4, font: "400 11px 'Estedad', sans-serif", color: 'var(--ink-3)' }}>
              <span style={{ width: 8, height: 8, borderRadius: 2, background: col, display: 'inline-block' }} />
              {lbl}
            </span>
          ))}
        </div>
      </div>

      {/* Month-by-month */}
      <div style={finStyles.chartCard}>
        <div style={{ font: "600 13px 'Estedad', sans-serif", color: 'var(--ink)', marginBottom: 6, direction: 'rtl' }}>ماه‌به‌ماه</div>
        {rows.map((r, i) => (
          <div key={i} style={{ direction: 'rtl', display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '9px 0', borderTop: i ? '1px solid var(--c-border-xs)' : 'none' }}>
            <div style={{ minWidth: 0 }}>
              <div style={{ font: "600 13px 'Estedad', sans-serif", color: 'var(--ink)' }}>{r.label} {r.yearLabel}</div>
              <div style={{ font: "400 11px 'Estedad', sans-serif", color: 'var(--ink-3)', marginTop: 2 }}>
                درآمد {_fmtMoney(r.income)} · هزینه {_fmtMoney(r.expense)}
              </div>
            </div>
            <div style={{ textAlign: 'left', flexShrink: 0 }}>
              <div style={{ font: "700 13px 'Estedad', sans-serif", color: r.net >= 0 ? '#16A34A' : '#DC2626' }}>
                {r.net < 0 ? '−' : '+'}{_fmtMoney(r.net)}
              </div>
              <div style={{ font: "400 11px 'Estedad', sans-serif", color: 'var(--ink-4)', marginTop: 2 }}>
                مانده: {r.cumulative < 0 ? '−' : ''}{_fmtMoney(r.cumulative)}
              </div>
            </div>
          </div>
        ))}
      </div>

      {/* Recurring drivers */}
      {recurring.length > 0 && (
        <div style={finStyles.chartCard}>
          <div style={{ font: "600 13px 'Estedad', sans-serif", color: 'var(--ink)', marginBottom: 8, direction: 'rtl' }}>
            موارد تکرارشونده ({_toFaF(recurring.length)})
          </div>
          {recurring.map(f => {
            const c = FIN_CATS[f.cat] || FIN_CATS.other;
            const I = Icons[c.icon];
            const isIn = f.type === 'income';
            return (
              <div key={f.id} style={{ direction: 'rtl', display: 'flex', alignItems: 'center', gap: 10, padding: '7px 0' }}>
                <span style={{ width: 30, height: 30, borderRadius: 8, background: c.bg, color: c.color, display: 'grid', placeItems: 'center', flexShrink: 0 }}>
                  {I && <I size={15} />}
                </span>
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ font: "500 13px 'Estedad', sans-serif", color: 'var(--ink)' }}>{f.title}</div>
                  <div style={{ font: "400 11px 'Estedad', sans-serif", color: 'var(--firoozeh-deep)' }}>
                    {f.recurrence === 'monthly' ? '↻ ماهانه' : '↻ سالانه'}
                  </div>
                </div>
                <div style={{ font: "600 13px 'Estedad', sans-serif", color: isIn ? '#16A34A' : '#DC2626', flexShrink: 0 }}>
                  {isIn ? '+' : '−'}{_fmtMoney(f.amount)}
                </div>
              </div>
            );
          })}
        </div>
      )}

      <div style={{ font: "400 11px/1.7 'Estedad', sans-serif", color: 'var(--ink-4)', textAlign: 'center', direction: 'rtl', padding: '2px 12px 8px' }}>
        پیش‌بینی بر اساس موارد تکرارشونده و رویدادهای آیندهٔ ثبت‌شده محاسبه می‌شود.
      </div>
    </div>
  );
}

function AddFinanceSheet({ open, onClose, onAdd, initialData }) {
  const { Icons } = window;
  const isEdit = !!initialData;
  const [type,       setType]       = React.useState('expense');
  const [cat,        setCat]        = React.useState('other');
  const [title,      setTitle]      = React.useState('');
  const [amount,     setAmount]     = React.useState('');
  const [date,       setDate]       = React.useState(_finToday);
  const [recurrence, setRecurrence] = React.useState('none');
  const [showCal,    setShowCal]    = React.useState(false);

  React.useEffect(() => {
    if (!open) return;
    if (initialData) {
      setType(initialData.type || 'expense');
      setCat(initialData.cat || 'other');
      setTitle(initialData.title || '');
      setAmount(String(initialData.amount || ''));
      setDate(initialData.date || _finToday());
      setRecurrence(initialData.recurrence || 'none');
    } else {
      setType('expense'); setCat('other'); setTitle(''); setAmount(''); setDate(_finToday()); setRecurrence('none');
    }
    setShowCal(false);
  }, [open, initialData?.id]);

  const close = () => { onClose(); };

  const save = () => {
    const n = _parseMoney(amount);
    if (!n || !title.trim()) return;
    onAdd({ id: initialData?.id || 'fin-' + Date.now(), type, cat, title: title.trim(), amount: n, date, recurrence });
    close();
  };

  if (!open) return null;
  const canSave = title.trim() && _parseMoney(amount) > 0;

  return (
    <div style={finStyles.overlay} onClick={close}>
      <div style={finStyles.sheet} onClick={e => e.stopPropagation()}>
        <div style={finStyles.sheetHandle} />
        <div style={finStyles.sheetHeader}>
          <span style={finStyles.sheetTitle}>{isEdit ? 'ویرایش رویداد' : 'ورودی مالی جدید'}</span>
          <button style={finStyles.sheetClose} onClick={close}><Icons.X size={16} /></button>
        </div>
        <div style={finStyles.sheetBody}>

          {/* Income / Expense toggle */}
          <div style={finStyles.typeToggle}>
            {[['expense','هزینه','#DC2626','#FEE2E2'],['income','درآمد','#16A34A','#DCFCE7']].map(([t,l,c,bg]) => (
              <button key={t} style={{
                ...finStyles.typeBtn,
                ...(type === t ? { background: bg, color: c, boxShadow: '0 2px 8px rgba(0,0,0,0.10)' } : {}),
              }} onClick={() => setType(t)}>{l}</button>
            ))}
          </div>

          {/* Amount */}
          <div style={finStyles.fieldLabel}>مبلغ</div>
          <div style={finStyles.amountWrap}>
            <input
              style={finStyles.amountInput}
              type="text" inputMode="numeric" placeholder="۰"
              value={amount} onChange={e => setAmount(e.target.value)} dir="ltr"
            />
            <span style={finStyles.amountUnit}>تومان</span>
          </div>
          {amount && _parseMoney(amount) <= 0 && (
            <div style={{ font: "400 12px 'Estedad', sans-serif", color: '#DC2626', marginBottom: 8, textAlign: 'right', direction: 'rtl' }}>
              مبلغ باید بیشتر از صفر باشد
            </div>
          )}

          {/* Description */}
          <div style={finStyles.fieldLabel}>توضیح</div>
          <input
            style={finStyles.titleInput}
            placeholder="مثلاً: حقوق اردیبهشت ۱۴۰۴"
            value={title} onChange={e => setTitle(e.target.value)}
          />

          {/* Date */}
          <div style={finStyles.fieldLabel}>تاریخ</div>
          <button
            onClick={() => setShowCal(v => !v)}
            style={{
              width: '100%', textAlign: 'right', padding: '11px 14px', borderRadius: 12,
              border: `1px solid ${showCal ? 'var(--firoozeh)' : 'rgba(25,28,29,0.12)'}`,
              background: 'var(--surface)', color: 'var(--ink)',
              font: "400 14px 'Estedad', sans-serif",
              cursor: 'pointer', marginBottom: showCal ? 8 : 16, direction: 'rtl',
              display: 'flex', alignItems: 'center', justifyContent: 'space-between',
            }}
          >
            <span>{_faDt(date)}</span>
            <Icons.Calendar size={16} style={{ color: 'var(--ink-3)', flexShrink: 0 }} />
          </button>
          {showCal && (
            <div style={{ marginBottom: 16 }}>
              <window.PersianDatePicker value={date} onChange={v => { setDate(v); setShowCal(false); }} />
            </div>
          )}

          {/* Category */}
          <div style={finStyles.fieldLabel}>دسته‌بندی</div>
          <div style={finStyles.catGrid}>
            {Object.entries(FIN_CATS).map(([k, c]) => {
              const I = Icons[c.icon];
              const on = cat === k;
              return (
                <button key={k} style={{
                  ...finStyles.catBtn,
                  ...(on ? { background: c.bg, borderColor: c.color, color: c.color } : {}),
                }} onClick={() => setCat(k)}>
                  <div style={{ ...finStyles.catIcon, background: on ? c.bg : 'var(--paper-2)', color: on ? c.color : 'var(--ink-3)' }}>
                    {I && <I size={15} />}
                  </div>
                  {c.label}
                </button>
              );
            })}
          </div>

          {/* Recurrence */}
          <div style={finStyles.fieldLabel}>تکرار</div>
          <div style={{ display: 'flex', gap: 8, marginBottom: 22 }}>
            {[['none','بدون تکرار'],['monthly','ماهانه'],['yearly','سالانه']].map(([k, l]) => (
              <button key={k} style={{
                flex: 1, padding: '10px 6px', borderRadius: 12, cursor: 'pointer',
                font: "500 12px 'Estedad', sans-serif",
                border: `1px solid ${recurrence === k ? 'var(--firoozeh)' : 'var(--c-border-sm)'}`,
                background: recurrence === k ? 'var(--firoozeh-soft)' : 'var(--paper-2)',
                color: recurrence === k ? 'var(--firoozeh-deep)' : 'var(--ink-2)',
              }} onClick={() => setRecurrence(k)}>{l}</button>
            ))}
          </div>

          <button
            style={{ ...finStyles.saveBtn, ...(canSave ? {} : finStyles.saveBtnOff) }}
            onClick={canSave ? save : undefined}
          >{isEdit ? 'ذخیره تغییرات' : 'ثبت رویداد'}</button>
        </div>
      </div>
    </div>
  );
}

function Finance({ finances, isDesktop, addOpen, onAddClose, onAdd, onDelete, onUpdate, highlightId }) {
  const { Icons } = window;
  const [filter, setFilter] = React.useState('all');
  const [range, setRange]   = React.useState('month'); // PRD-003 date range
  const [seg, setSeg]       = React.useState('tx');
  const [editItem, setEditItem] = React.useState(null);

  React.useEffect(() => {
    if (!highlightId) return;
    setSeg('tx');
    setTimeout(() => {
      const el = document.getElementById('fin-item-' + highlightId);
      if (el) el.scrollIntoView({ behavior: 'smooth', block: 'center' });
    }, 80);
  }, [highlightId]);

  const now = new Date();
  const _ms = (d) => [d.getFullYear(), String(d.getMonth()+1).padStart(2,'0'), '01'].join('-');
  const RANGES = {
    all:       { label: 'همه تاریخ‌ها', from: '0000-00-00', to: '9999-99-99' },
    month:     { label: _faMonth(),     from: _ms(now), to: _ms(new Date(now.getFullYear(), now.getMonth()+1, 1)) },
    lastMonth: { label: 'ماه قبل',      from: _ms(new Date(now.getFullYear(), now.getMonth()-1, 1)), to: _ms(now) },
    '3m':      { label: '۳ ماه اخیر',   from: _ms(new Date(now.getFullYear(), now.getMonth()-2, 1)), to: _ms(new Date(now.getFullYear(), now.getMonth()+1, 1)) },
  };
  const R = RANGES[range] || RANGES.month;
  const inRange = f => f.date >= R.from && f.date < R.to;
  const rangeItems = finances.filter(inRange);
  const income  = rangeItems.filter(f => f.type === 'income').reduce((s, f)  => s + f.amount, 0);
  const expense = rangeItems.filter(f => f.type === 'expense').reduce((s, f) => s + f.amount, 0);
  const balance = income - expense;

  const filtered = finances.filter(f => inRange(f) && (filter === 'all' || f.type === filter))
    .sort((a, b) => b.date.localeCompare(a.date));

  const pad = isDesktop ? '0 24px 40px' : '0 16px 120px';

  return (
    <>
      <div className="sb-flow" style={{ ...finStyles.wrap, padding: pad }}>

        {/* Summary card — always visible */}
        <div className="sb-animated-card" style={finStyles.summary}>
          <div style={finStyles.summaryLabel}>{R.label}</div>
          <div style={{ ...finStyles.summaryBalance, color: balance >= 0 ? '#6EE7B7' : '#FCA5A5' }}>
            {balance < 0 ? '−' : '+'}{_fmtMoney(balance)} تومان
          </div>
          <div style={finStyles.summaryRow}>
            <div style={finStyles.summaryPill}>
              <span style={finStyles.summaryPillLabel}>درآمد</span>
              <span style={{ ...finStyles.summaryPillVal, color: '#6EE7B7' }}>{_fmtMoney(income)}</span>
            </div>
            <div style={finStyles.summaryPill}>
              <span style={finStyles.summaryPillLabel}>هزینه</span>
              <span style={{ ...finStyles.summaryPillVal, color: '#FCA5A5' }}>{_fmtMoney(expense)}</span>
            </div>
          </div>
        </div>

        {/* Segment toggle */}
        <div style={finStyles.segWrap}>
          {[['tx','رویدادها'],['chart','نمودار'],['forecast','پیش‌بینی']].map(([k,l]) => (
            <button key={k}
              style={{ ...finStyles.segBtn, ...(seg===k ? finStyles.segBtnActive : {}) }}
              onClick={() => setSeg(k)}
            >{l}</button>
          ))}
        </div>

        {seg === 'tx' ? (
          <>
            {/* Filter chips */}
            <div style={finStyles.filterRow}>
              {[['all','همه'],['income','درآمد'],['expense','هزینه']].map(([k,l]) => (
                <button key={k}
                  style={{ ...finStyles.chip, ...(filter===k ? finStyles.chipActive : {}) }}
                  onClick={() => setFilter(k)}
                >{l}</button>
              ))}
              <span style={{ flex:1 }} />
              <span style={{ font: "400 12px 'Estedad', sans-serif", color: 'var(--ink-3)', alignSelf: 'center' }}>
                {_toFaF(filtered.length)} ورودی
              </span>
            </div>

            {/* PRD-003: date-range chips */}
            <div style={{ ...finStyles.filterRow, overflowX: 'auto' }}>
              {[['all','همه تاریخ‌ها'],['month','این ماه'],['lastMonth','ماه قبل'],['3m','۳ ماه اخیر']].map(([k,l]) => (
                <button key={k}
                  style={{ ...finStyles.chip, flexShrink: 0, ...(range===k ? finStyles.chipActive : {}) }}
                  onClick={() => setRange(k)}
                >{l}</button>
              ))}
            </div>

            {/* Empty state */}
            {filtered.length === 0 && (
              <div style={finStyles.empty}>
                <div style={{ fontSize: 38, marginBottom: 10 }}>🪙</div>
                <div>هنوز رویداد مالی ثبت نشده</div>
                <div style={{ fontSize: 12, marginTop: 6, color: 'var(--ink-4)' }}>
                  با دکمه + در بالا اولین ورودی رو بساز
                </div>
              </div>
            )}

            {/* Transaction list */}
            {filtered.map(f => {
              const c = FIN_CATS[f.cat] || FIN_CATS.other;
              const I = Icons[c.icon];
              const isIn = f.type === 'income';
              const isHl = highlightId === f.id;
              return (
                <div key={f.id} id={'fin-item-' + f.id}
                  className="sb-animated-card"
                  style={{ ...finStyles.txCard, ...(isHl ? { boxShadow: '0 0 0 2px var(--firoozeh)', transition: 'box-shadow 0.3s' } : {}) }}
                  onClick={() => setEditItem(f)}
                >
                  <div style={{ ...finStyles.txIcon, background: c.bg, color: c.color }}>
                    {I && <I size={18} />}
                  </div>
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <div style={finStyles.txTitle}>{f.title}</div>
                    <div style={finStyles.txMeta}>
                      {c.label} · {_faDt(f.date)}
                      {f.recurrence && f.recurrence !== 'none' && (
                        <span style={{ marginRight: 4, color: 'var(--firoozeh-deep)' }}>
                          · {f.recurrence === 'monthly' ? '↻ ماهانه' : '↻ سالانه'}
                        </span>
                      )}
                    </div>
                  </div>
                  <div style={{ ...finStyles.txAmount, color: isIn ? '#16A34A' : '#DC2626' }}>
                    {isIn ? '+' : '−'}{_fmtMoney(f.amount)}
                  </div>
                  <button
                    style={{ background: 'none', border: 'none', cursor: 'pointer', color: 'var(--ink-4)', padding: '4px 2px', borderRadius: 8, flexShrink: 0 }}
                    onClick={e => { e.stopPropagation(); window.confirmAction('این رویداد مالی حذف شود؟', () => onDelete(f.id)); }}
                  >
                    <Icons.Trash size={15} />
                  </button>
                </div>
              );
            })}
          </>
        ) : seg === 'chart' ? (
          <AnalyticsView finances={finances} />
        ) : (
          <ForecastView finances={finances} />
        )}

      </div>
      <AddFinanceSheet
        open={addOpen || !!editItem}
        onClose={() => { setEditItem(null); onAddClose(); }}
        onAdd={item => {
          if (editItem) { onUpdate?.(item.id, { type: item.type, cat: item.cat, title: item.title, amount: item.amount, date: item.date, recurrence: item.recurrence }); }
          else { onAdd(item); }
          setEditItem(null);
        }}
        initialData={editItem}
      />
    </>
  );
}

window.Finance = Finance;
