// Flow screens: Add Expense, Add Income, Subscriptions, Credits.
// Each wires through to TxStore / DATA persistence callbacks from app.jsx.

// ─── Offline smart parser: detect amount + category from natural language ─
const SMART_KEYWORDS = {
  food:      ['продукт','магазин','пятёр','пятерочк','перекр','лента','ашан','вкусвилл','фрукт','овощ','хлеб','молок','мяс','сыр','еда'],
  transport: ['такси','метро','автобус','троллейб','трамвай','бензин','заправк','каршер','делимобил','юбер','яндекс го','аэроэкспресс'],
  cafe:      ['кофе','кафе','капучин','латте','эспрессо','ресторан','бар','обед','ужин','завтрак','starbucks','шоколадниц','пиццерия','суши','доставка еды','макдо','бургер','kfc','vkus'],
  edu:       ['курс','обучен','книг','учебник','школа','универ','лекци','skillbox','skillfactory','udemy','coursera','репетитор'],
  health:    ['врач','аптек','лекарств','доктор','клиник','анализ','стомат','зубн','витамин','медицин'],
  fun:       ['кино','театр','концерт','билет','выставк','музей','клуб','боулинг','караок','vr','playstation','xbox','стим','steam','игр'],
  subs:      ['подписк','spotify','netflix','iclou','yotube','copilot','notion','plus','премиум','tinder','duolingo','патреон'],
  gifts:     ['подарок','подар','цвет','букет','сувенир','открытк'],
  travel:    ['отель','авиабилет','авиабиле','перелёт','aviasal','airbnb','booking','эксп','туристич','виза','аренда жил','отдых','путешеств'],
  clothes:   ['одежд','кроссовк','рубашк','штан','джинс','платье','куртк','футболк','свитер','zara','uniqlo','nike','adidas','ботинк','юбк'],
  utilities: ['жкх','коммуналк','свет','газ','вода','электр','отопл','интернет','связь'],
  beauty:    ['парикмах','маникюр','педикюр','салон красот','спа','массаж','стрижк','окраск'],
  pets:      ['корм','зоомагазин','ветеринар','питомец','собак','кошк','кот ','лоток','наполнитель'],
};

function parseSmartExpense(text) {
  const lower = (text || '').toLowerCase();
  const nums = lower.match(/[\d]+([.,][\d]+)?/g) || [];
  const amount = nums.length ? parseFloat(nums[nums.length - 1].replace(',', '.')) : null;
  let catId = null;
  for (const [id, kws] of Object.entries(SMART_KEYWORDS)) {
    if (kws.some(k => lower.includes(k))) { catId = id; break; }
  }
  let note = text.replace(/[\d]+([.,][\d]+)?\s*(₽|руб|р)?/gi, '').replace(/\bза\b/gi, '').replace(/\s+/g, ' ').trim();
  if (note.length > 40) note = note.slice(0, 40);
  return { amount, catId, note };
}

// ═══ ADD EXPENSE ═════════════════════════════════
function AddExpenseScreen({ dark, onClose, settings, onAddTx }) {
  const t = T(dark);
  const [amount, setAmount] = React.useState('0');
  const [currency, setCurrency] = React.useState('RUB');
  const initialCat = (DATA.categories.find(c => !c.archived) || {}).id || 'other';
  const initialAcct = ((DATA.accounts.find(a => a.main) || DATA.accounts[0]) || {}).id;
  const [catId, setCatId] = React.useState(initialCat);
  const [accountId, setAccountId] = React.useState(initialAcct);
  const [note, setNote] = React.useState('');
  const [showAccts, setShowAccts] = React.useState(false);
  const [smart, setSmart] = React.useState('');
  const [listening, setListening] = React.useState(false);
  const [smartHint, setSmartHint] = React.useState(null);
  const [suggestNew, setSuggestNew] = React.useState(null);
  const [aiBusy, setAiBusy] = React.useState(false);
  const [, force] = React.useReducer(x => x + 1, 0);
  const recogRef = React.useRef(null);

  const aiOn = aiAvailable(settings);

  const applySmart = async (text) => {
    if (!text || !text.trim()) return;
    let r;
    if (aiOn) {
      setAiBusy(true);
      try { r = await parseExpenseAI(text, settings); }
      catch (e) {
        setSmartHint({ error: 'AI не ответил, использую правила' });
        setTimeout(() => setSmartHint(null), 2400);
        r = parseSmartExpense(text);
      }
      setAiBusy(false);
    } else r = parseSmartExpense(text);

    if (r.amount != null) setAmount(String(r.amount));
    if (r.catId) setCatId(r.catId);
    if (r.note) setNote(r.note);
    setSmartHint({
      amount: r.amount,
      catTitle: r.catId ? (DATA.categories.find(c => c.id === r.catId) || {}).title : null,
      ai: aiOn,
    });
    setTimeout(() => setSmartHint(null), 2800);
    if (r.suggestNew && r.suggestNew.title) setSuggestNew(r.suggestNew);
  };

  const acceptSuggested = () => {
    if (!suggestNew) return;
    const palette = ['#C77B4A','#5B8BAA','#D4A23A','#7A6BB8','#5BA68A','#FF3D9A','#6D8FFF','#B86F8E','#3DDBDB','#A38869','#3DBA85','#C68FB8'];
    const color = palette[DATA.categories.length % palette.length];
    const newCat = addCategory({
      id: 'c_' + Date.now(),
      title: suggestNew.title,
      icon: 'plus', color, emoji: suggestNew.emoji,
    });
    setCatId(newCat.id);
    setSuggestNew(null);
    force();
  };

  const startVoice = () => {
    const SR = window.SpeechRecognition || window.webkitSpeechRecognition;
    if (!SR) {
      setSmartHint({ error: 'Голосовой ввод не поддерживается браузером' });
      setTimeout(() => setSmartHint(null), 2400);
      return;
    }
    const r = new SR();
    r.lang = 'ru-RU';
    r.interimResults = true;
    r.continuous = false;
    r.onresult = (e) => {
      const txt = Array.from(e.results).map(res => res[0].transcript).join(' ');
      setSmart(txt);
      if (e.results[0].isFinal) applySmart(txt);
    };
    r.onend = () => setListening(false);
    r.onerror = () => setListening(false);
    recogRef.current = r;
    setListening(true);
    r.start();
  };

  const stopVoice = () => {
    if (recogRef.current) recogRef.current.stop();
    setListening(false);
  };

  const tap = (k) => {
    if (k === '⌫') { setAmount(a => a.length <= 1 ? '0' : a.slice(0, -1)); return; }
    if (k === '.') { if (!amount.includes('.')) setAmount(a => a + '.'); return; }
    setAmount(a => a === '0' ? k : a + k);
  };
  const setQuick = (n) => setAmount(String(n));

  const cat = DATA.categories.find(c => c.id === catId) || DATA.categories[0];
  const acct = DATA.accounts.find(a => a.id === accountId) || DATA.accounts[0];
  const rawAmt = parseFloat(amount || 0);
  // Convert to RUB if foreign currency.
  const rateMap = { RUB: 1, USD: DATA.rates.usd, EUR: DATA.rates.eur };
  const rubAmt = rawAmt * (rateMap[currency] || 1);
  const displayAmount = amount.replace(/\B(?=(\d{3})+(?!\.))/g, ' ');
  const usd = (rubAmt / DATA.rates.usd).toFixed(2);
  // Budget warning
  const newSpent = (cat ? cat.spent : 0) + rubAmt;
  const overBudget = cat && cat.planned > 0 && newSpent > cat.planned;
  const overPct = overBudget ? Math.round(newSpent / cat.planned * 100) : 0;

  const save = async () => {
    if (rawAmt <= 0) return;
    const tx = {
      type: 'expense',
      amount: rubAmt,
      currency,
      currencyAmount: currency !== 'RUB' ? rawAmt : undefined,
      categoryId: catId,
      accountId,
      date: new Date().toISOString(),
      note,
      source: smart ? (aiOn ? 'ai' : 'voice') : 'manual',
    };
    await (onAddTx ? onAddTx(tx) : Promise.resolve());
    onClose && onClose();
  };

  const activeCats = DATA.categories.filter(c => !c.archived);

  return (
    <Screen dark={dark} scroll={false} padBottom={0}>
      <div style={{ padding: '6px 20px 10px', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
        <button onClick={onClose} style={{ width: 36, height: 36, borderRadius: 18, border: 'none', background: t.surfaceAlt, cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
          <Icon d={ICONS.x} size={18} stroke={t.ink} />
        </button>
        <div style={{ fontFamily: TOK.fontDisplay, fontSize: 17, fontWeight: 700, color: t.ink }}>Новая трата</div>
        <div style={{ display: 'flex', gap: 4 }}>
          {['RUB','USD','EUR'].map(cc => (
            <button key={cc} onClick={() => setCurrency(cc)} style={{
              padding: '5px 9px', borderRadius: 9, border: 'none', cursor: 'pointer',
              background: currency === cc ? t.accent : t.surfaceAlt,
              color: currency === cc ? '#fff' : t.muted,
              fontFamily: 'inherit', fontSize: 11, fontWeight: 800,
            }}>{cc === 'RUB' ? '₽' : cc === 'USD' ? '$' : '€'}</button>
          ))}
        </div>
      </div>

      {/* smart input */}
      <div style={{ padding: '0 16px 4px' }}>
        <div style={{
          display: 'flex', alignItems: 'center', gap: 8,
          background: listening ? t.accentSoft : t.surface,
          borderRadius: 16, padding: '10px 12px',
          border: `1.5px solid ${listening ? t.accent : t.line}`,
          transition: 'background .15s, border-color .15s',
        }}>
          <button onClick={listening ? stopVoice : startVoice} style={{
            width: 36, height: 36, borderRadius: 10, border: 'none', cursor: 'pointer',
            background: listening ? t.accent : t.accentSoft, color: listening ? '#fff' : t.accent,
            display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0,
            position: 'relative',
          }} title="Голосовой ввод">
            <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
              <rect x="9" y="2" width="6" height="11" rx="3" />
              <path d="M5 10v1a7 7 0 0014 0v-1" />
              <line x1="12" y1="19" x2="12" y2="22" />
            </svg>
            {listening && (
              <div style={{ position: 'absolute', inset: -4, borderRadius: 14, border: `2px solid ${t.accent}`, opacity: 0.4, animation: 'pulse 1.2s ease infinite' }} />
            )}
          </button>
          <input value={smart} onChange={e => setSmart(e.target.value)}
            onKeyDown={e => { if (e.key === 'Enter') applySmart(smart); }}
            placeholder={listening ? 'Слушаю…' : (aiOn ? 'Опишите трату — AI разберёт' : 'Купил кофе за 380')}
            style={{
              flex: 1, border: 'none', outline: 'none', background: 'transparent',
              fontFamily: 'inherit', fontSize: 14, fontWeight: 500, color: t.ink, minWidth: 0,
            }} />
          {aiOn && (
            <div style={{
              padding: '3px 8px', borderRadius: 8, background: t.accent, color: '#fff',
              fontSize: 9, fontWeight: 800, letterSpacing: 0.4, flexShrink: 0,
            }}>AI</div>
          )}
          {smart && !listening && (
            <button onClick={() => applySmart(smart)} disabled={aiBusy} style={{
              padding: '6px 12px', borderRadius: 10, border: 'none', cursor: aiBusy ? 'wait' : 'pointer',
              background: t.accent, color: '#fff', fontFamily: 'inherit', fontSize: 12, fontWeight: 700,
              opacity: aiBusy ? 0.6 : 1,
            }}>{aiBusy ? '…' : 'OK'}</button>
          )}
        </div>
        {smartHint && (
          <div style={{
            marginTop: 8, padding: '8px 12px', borderRadius: 10,
            background: smartHint.error ? t.dangerSoft : t.accentSoft,
            color: smartHint.error ? t.danger : t.accent,
            fontSize: 12, fontWeight: 600,
          }}>
            {smartHint.error || (
              <>
                {smartHint.ai && <span style={{ fontWeight: 800 }}>AI: </span>}
                {smartHint.amount != null && <>сумма <b>{fmtR(smartHint.amount)} ₽</b></>}
                {smartHint.amount != null && smartHint.catTitle && ' · '}
                {smartHint.catTitle && <>категория <b>{smartHint.catTitle}</b></>}
                {smartHint.amount == null && !smartHint.catTitle && 'не распознал, попробуйте ещё раз'}
              </>
            )}
          </div>
        )}
        {suggestNew && (
          <div style={{
            marginTop: 8, padding: '10px 12px', borderRadius: 12,
            background: t.warnSoft, color: dark ? t.warn : '#7A5E1B',
            fontSize: 12, fontWeight: 600,
            display: 'flex', alignItems: 'center', gap: 8,
          }}>
            <div style={{ fontSize: 18 }}>{suggestNew.emoji || '✨'}</div>
            <div style={{ flex: 1 }}>
              AI предлагает новую категорию: <b>{suggestNew.title}</b>
            </div>
            <button onClick={acceptSuggested} style={{
              padding: '6px 12px', borderRadius: 10, border: 'none', cursor: 'pointer',
              background: t.accent, color: '#fff', fontFamily: 'inherit', fontSize: 12, fontWeight: 700,
            }}>Создать</button>
            <button onClick={() => setSuggestNew(null)} style={{
              padding: '6px 10px', borderRadius: 10, border: 'none', cursor: 'pointer',
              background: 'transparent', color: 'inherit', fontFamily: 'inherit', fontSize: 12, fontWeight: 600,
            }}>×</button>
          </div>
        )}
      </div>

      {/* amount display */}
      <div style={{ padding: '6px 24px 0', textAlign: 'center' }}>
        <div style={{ fontSize: 11, color: t.muted, fontWeight: 700, letterSpacing: 0.6, textTransform: 'uppercase' }}>
          Сумма {currency !== 'RUB' && '(' + currency + ')'}
        </div>
        <div style={{ fontFamily: TOK.fontDisplay, fontSize: 56, fontWeight: 800, color: overBudget ? t.danger : t.ink, letterSpacing: -2.5, lineHeight: 1.05, marginTop: 4, fontVariantNumeric: 'tabular-nums' }}>
          {displayAmount} <span style={{ color: t.accent }}>{currency === 'RUB' ? '₽' : currency === 'USD' ? '$' : '€'}</span>
        </div>
        <div style={{ fontSize: 12, color: overBudget ? t.danger : t.muted, marginTop: 2, fontVariantNumeric: 'tabular-nums', fontWeight: overBudget ? 700 : 500 }}>
          {currency !== 'RUB' && <>≈ {fmtR(rubAmt)} ₽ · </>}
          ≈ ${usd}
          {overBudget && <> · {overPct}% от плана «{cat.title}»</>}
        </div>
      </div>

      {/* quick amounts */}
      <div style={{ padding: '8px 20px 8px', display: 'flex', gap: 6, justifyContent: 'center' }}>
        {[100, 500, 1000, 5000].map(n => (
          <Pill key={n} dark={dark} onClick={() => setQuick(n)} style={{ padding: '6px 12px', fontSize: 12 }}>
            +{fmtCompact(n)}
          </Pill>
        ))}
      </div>

      {/* category strip */}
      <div style={{ padding: '4px 0 8px', overflowX: 'auto' }}>
        <div style={{ display: 'flex', gap: 8, padding: '0 20px', width: 'max-content' }}>
          {activeCats.map(c => {
            const active = c.id === catId;
            return (
              <button key={c.id} onClick={() => setCatId(c.id)} style={{
                width: 62, padding: '10px 6px', borderRadius: 16, border: 'none', cursor: 'pointer',
                background: active ? c.color : t.surface,
                color: active ? '#fff' : t.ink,
                boxShadow: active ? `0 8px 18px ${c.color}50` : `0 1px 3px ${t.line}`,
                transform: active ? 'translateY(-2px)' : 'none', transition: 'all .15s',
                display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 4,
                fontFamily: 'inherit', flexShrink: 0,
              }}>
                {c.emoji
                  ? <div style={{ fontSize: 20, lineHeight: 1 }}>{c.emoji}</div>
                  : <Icon d={ICONS[c.icon]} size={20} stroke={active ? '#fff' : c.color} sw={1.9} />}
                <div style={{ fontSize: 9.5, fontWeight: 700, letterSpacing: -0.1 }}>{c.title}</div>
              </button>
            );
          })}
        </div>
      </div>

      {/* account + note */}
      <div style={{ padding: '4px 20px 12px' }}>
        <Card dark={dark} pad={0} radius={16}>
          <button onClick={() => setShowAccts(true)} style={{
            width: '100%', border: 'none', background: 'transparent', cursor: 'pointer',
            padding: '12px 14px', display: 'flex', alignItems: 'center', gap: 12,
            borderBottom: `1px solid ${t.line}`, fontFamily: 'inherit', textAlign: 'left',
          }}>
            <div style={{ width: 30, height: 30, borderRadius: 8, background: acct ? acct.color : t.surfaceAlt, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
              <Icon d={ICONS.card} size={16} stroke="#fff" sw={2} />
            </div>
            <div style={{ flex: 1 }}>
              <div style={{ fontSize: 11, color: t.muted, fontWeight: 600 }}>Списать со счёта</div>
              <div style={{ fontSize: 14, color: t.ink, fontWeight: 700, marginTop: 1 }}>{acct ? `${acct.bank} · ${acct.title}` : '—'}</div>
            </div>
            <div style={{ fontSize: 12, color: t.muted, fontVariantNumeric: 'tabular-nums' }}>{acct ? fmtR(acct.balance) + ' ₽' : ''}</div>
            <Icon d={ICONS.chevronD} size={16} stroke={t.faint} />
          </button>

          <div style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '12px 14px' }}>
            <div style={{ width: 30, height: 30, borderRadius: 8, background: t.surfaceAlt, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
              <Icon d={ICONS.edit} size={14} stroke={t.muted} sw={1.8} />
            </div>
            <input value={note} onChange={e => setNote(e.target.value)} placeholder="Заметка (необязательно)"
              style={{ flex: 1, border: 'none', outline: 'none', background: 'transparent', fontFamily: 'inherit', fontSize: 14, color: t.ink, fontWeight: 500 }} />
          </div>
        </Card>
      </div>

      {/* numpad */}
      <div style={{ position: 'absolute', left: 0, right: 0, bottom: 0, padding: '0 16px 14px', background: t.bg }}>
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 8, marginBottom: 10 }}>
          {['1','2','3','4','5','6','7','8','9','.','0','⌫'].map(k => (
            <button key={k} onClick={() => tap(k)} style={{
              padding: '16px 0', borderRadius: 16, border: 'none', cursor: 'pointer',
              background: t.surface, color: t.ink,
              fontFamily: TOK.fontDisplay, fontSize: 24, fontWeight: 700,
              boxShadow: dark ? 'none' : `0 1px 2px ${t.line}`,
              transition: 'background .1s',
            }}
              onMouseDown={e => e.currentTarget.style.background = t.surfaceAlt}
              onMouseUp={e => e.currentTarget.style.background = t.surface}
              onMouseLeave={e => e.currentTarget.style.background = t.surface}>
              {k === '⌫' ? <Icon d={['M12 19l-7-7 7-7','M5 12h14','M8 9l3 3-3 3']} size={20} stroke={t.muted} sw={2} /> : k}
            </button>
          ))}
        </div>
        <Btn dark={dark} primary full onClick={save} icon="check">
          Сохранить · {cat ? cat.title : ''}
        </Btn>
      </div>

      <Sheet open={showAccts} onClose={() => setShowAccts(false)} dark={dark} title="С какого счёта">
        {DATA.accounts.map((a, i) => (
          <button key={a.id} onClick={() => { setAccountId(a.id); setShowAccts(false); }} style={{
            width: '100%', border: 'none', background: 'transparent', cursor: 'pointer', padding: 0, textAlign: 'left',
          }}>
            <ListRow dark={dark} icon="card" color={a.color} title={`${a.bank} · ${a.title}`} sub={`•• ${a.last4}`} value={`${fmtR(a.balance)} ₽`} last={i === DATA.accounts.length - 1} />
          </button>
        ))}
      </Sheet>
    </Screen>
  );
}

// ═══ ADD INCOME ════════════════════════
function AddIncomeScreen({ dark, onClose, onAddTx }) {
  const t = T(dark);
  const [amount, setAmount] = React.useState('0');
  const sources = [
    { id: 'salary',   title: 'Зарплата',   icon: 'briefcase', color: '#0F8A5A' },
    { id: 'freelance',title: 'Фриланс',    icon: 'edit',      color: '#C77B4A' },
    { id: 'invest',   title: 'Инвестиции', icon: 'invest',    color: '#5B8BAA' },
    { id: 'gift',     title: 'Подарок',    icon: 'gift',      color: '#B86F8E' },
    { id: 'sale',     title: 'Продажа',    icon: 'cart',      color: '#7A6BB8' },
    { id: 'cashback', title: 'Кэшбэк',     icon: 'card',      color: '#D4A23A' },
  ];
  const [source, setSource] = React.useState('salary');
  const [accountId, setAccountId] = React.useState(((DATA.accounts.find(a => a.main) || DATA.accounts[0]) || {}).id);
  const [autoDistribute, setAutoDistribute] = React.useState(true);
  const [showAccts, setShowAccts] = React.useState(false);

  const incSrc = DATA.incomeSources.find(s => s.id === source);
  const distributionRules = autoDistribute && incSrc && incSrc.distributionRules;

  const tap = (k) => {
    if (k === '⌫') { setAmount(a => a.length <= 1 ? '0' : a.slice(0, -1)); return; }
    if (k === '.') { if (!amount.includes('.')) setAmount(a => a + '.'); return; }
    setAmount(a => a === '0' ? k : a + k);
  };
  const displayAmount = amount.replace(/\B(?=(\d{3})+(?!\.))/g, ' ');
  const acct = DATA.accounts.find(a => a.id === accountId) || DATA.accounts[0];

  const save = async () => {
    const total = parseFloat(amount || 0);
    if (total <= 0 || !onAddTx) { onClose && onClose(); return; }
    const sourceTitle = (sources.find(s => s.id === source) || {}).title || 'Доход';

    if (distributionRules && distributionRules.length) {
      for (const rule of distributionRules) {
        const part = Math.round(total * (rule.percent || 0) / 100);
        if (part <= 0) continue;
        await onAddTx({
          type: 'income', amount: part, currency: 'RUB',
          categoryId: source, accountId: rule.accountId,
          date: new Date().toISOString(),
          note: `${sourceTitle} (${rule.percent}%)`,
          source: 'manual',
        });
      }
    } else {
      await onAddTx({
        type: 'income', amount: total, currency: 'RUB',
        categoryId: source, accountId,
        date: new Date().toISOString(),
        note: sourceTitle,
        source: 'manual',
      });
    }
    onClose && onClose();
  };

  return (
    <Screen dark={dark} scroll={false} padBottom={0}>
      <div style={{ padding: '6px 20px 12px', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
        <button onClick={onClose} style={{ width: 36, height: 36, borderRadius: 18, border: 'none', background: t.surfaceAlt, cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
          <Icon d={ICONS.x} size={18} stroke={t.ink} />
        </button>
        <div style={{ fontFamily: TOK.fontDisplay, fontSize: 17, fontWeight: 700, color: t.ink }}>Доход</div>
        <div style={{ width: 36 }} />
      </div>

      <div style={{ padding: '14px 24px 4px', textAlign: 'center' }}>
        <div style={{ fontSize: 11, color: t.muted, fontWeight: 700, letterSpacing: 0.6, textTransform: 'uppercase' }}>Сумма</div>
        <div style={{ fontFamily: TOK.fontDisplay, fontSize: 60, fontWeight: 800, color: t.positive, letterSpacing: -2.5, lineHeight: 1.05, marginTop: 4, fontVariantNumeric: 'tabular-nums' }}>
          +{displayAmount} ₽
        </div>
      </div>

      <div style={{ padding: '14px 0 10px', overflowX: 'auto' }}>
        <div style={{ display: 'flex', gap: 8, padding: '0 20px', width: 'max-content' }}>
          {sources.map(s => {
            const active = s.id === source;
            return (
              <button key={s.id} onClick={() => setSource(s.id)} style={{
                width: 76, padding: '10px 6px', borderRadius: 16, border: 'none', cursor: 'pointer',
                background: active ? s.color : t.surface,
                color: active ? '#fff' : t.ink,
                boxShadow: active ? `0 8px 18px ${s.color}50` : `0 1px 3px ${t.line}`,
                transform: active ? 'translateY(-2px)' : 'none', transition: 'all .15s',
                display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 4,
                fontFamily: 'inherit',
              }}>
                <Icon d={ICONS[s.icon]} size={20} stroke={active ? '#fff' : s.color} sw={1.9} />
                <div style={{ fontSize: 10, fontWeight: 700 }}>{s.title}</div>
              </button>
            );
          })}
        </div>
      </div>

      <div style={{ padding: '4px 20px 12px' }}>
        <Card dark={dark} pad={0} radius={16}>
          <button onClick={() => setShowAccts(true)} style={{
            width: '100%', border: 'none', background: 'transparent', cursor: 'pointer',
            padding: '12px 14px', display: 'flex', alignItems: 'center', gap: 12,
            borderBottom: `1px solid ${t.line}`, fontFamily: 'inherit', textAlign: 'left',
          }}>
            <div style={{ width: 30, height: 30, borderRadius: 8, background: acct ? acct.color : t.surfaceAlt, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
              <Icon d={ICONS.card} size={16} stroke="#fff" sw={2} />
            </div>
            <div style={{ flex: 1 }}>
              <div style={{ fontSize: 11, color: t.muted, fontWeight: 600 }}>Зачислить на</div>
              <div style={{ fontSize: 14, color: t.ink, fontWeight: 700, marginTop: 1 }}>{acct ? `${acct.bank} · ${acct.title}` : '—'}</div>
            </div>
            <Icon d={ICONS.chevronD} size={16} stroke={t.faint} />
          </button>
          {incSrc && incSrc.distributionRules && incSrc.distributionRules.length > 0 && (
            <button onClick={() => setAutoDistribute(v => !v)} style={{
              width: '100%', border: 'none', background: 'transparent', cursor: 'pointer',
              padding: '12px 14px', display: 'flex', alignItems: 'center', gap: 12, fontFamily: 'inherit', textAlign: 'left',
            }}>
              <div style={{ width: 30, height: 30, borderRadius: 8, background: t.accentSoft, color: t.accent, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
                <Icon d={ICONS.repeat} size={14} stroke={t.accent} sw={2} />
              </div>
              <div style={{ flex: 1 }}>
                <div style={{ fontSize: 14, color: t.ink, fontWeight: 700 }}>Авто-распределение</div>
                <div style={{ fontSize: 11, color: t.muted, fontWeight: 500, marginTop: 1 }}>
                  {incSrc.distributionRules.map(r => `${r.percent}% ${(DATA.accounts.find(a => a.id === r.accountId) || {}).bank || '—'}`).join(' · ')}
                </div>
              </div>
              <div style={{
                width: 42, height: 24, borderRadius: 12, position: 'relative',
                background: autoDistribute ? t.accent : t.lineStrong, transition: 'background .15s',
              }}>
                <div style={{ position: 'absolute', top: 2, left: autoDistribute ? 20 : 2, width: 20, height: 20, borderRadius: 10, background: '#fff', boxShadow: '0 1px 3px rgba(0,0,0,0.25)', transition: 'left .15s' }} />
              </div>
            </button>
          )}
        </Card>
      </div>

      <div style={{ position: 'absolute', left: 0, right: 0, bottom: 0, padding: '0 16px 14px', background: t.bg }}>
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 8, marginBottom: 10 }}>
          {['1','2','3','4','5','6','7','8','9','.','0','⌫'].map(k => (
            <button key={k} onClick={() => tap(k)} style={{
              padding: '16px 0', borderRadius: 16, border: 'none', cursor: 'pointer',
              background: t.surface, color: t.ink,
              fontFamily: TOK.fontDisplay, fontSize: 24, fontWeight: 700,
              boxShadow: dark ? 'none' : `0 1px 2px ${t.line}`,
            }}>
              {k === '⌫' ? <Icon d={['M12 19l-7-7 7-7','M5 12h14','M8 9l3 3-3 3']} size={20} stroke={t.muted} sw={2} /> : k}
            </button>
          ))}
        </div>
        <Btn dark={dark} primary full onClick={save} icon="check">Добавить доход</Btn>
      </div>

      <Sheet open={showAccts} onClose={() => setShowAccts(false)} dark={dark} title="На какой счёт">
        {DATA.accounts.map((a, i) => (
          <button key={a.id} onClick={() => { setAccountId(a.id); setShowAccts(false); }} style={{
            width: '100%', border: 'none', background: 'transparent', cursor: 'pointer', padding: 0, textAlign: 'left',
          }}>
            <ListRow dark={dark} icon="card" color={a.color} title={`${a.bank} · ${a.title}`} sub={`•• ${a.last4}`} value={`${fmtR(a.balance)} ₽`} last={i === DATA.accounts.length - 1} />
          </button>
        ))}
      </Sheet>
    </Screen>
  );
}

// ═══ SUBSCRIPTIONS ═══════════════════════════════
function SubscriptionsScreen({ dark, onBack }) {
  const t = T(dark);
  const [editing, setEditing] = React.useState(null);
  const [, force] = React.useReducer(x => x + 1, 0);

  const subs = DATA.subs.slice();
  const total = subs.reduce((s,x) => s + x.amount, 0);
  const yearTotal = total * 12;
  const sorted = subs.slice().sort((a,b) => a.day - b.day);
  const today = new Date().getDate();
  const next = sorted.find(s => s.day >= today) || sorted[0];

  const onSave = (s) => {
    if (s.__delete) DATA.subs = DATA.subs.filter(x => x.id !== s.id);
    else if (s.id === '__new') DATA.subs.push({ ...s, id: 'sub-' + Date.now() });
    else { const i = DATA.subs.findIndex(x => x.id === s.id); if (i >= 0) DATA.subs[i] = s; }
    persistSubs();
    setEditing(null); force();
  };

  return (
    <Screen dark={dark}>
      <PageHeader dark={dark} title="Подписки" subtitle={`${subs.length} активных`} large
        leading={<BackBtn dark={dark} onClick={onBack} />}
        trailing={
          <button onClick={() => setEditing('__new')} style={{ width: 36, height: 36, borderRadius: 18, border: `1px solid ${t.line}`, background: t.surface, display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer' }}>
            <Icon d={ICONS.plus} size={18} stroke={t.ink} sw={2.2} />
          </button>
        } />

      <div style={{ padding: '0 20px' }}>
        <Card dark={dark} pad={22} radius={24}>
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>
            <div>
              <div style={{ fontSize: 12, color: t.muted, fontWeight: 600, letterSpacing: 0.3 }}>В МЕСЯЦ</div>
              <div style={{ fontFamily: TOK.fontDisplay, fontSize: 38, fontWeight: 800, marginTop: 4, letterSpacing: -1.2, lineHeight: 1, color: t.ink, fontVariantNumeric: 'tabular-nums' }}>
                {fmtR(total)} <span style={{ fontSize: 18, color: t.muted, fontWeight: 700 }}>₽</span>
              </div>
              <div style={{ fontSize: 12, color: t.muted, marginTop: 4, fontVariantNumeric: 'tabular-nums' }}>{fmtR(yearTotal)} ₽ в год</div>
            </div>
          </div>

          <div style={{ marginTop: 22 }}>
            <div style={{ fontSize: 11, color: t.muted, fontWeight: 700, marginBottom: 10, letterSpacing: 0.3 }}>СПИСАНИЯ В МЕСЯЦЕ</div>
            <div style={{ position: 'relative', height: 32 }}>
              <div style={{ position: 'absolute', left: 0, right: 0, top: 14, height: 3, background: t.surfaceAlt, borderRadius: 2 }} />
              {sorted.map(s => (
                <div key={s.id} style={{
                  position: 'absolute', left: `${(s.day / 30) * 100}%`, top: 5, transform: 'translateX(-50%)',
                  width: 22, height: 22, borderRadius: 11, background: s.color, color: '#fff',
                  display: 'flex', alignItems: 'center', justifyContent: 'center',
                  fontSize: 9, fontWeight: 800, boxShadow: `0 2px 6px ${s.color}66`,
                  border: '2px solid ' + t.surface,
                }} title={`${s.title} · ${s.day}`}>{s.logo}</div>
              ))}
            </div>
            <div style={{ display: 'flex', justifyContent: 'space-between', marginTop: 8, fontSize: 10, color: t.faint, fontWeight: 700 }}>
              <span>1</span><span>10</span><span>20</span><span>30</span>
            </div>
          </div>
        </Card>

        {next && (
          <Card dark={dark} pad={14} radius={16} style={{ marginTop: 12, display: 'flex', alignItems: 'center', gap: 12, background: t.warnSoft, color: t.warn }}>
            <Icon d={ICONS.bell} size={20} stroke={t.warn} />
            <div style={{ flex: 1, fontSize: 13, color: dark ? t.warn : '#7A5E1B', fontWeight: 600 }}>
              Ближайшее: <b>{next.title}</b> — {fmtR(next.amount)} ₽ · {next.day} числа
            </div>
          </Card>
        )}

        <SectionLabel dark={dark} action="Добавить" onAction={() => setEditing('__new')}>Все подписки</SectionLabel>
        {sorted.length === 0 ? (
          <Card dark={dark} pad={20} radius={16} style={{ textAlign: 'center', color: t.muted, fontSize: 13 }}>
            Подписок пока нет.
          </Card>
        ) : (
          <Card dark={dark} pad={0} radius={20}>
            {sorted.map((s, i) => (
              <button key={s.id} onClick={() => setEditing(s.id)} style={{
                width: '100%', border: 'none', background: 'transparent', cursor: 'pointer', textAlign: 'left',
                padding: '14px 16px', borderBottom: i === sorted.length - 1 ? 'none' : `1px solid ${t.line}`,
                display: 'flex', alignItems: 'center', gap: 12, fontFamily: 'inherit',
              }}>
                <div style={{
                  width: 44, height: 44, borderRadius: 12, background: s.color, color: '#fff',
                  display: 'flex', alignItems: 'center', justifyContent: 'center',
                  fontFamily: TOK.fontDisplay, fontWeight: 800, fontSize: 14, flexShrink: 0,
                }}>{s.logo}</div>
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ fontSize: 15, fontWeight: 700, color: t.ink }}>{s.title}</div>
                  <div style={{ fontSize: 11, color: t.muted, fontWeight: 500, marginTop: 2 }}>{s.cat} · {s.day} числа</div>
                </div>
                <div style={{ textAlign: 'right' }}>
                  <div style={{ fontFamily: TOK.fontDisplay, fontSize: 15, fontWeight: 800, color: t.ink, fontVariantNumeric: 'tabular-nums' }}>{fmtR(s.amount)} ₽</div>
                  <div style={{ fontSize: 10, color: t.muted, marginTop: 2 }}>/мес</div>
                </div>
                <Icon d={ICONS.chevronR} size={14} stroke={t.faint} />
              </button>
            ))}
          </Card>
        )}

        <button onClick={() => setEditing('__new')} style={{
          marginTop: 14, padding: '16px 18px', borderRadius: 18, border: `2px dashed ${t.lineStrong}`,
          background: 'transparent', color: t.accent, cursor: 'pointer', width: '100%',
          fontFamily: 'inherit', fontSize: 14, fontWeight: 700,
          display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,
        }}>
          <Icon d={ICONS.plus} size={16} stroke={t.accent} sw={2.4} />
          Добавить подписку
        </button>
      </div>

      <EditSubSheet dark={dark} editingId={editing}
        initial={editing && editing !== '__new' ? subs.find(s => s.id === editing) : null}
        onClose={() => setEditing(null)} onSave={onSave} />
    </Screen>
  );
}

function EditSubSheet({ dark, editingId, initial, onClose, onSave }) {
  const t = T(dark);
  const isNew = editingId === '__new';
  const defaults = {
    id: '__new', title: '', amount: 299, day: 1, color: '#0F8A5A',
    cat: 'Сервисы', logo: 'M', accountId: ((DATA.accounts.find(a => a.main) || DATA.accounts[0]) || {}).id, active: true,
  };
  const [form, setForm] = React.useState(initial || defaults);

  React.useEffect(() => {
    if (initial) setForm(initial);
    else if (isNew) setForm(defaults);
  }, [editingId]);

  if (!editingId) return null;
  const set = (k, v) => setForm(f => ({ ...f, [k]: v }));

  const PALETTE = ['#0F8A5A','#1DB954','#FFDB4D','#2997FF','#24292E','#2D2D2D','#FA5400','#C77B4A','#B86F8E','#5B8BAA','#7A6BB8','#D4A23A'];
  const CATS = ['Музыка','Сервисы','Облако','Работа','Спорт','Видео','Игры','Другое'];

  const Field = ({ label, value, onChange, suffix, isNum, placeholder }) => (
    <div style={{ marginBottom: 10 }}>
      <div style={{ fontSize: 11, color: t.muted, fontWeight: 700, textTransform: 'uppercase', letterSpacing: 0.4, marginBottom: 4 }}>{label}</div>
      <div style={{ display: 'flex', alignItems: 'center', gap: 6, background: t.surface, borderRadius: 12, padding: '10px 14px', border: `1px solid ${t.line}` }}>
        <input value={value} placeholder={placeholder}
          onChange={e => onChange(isNum ? (parseFloat(e.target.value) || 0) : e.target.value)}
          inputMode={isNum ? 'decimal' : 'text'}
          style={{ flex: 1, border: 'none', outline: 'none', background: 'transparent', fontFamily: 'inherit',
            fontSize: 15, fontWeight: 600, color: t.ink, fontVariantNumeric: 'tabular-nums', width: '100%' }} />
        {suffix && <div style={{ fontSize: 12, color: t.muted, fontWeight: 600 }}>{suffix}</div>}
      </div>
    </div>
  );

  return (
    <Sheet open={!!editingId} onClose={onClose} dark={dark} title={isNew ? 'Новая подписка' : 'Изменить подписку'} height="92%">
      <div style={{ marginBottom: 14, display: 'flex', alignItems: 'center', gap: 12, padding: 14, background: t.surface, borderRadius: 16 }}>
        <div style={{
          width: 48, height: 48, borderRadius: 14, background: form.color, color: '#fff',
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          fontFamily: TOK.fontDisplay, fontWeight: 800, fontSize: 16,
        }}>{(form.logo || form.title || 'M').slice(0, 2).toUpperCase()}</div>
        <div style={{ flex: 1 }}>
          <div style={{ fontSize: 15, fontWeight: 700, color: t.ink }}>{form.title || 'Название'}</div>
          <div style={{ fontSize: 11, color: t.muted, marginTop: 2 }}>{form.cat} · {form.day} числа</div>
        </div>
        <div style={{ fontFamily: TOK.fontDisplay, fontSize: 16, fontWeight: 800, color: t.ink, fontVariantNumeric: 'tabular-nums' }}>{fmtR(form.amount)} ₽</div>
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
        <Field label="Название" value={form.title} onChange={v => set('title', v)} placeholder="Spotify" />
        <Field label="Логотип" value={form.logo} onChange={v => set('logo', v.slice(0, 2))} placeholder="S" />
        <Field label="Сумма" value={form.amount} onChange={v => set('amount', v)} suffix="₽" isNum />
        <Field label="День списания" value={form.day} onChange={v => set('day', Math.min(31, Math.max(1, v)))} suffix="числа" isNum />
      </div>

      <div style={{ fontSize: 11, color: t.muted, fontWeight: 700, textTransform: 'uppercase', letterSpacing: 0.4, margin: '4px 0 6px' }}>Категория</div>
      <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6, marginBottom: 12 }}>
        {CATS.map(c => (
          <Pill key={c} dark={dark} active={form.cat === c} onClick={() => set('cat', c)}>{c}</Pill>
        ))}
      </div>

      <div style={{ fontSize: 11, color: t.muted, fontWeight: 700, textTransform: 'uppercase', letterSpacing: 0.4, margin: '4px 0 6px' }}>Цвет</div>
      <div style={{ display: 'flex', gap: 8, marginBottom: 14, flexWrap: 'wrap' }}>
        {PALETTE.map(p => (
          <button key={p} onClick={() => set('color', p)} style={{
            width: 34, height: 34, borderRadius: 10, border: 'none', background: p, cursor: 'pointer',
            boxShadow: form.color === p ? `0 0 0 3px ${t.bg}, 0 0 0 5px ${p}` : 'none',
          }}>
            {form.color === p && <Icon d={ICONS.check} size={16} stroke="#fff" sw={3} />}
          </button>
        ))}
      </div>

      <div style={{ fontSize: 11, color: t.muted, fontWeight: 700, textTransform: 'uppercase', letterSpacing: 0.4, margin: '4px 0 6px' }}>Списывать с</div>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 6, marginBottom: 12 }}>
        {DATA.accounts.map(a => (
          <button key={a.id} onClick={() => set('accountId', a.id)} style={{
            padding: '10px 12px', borderRadius: 12, border: `1.5px solid ${form.accountId === a.id ? t.accent : t.line}`,
            background: form.accountId === a.id ? t.accentSoft : t.surface, cursor: 'pointer',
            display: 'flex', alignItems: 'center', gap: 10, fontFamily: 'inherit',
          }}>
            <div style={{ width: 22, height: 22, borderRadius: 6, background: a.color }} />
            <div style={{ flex: 1, textAlign: 'left' }}>
              <div style={{ fontSize: 13, fontWeight: 700, color: t.ink }}>{a.bank} · {a.title}</div>
            </div>
            {form.accountId === a.id && <Icon d={ICONS.check} size={14} stroke={t.accent} sw={2.4} />}
          </button>
        ))}
      </div>

      <div style={{ display: 'flex', gap: 10, marginTop: 4 }}>
        {!isNew && (
          <button onClick={() => onSave({ ...form, __delete: true })} style={{
            padding: '14px 16px', borderRadius: 14, border: 'none', cursor: 'pointer',
            background: t.dangerSoft, color: t.danger, fontFamily: 'inherit', fontSize: 14, fontWeight: 700,
            display: 'flex', alignItems: 'center', gap: 6,
          }}>
            <Icon d={ICONS.trash} size={16} stroke={t.danger} sw={2} />
            Удалить
          </button>
        )}
        <Btn dark={dark} primary full onClick={() => onSave(form)} icon="check" style={{ flex: 1 }}>
          {isNew ? 'Создать' : 'Сохранить'}
        </Btn>
      </div>
    </Sheet>
  );
}

// ═══ CREDITS ═════════════════════════════════════
function CreditsScreen({ dark, onBack, settings }) {
  const t = T(dark);
  const [editing, setEditing] = React.useState(null);
  const [pdfBusy, setPdfBusy] = React.useState(false);
  const [pdfError, setPdfError] = React.useState(null);
  const [, force] = React.useReducer(x => x + 1, 0);
  const fileRef = React.useRef(null);

  const credits = DATA.credits.slice();
  const totalDebt = credits.reduce((s,c) => s + (c.total - c.paid), 0);
  const _now = new Date();
  const thisYear = _now.getFullYear(), thisMonth = _now.getMonth() + 1;
  const monthlyTotal = credits.reduce((s,c) => s + creditPaymentForMonth(c, thisYear, thisMonth), 0);

  const onSave = (c) => {
    if (c.id === '__new') DATA.credits.push({ ...c, id: 'cr-' + Date.now() });
    else if (c.__delete) DATA.credits = DATA.credits.filter(x => x.id !== c.id);
    else { const i = DATA.credits.findIndex(x => x.id === c.id); if (i >= 0) DATA.credits[i] = c; }
    persistCredits();
    setEditing(null); force();
  };

  const onUploadPdf = async (e) => {
    const file = e.target.files && e.target.files[0];
    e.target.value = '';
    if (!file) return;
    if (!aiAvailable(settings)) {
      setPdfError('Включите AI в настройках, чтобы разбирать PDF договоры.');
      return;
    }
    setPdfBusy(true);
    setPdfError(null);
    try {
      const parsed = await parseCreditPdfAI(file, settings);
      const draft = {
        id: '__new',
        bank: parsed.bank || 'Банк',
        title: parsed.title || 'Кредит',
        total: parsed.total || 0,
        paid: 0,
        rate: parsed.rate || 10,
        monthly: parsed.monthly || 0,
        years: parsed.years || 5,
        nextDate: parsed.nextDate || '01 нояб',
        accountId: ((DATA.accounts.find(a => a.main) || DATA.accounts[0]) || {}).id,
        paymentSchedule: parsed.schedule || [],
      };
      setEditing(draft);
    } catch (err) {
      setPdfError('Не удалось разобрать PDF: ' + (err.message || err));
    } finally {
      setPdfBusy(false);
    }
  };

  return (
    <Screen dark={dark}>
      <PageHeader dark={dark} title="Кредиты" subtitle="Активные обязательства" large
        leading={<BackBtn dark={dark} onClick={onBack} />}
        trailing={
          <button onClick={() => setEditing('__new')} style={{ width: 36, height: 36, borderRadius: 18, border: `1px solid ${t.line}`, background: t.surface, display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer' }}>
            <Icon d={ICONS.plus} size={18} stroke={t.ink} sw={2.2} />
          </button>
        } />

      <div style={{ padding: '0 20px' }}>
        <Card dark={dark} pad={22} radius={24}>
          <div style={{ fontSize: 12, color: t.muted, fontWeight: 700, letterSpacing: 0.3 }}>ОБЩИЙ ДОЛГ</div>
          <div style={{ fontFamily: TOK.fontDisplay, fontSize: 38, fontWeight: 800, marginTop: 4, letterSpacing: -1.2, lineHeight: 1, color: t.ink, fontVariantNumeric: 'tabular-nums' }}>
            {fmtR(totalDebt)} <span style={{ fontSize: 18, color: t.muted, fontWeight: 700 }}>₽</span>
          </div>
          <div style={{ marginTop: 14, padding: '10px 14px', background: t.warnSoft, borderRadius: 12, display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
            <div style={{ fontSize: 13, color: dark ? t.warn : '#7A5E1B', fontWeight: 600 }}>В месяц на платежи</div>
            <div style={{ fontFamily: TOK.fontDisplay, fontSize: 16, fontWeight: 800, color: dark ? t.warn : '#7A5E1B', fontVariantNumeric: 'tabular-nums' }}>{fmtR(monthlyTotal)} ₽</div>
          </div>
        </Card>

        <div style={{ marginTop: 12, display: 'flex', flexDirection: 'column', gap: 12 }}>
          {credits.map(c => {
            const pct = Math.round((c.paid / c.total) * 100);
            const remaining = c.total - c.paid;
            const linkedAcct = DATA.accounts.find(a => a.id === c.accountId);
            const hasSchedule = Array.isArray(c.paymentSchedule) && c.paymentSchedule.length > 0;
            const thisMonthAmount = creditPaymentForMonth(c, thisYear, thisMonth);
            // Find the next future payment from schedule (if any), for "Следующий платёж"
            let nextLabel = c.nextDate, nextAmount = thisMonthAmount;
            if (hasSchedule) {
              const todayKey = new Date().toISOString().slice(0, 10);
              const future = c.paymentSchedule
                .map(p => {
                  const s = String(p.date || '').replace(/[-/]/g, '.');
                  const m1 = s.match(/^(\d{1,2})\.(\d{1,2})\.(\d{4})$/);
                  const m2 = s.match(/^(\d{4})\.(\d{1,2})\.(\d{1,2})$/);
                  let iso;
                  if (m1) iso = `${m1[3]}-${m1[2].padStart(2,'0')}-${m1[1].padStart(2,'0')}`;
                  else if (m2) iso = `${m2[1]}-${m2[2].padStart(2,'0')}-${m2[3].padStart(2,'0')}`;
                  return iso ? { iso, amount: p.amount } : null;
                })
                .filter(x => x && x.iso >= todayKey)
                .sort((a,b) => a.iso.localeCompare(b.iso));
              if (future[0]) {
                const MONTHS = ['янв','фев','мар','апр','май','июн','июл','авг','сен','окт','нояб','дек'];
                const d = new Date(future[0].iso + 'T00:00:00');
                nextLabel = `${String(d.getDate()).padStart(2,'0')} ${MONTHS[d.getMonth()]}`;
                nextAmount = future[0].amount;
              }
            }
            // Min/max in schedule — to show range for differentiated credits
            let minPayment = null, maxPayment = null;
            if (hasSchedule) {
              const amounts = c.paymentSchedule.map(p => p.amount).filter(a => a > 0);
              if (amounts.length) { minPayment = Math.min(...amounts); maxPayment = Math.max(...amounts); }
            }
            const isDifferentiated = hasSchedule && minPayment != null && Math.abs(maxPayment - minPayment) > 10;

            return (
              <Card key={c.id} dark={dark} pad={20} radius={22}>
                <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>
                  <div>
                    <div style={{ fontSize: 11, color: t.muted, fontWeight: 700, letterSpacing: 0.5 }}>
                      {(c.bank || '').toUpperCase()}
                      {isDifferentiated && <span style={{ marginLeft: 8, padding: '2px 6px', borderRadius: 6, background: t.warnSoft, color: dark ? t.warn : '#7A5E1B', fontSize: 9, fontWeight: 800 }}>ДИФФ.</span>}
                      {hasSchedule && !isDifferentiated && <span style={{ marginLeft: 8, padding: '2px 6px', borderRadius: 6, background: t.accentSoft, color: t.accent, fontSize: 9, fontWeight: 800 }}>АННУИТЕТ</span>}
                    </div>
                    <div style={{ fontFamily: TOK.fontDisplay, fontSize: 22, fontWeight: 800, marginTop: 4, color: t.ink, letterSpacing: -0.5 }}>{c.title}</div>
                  </div>
                  <div style={{ display: 'flex', gap: 6, alignItems: 'center' }}>
                    <div style={{ padding: '5px 10px', borderRadius: 10, background: t.surfaceAlt, fontSize: 12, fontWeight: 700, color: t.ink, fontVariantNumeric: 'tabular-nums' }}>{c.rate}%</div>
                    <button onClick={() => setEditing(c.id)} style={{
                      width: 32, height: 32, borderRadius: 10, border: 'none', background: t.surfaceAlt, cursor: 'pointer',
                      display: 'flex', alignItems: 'center', justifyContent: 'center',
                    }} title="Изменить">
                      <Icon d={ICONS.edit} size={15} stroke={t.muted} sw={1.8} />
                    </button>
                  </div>
                </div>

                <div style={{ marginTop: 18, display: 'flex', alignItems: 'baseline', justifyContent: 'space-between' }}>
                  <div>
                    <div style={{ fontSize: 11, color: t.muted, fontWeight: 600 }}>Осталось</div>
                    <div style={{ fontFamily: TOK.fontDisplay, fontSize: 24, fontWeight: 800, color: t.ink, marginTop: 2, letterSpacing: -0.5, fontVariantNumeric: 'tabular-nums' }}>{fmtR(remaining)}</div>
                  </div>
                  <div style={{ textAlign: 'right' }}>
                    <div style={{ fontSize: 11, color: t.muted, fontWeight: 600 }}>{pct}% выплачено</div>
                    <div style={{ fontSize: 12, color: t.muted, marginTop: 2, fontVariantNumeric: 'tabular-nums' }}>{c.years} лет</div>
                  </div>
                </div>

                <div style={{ marginTop: 10, height: 8, background: t.surfaceAlt, borderRadius: 4, overflow: 'hidden' }}>
                  <div style={{ height: '100%', width: `${pct}%`, background: `linear-gradient(90deg, ${t.accent}, ${t.accent}cc)`, borderRadius: 4 }} />
                </div>

                <div style={{ marginTop: 14, padding: '12px 14px', background: t.surfaceAlt, borderRadius: 14, display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
                  <div>
                    <div style={{ fontSize: 11, color: t.muted, fontWeight: 600 }}>Следующий платёж · {nextLabel}</div>
                    <div style={{ fontSize: 12, color: t.muted, marginTop: 2 }}>
                      с карты {linkedAcct ? linkedAcct.bank : '—'}
                      {isDifferentiated && <> · от {fmtR(minPayment)} до {fmtR(maxPayment)} ₽</>}
                    </div>
                  </div>
                  <div style={{ fontFamily: TOK.fontDisplay, fontSize: 17, fontWeight: 800, color: t.ink, fontVariantNumeric: 'tabular-nums' }}>{fmtR(nextAmount)} ₽</div>
                </div>

                {/* Переплата и потенциальная экономия */}
                {(() => {
                  const fut = creditFuturePaymentsTotal(c);
                  if (!fut || fut.total <= 0) return null;
                  const overpay = fut.total - remaining;
                  if (overpay <= 0) return null;
                  return (
                    <div style={{ marginTop: 8, display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 6 }}>
                      <div style={{ padding: '8px 10px', borderRadius: 10, background: 'transparent' }}>
                        <div style={{ fontSize: 10, color: t.muted, fontWeight: 600, lineHeight: 1.2 }}>
                          Переплата процентами<br/>с этого момента
                        </div>
                        <div style={{ fontFamily: TOK.fontDisplay, fontSize: 13, fontWeight: 800, color: t.warn, marginTop: 3, fontVariantNumeric: 'tabular-nums' }}>
                          +{fmtR(overpay)} ₽
                        </div>
                        <div style={{ fontSize: 9, color: t.faint, marginTop: 1 }}>
                          {fut.count} {fut.count === 1 ? 'платёж' : fut.count < 5 ? 'платежа' : 'платежей'} · {fut.source === 'schedule' ? 'по графику' : 'оценка'}
                        </div>
                      </div>
                      <div style={{ padding: '8px 10px', borderRadius: 10, background: t.accentSoft }}>
                        <div style={{ fontSize: 10, color: dark ? t.accent : '#0B6B47', fontWeight: 600, lineHeight: 1.2 }}>
                          Сэкономлю при досрочном<br/>погашении сегодня
                        </div>
                        <div style={{ fontFamily: TOK.fontDisplay, fontSize: 13, fontWeight: 800, color: t.accent, marginTop: 3, fontVariantNumeric: 'tabular-nums' }}>
                          −{fmtR(overpay)} ₽
                        </div>
                        <div style={{ fontSize: 9, color: t.faint, marginTop: 1 }}>
                          если закрыть {fmtR(remaining)} ₽ сейчас
                        </div>
                      </div>
                    </div>
                  );
                })()}

                {isDifferentiated && (
                  <details style={{ marginTop: 10 }}>
                    <summary style={{ fontSize: 11, color: t.accent, fontWeight: 700, cursor: 'pointer' }}>
                      Показать график · {c.paymentSchedule.length} платежей
                    </summary>
                    <div style={{ marginTop: 8, maxHeight: 180, overflowY: 'auto' }}>
                      {c.paymentSchedule.slice(0, 60).map((p, i) => (
                        <div key={i} style={{ display: 'flex', justifyContent: 'space-between', padding: '6px 4px', borderBottom: `1px solid ${t.line}`, fontSize: 12, color: t.ink, fontFamily: TOK.fontMono }}>
                          <span>{p.date}</span>
                          <span style={{ fontVariantNumeric: 'tabular-nums' }}>{fmtR(p.amount)} ₽</span>
                        </div>
                      ))}
                    </div>
                  </details>
                )}
              </Card>
            );
          })}
        </div>

        <input ref={fileRef} type="file" accept="application/pdf,.pdf" style={{ display: 'none' }} onChange={onUploadPdf} />
        <Card dark={dark} pad={20} radius={20} onClick={() => fileRef.current && fileRef.current.click()}
          style={{ marginTop: 14, textAlign: 'center', border: `2px dashed ${t.lineStrong}`, background: t.surfaceAlt, cursor: 'pointer' }}>
          <div style={{ width: 48, height: 48, borderRadius: 14, background: t.accent, color: '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center', margin: '0 auto 10px' }}>
            <Icon d={ICONS.upload} size={22} stroke="#fff" sw={2} />
          </div>
          <div style={{ fontSize: 15, fontWeight: 700, color: t.ink, marginBottom: 4 }}>
            {pdfBusy ? 'AI разбирает PDF…' : 'Загрузить договор PDF'}
          </div>
          <div style={{ fontSize: 12, color: t.muted }}>
            {aiAvailable(settings) ? 'AI извлечёт сумму, ставку, график платежей' : 'Включите AI в настройках'}
          </div>
        </Card>
        {pdfError && (
          <div style={{ marginTop: 10, padding: '10px 14px', borderRadius: 12, background: t.dangerSoft, color: t.danger, fontSize: 12, fontWeight: 600 }}>
            {pdfError}
          </div>
        )}
      </div>

      <EditCreditSheet dark={dark} editingId={typeof editing === 'object' && editing ? '__new' : editing}
        initial={typeof editing === 'object' && editing ? editing : (editing && editing !== '__new' ? credits.find(c => c.id === editing) : null)}
        onClose={() => setEditing(null)} onSave={onSave} />
    </Screen>
  );
}

function EditCreditSheet({ dark, editingId, initial, onClose, onSave }) {
  const t = T(dark);
  const isNew = editingId === '__new' && (!initial || initial.id === '__new');
  const [form, setForm] = React.useState(() => initial || {
    id: '__new', bank: 'Тинькофф', title: 'Новый кредит',
    total: 1000000, paid: 0, rate: 10, monthly: 15000, years: 5,
    nextDate: '01 нояб', accountId: ((DATA.accounts.find(a => a.main) || DATA.accounts[0]) || {}).id,
  });

  React.useEffect(() => {
    if (initial) setForm(initial);
    else if (isNew) setForm({
      id: '__new', bank: 'Тинькофф', title: '', total: 0, paid: 0,
      rate: 10, monthly: 0, years: 5, nextDate: '01 нояб', accountId: ((DATA.accounts.find(a => a.main) || DATA.accounts[0]) || {}).id,
    });
  }, [editingId]);

  if (!editingId) return null;
  const set = (k, v) => setForm(f => ({ ...f, [k]: v }));

  const Field = ({ label, value, onChange, suffix, isNum, placeholder }) => (
    <div style={{ marginBottom: 10 }}>
      <div style={{ fontSize: 11, color: t.muted, fontWeight: 700, textTransform: 'uppercase', letterSpacing: 0.4, marginBottom: 4 }}>{label}</div>
      <div style={{ display: 'flex', alignItems: 'center', gap: 6, background: t.surface, borderRadius: 12, padding: '10px 14px', border: `1px solid ${t.line}` }}>
        <input value={value} placeholder={placeholder}
          onChange={e => onChange(isNum ? (parseFloat(e.target.value) || 0) : e.target.value)}
          inputMode={isNum ? 'decimal' : 'text'}
          style={{ flex: 1, border: 'none', outline: 'none', background: 'transparent', fontFamily: 'inherit',
            fontSize: 15, fontWeight: 600, color: t.ink, fontVariantNumeric: 'tabular-nums', width: '100%' }} />
        {suffix && <div style={{ fontSize: 12, color: t.muted, fontWeight: 600 }}>{suffix}</div>}
      </div>
    </div>
  );

  return (
    <Sheet open={!!editingId} onClose={onClose} dark={dark} title={isNew ? 'Новый кредит' : 'Изменить кредит'} height="92%">
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
        <Field label="Банк" value={form.bank} onChange={v => set('bank', v)} placeholder="Тинькофф" />
        <Field label="Название" value={form.title} onChange={v => set('title', v)} placeholder="Ипотека" />
        <Field label="Сумма всего" value={form.total} onChange={v => set('total', v)} suffix="₽" isNum />
        <Field label="Уже выплачено" value={form.paid} onChange={v => set('paid', v)} suffix="₽" isNum />
        <Field label="Ставка" value={form.rate} onChange={v => set('rate', v)} suffix="%" isNum />
        <Field label="Срок" value={form.years} onChange={v => set('years', v)} suffix="лет" isNum />
        <Field label="Платёж в месяц" value={form.monthly} onChange={v => set('monthly', v)} suffix="₽" isNum />
        <Field label="Следующий" value={form.nextDate} onChange={v => set('nextDate', v)} placeholder="05 нояб" />
      </div>

      <div style={{ fontSize: 11, color: t.muted, fontWeight: 700, textTransform: 'uppercase', letterSpacing: 0.4, margin: '8px 0 6px' }}>Списывать со счёта</div>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 6, marginBottom: 12 }}>
        {DATA.accounts.map(a => (
          <button key={a.id} onClick={() => set('accountId', a.id)} style={{
            padding: '12px 14px', borderRadius: 12, border: `1.5px solid ${form.accountId === a.id ? t.accent : t.line}`,
            background: form.accountId === a.id ? t.accentSoft : t.surface, cursor: 'pointer',
            display: 'flex', alignItems: 'center', gap: 10, fontFamily: 'inherit',
          }}>
            <div style={{ width: 24, height: 24, borderRadius: 6, background: a.color }} />
            <div style={{ flex: 1, textAlign: 'left' }}>
              <div style={{ fontSize: 14, fontWeight: 700, color: t.ink }}>{a.bank} · {a.title}</div>
              <div style={{ fontSize: 11, color: t.muted, marginTop: 2 }}>•• {a.last4}</div>
            </div>
            {form.accountId === a.id && <Icon d={ICONS.check} size={16} stroke={t.accent} sw={2.4} />}
          </button>
        ))}
      </div>

      {form.paymentSchedule && form.paymentSchedule.length > 0 && (
        <details style={{ marginBottom: 12 }}>
          <summary style={{ fontSize: 12, color: t.muted, fontWeight: 700, cursor: 'pointer' }}>
            График платежей · {form.paymentSchedule.length} строк
          </summary>
          <div style={{ marginTop: 8, maxHeight: 200, overflowY: 'auto', fontSize: 12, color: t.ink, fontFamily: TOK.fontMono }}>
            {form.paymentSchedule.slice(0, 60).map((p, i) => (
              <div key={i} style={{ display: 'flex', justifyContent: 'space-between', padding: '4px 8px', borderBottom: `1px solid ${t.line}` }}>
                <span>{p.date}</span>
                <span style={{ fontVariantNumeric: 'tabular-nums' }}>{fmtR(p.amount)} ₽</span>
              </div>
            ))}
          </div>
        </details>
      )}

      <div style={{ display: 'flex', gap: 10, marginTop: 8 }}>
        {!isNew && (
          <button onClick={() => onSave({ ...form, __delete: true })} style={{
            padding: '14px 16px', borderRadius: 14, border: 'none', cursor: 'pointer',
            background: t.dangerSoft, color: t.danger, fontFamily: 'inherit', fontSize: 14, fontWeight: 700,
            display: 'flex', alignItems: 'center', gap: 6,
          }}>
            <Icon d={ICONS.trash} size={16} stroke={t.danger} sw={2} />
            Удалить
          </button>
        )}
        <Btn dark={dark} primary full onClick={() => onSave(form)} icon="check" style={{ flex: 1 }}>
          {isNew ? 'Создать' : 'Сохранить'}
        </Btn>
      </div>
    </Sheet>
  );
}

Object.assign(window, { AddExpenseScreen, AddIncomeScreen, SubscriptionsScreen, CreditsScreen, parseSmartExpense });
