// Cart sheet — РЕАЛЬНЫЙ чекаут: по каждому подарку POST /purchase с
// pay_with_balance (списание с внутреннего ₽-баланса) → поллинг всех заказов
// до success/failed. Дизайн-экраны прежние + прогресс и partial-fail.
// NB: внешняя платёжка (invoice_url/_openPayUrl) здесь НЕ используется — чекаут
// балансовый; оплата картой при нехватке баланса была бы отдельным путём.

function CartRow({ item, onRemove }) {
  return (
    <div className="row aic gap-10" style={{
      padding: '10px 12px', borderRadius: 14,
      background: 'var(--bg-input)',
      border: '0.5px solid var(--border)',
    }}>
      <div style={{
        position: 'relative', width: 52, height: 52,
        borderRadius: 12, overflow: 'hidden', flexShrink: 0,
      }}>
        <GiftMedia kind={item.kind} num={item.num} rounded={12} photo={item.photo}/>
      </div>
      <div className="flex1 col" style={{ minWidth: 0 }}>
        <div style={{ fontSize: 14, fontWeight: 650, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{item.name}</div>
        {item.num != null && <div className="small t-mute mono">#{item.num.toLocaleString('ru-RU')}</div>}
        <div className="mono" style={{ fontSize: 13, fontWeight: 700, marginTop: 2 }}>{fmtRub(item.rub)}</div>
      </div>
      <button onClick={() => onRemove(item.id)} style={{
        border: 0, background: 'var(--bg-input)', color: 'var(--text-mute)',
        width: 30, height: 30, borderRadius: 8,
        cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center',
      }}>
        <Icons.close size={14}/>
      </button>
    </div>
  );
}

function CartSheet({ cart, balance, onClose, onRemove, onCheckout, onBrowseMore, onSuccess }) {
  const [stage, setStage] = React.useState('list'); // list | processing | success | error
  const [note, setNote] = React.useState('');
  const [okItems, setOkItems] = React.useState([]);
  const [failItems, setFailItems] = React.useState([]);
  const total = cart.reduce((s, i) => s + i.rub, 0);
  const stopRef = React.useRef(false);
  React.useEffect(() => () => { stopRef.current = true; }, []);

  // Snapshot the cart at the moment we begin processing so the processing /
  // success cards keep showing the items even after the parent clears the cart.
  const purchasedRef = React.useRef([]);
  const purchasedItems = stage === 'list' ? cart : purchasedRef.current;
  const purchasedTotal = purchasedItems.reduce((s, i) => s + i.rub, 0);

  const startCheckout = async () => {
    const DS = window.DataSource;
    const items = cart.slice();
    purchasedRef.current = items;
    setOkItems([]); setFailItems([]);
    setStage('processing');

    if (!DS || !DS.purchase) {
      // Прод в Telegram без DataSource — НЕ имитируем успех (иначе «куплено» без покупки).
      if (window.Telegram && window.Telegram.WebApp && window.Telegram.WebApp.initData) {
        setFailItems(items.map(it => ({ item: it, err: 'сервис недоступен' })));
        setStage('error'); return;
      }
      setTimeout(() => { setOkItems(items); setStage('success'); }, 1900);  // дизайн-симулятор
      return;
    }

    // 1) Создаём счета ПОСЛЕДОВАТЕЛЬНО (Portals душит параллель) и оплачиваем.
    const orders = [];
    const failed = [];
    for (let i = 0; i < items.length; i++) {
      if (stopRef.current) return;
      const item = items[i];
      setNote(`Оплата ${i + 1} из ${items.length}: ${item.name}…`);
      try {
        // Списание с ₽-баланса — заказ сразу в processing, поллим ниже.
        const inv = await DS.purchase(item, true);
        orders.push({ item, inv });
      } catch (e) {
        failed.push({ item, err: window.friendlyError ? window.friendlyError(e, 'cart') : 'не получилось' });
      }
    }

    // 2) Поллим все заказы до терминального статуса (до 10 минут суммарно).
    const done = [];
    let pending = orders.slice();
    const deadline = Date.now() + 10 * 60 * 1000;
    while (pending.length && !stopRef.current && Date.now() < deadline) {
      await new Promise(r => setTimeout(r, 4000));
      if (stopRef.current) return;
      setNote(`Оплачено ${done.length} из ${orders.length}, ждём подтверждения…`);
      const still = [];
      for (const o of pending) {
        let st = null;
        try { st = await DS.getOrder(o.inv.order_id); } catch (_) { still.push(o); continue; }
        if (st.status === 'success') done.push(o.item);
        else if (st.status === 'failed') {
          try { console.warn('[cart] order failed:', st.error_msg); } catch (_) {}
          failed.push({ item: o.item, err: 'оплата не прошла' });
        }
        else still.push(o);
      }
      pending = still;
    }
    // По таймауту оставшиеся считаем «в обработке» — они доедут в «Мои подарки».
    pending.forEach(o => done.push(o.item));

    if (stopRef.current) return;
    setOkItems(done);
    setFailItems(failed);
    if (done.length > 0) setStage('success');
    else setStage('error');
  };

  // Commit the purchase the instant we transition into 'success' — clearing
  // the parent's cart and hiding bought listings from the market.
  React.useEffect(() => {
    if (stage === 'success' && typeof onSuccess === 'function' && okItems.length) {
      onSuccess(okItems);
    }
    if (stage === 'success' && window.SFX) window.SFX.success();
  }, [stage]);

  if (cart.length === 0 && stage === 'list') {
    return (
      <SheetShell onClose={onClose}>
        <div className="col aic" style={{ alignItems: 'center', textAlign: 'center', padding: '20px 16px 8px' }}>
          <div style={{
            width: 72, height: 72, borderRadius: 22,
            background: 'var(--bg-input)', display: 'flex', alignItems: 'center', justifyContent: 'center',
            color: 'var(--text-mute)',
          }}>
            <Icons.cart size={32}/>
          </div>
          <div className="h2" style={{ marginTop: 16 }}>Корзина пуста</div>
          <div className="t-soft body" style={{ marginTop: 6, maxWidth: 260 }}>
            Добавь подарки из маркета — здесь они подождут оплаты одной транзакцией.
          </div>
          <WithSheetClose>{close => (
            <button className="btn btn-primary center" style={{
              justifyContent: 'center', padding: '14px',
              alignSelf: 'stretch', marginTop: 22, fontSize: 15, fontWeight: 650,
            }} onClick={() => { close(); setTimeout(() => onBrowseMore?.(), 320); }}>
              <Icons.grid size={16}/> В маркет
            </button>
          )}</WithSheetClose>
        </div>
      </SheetShell>
    );
  }

  return (
    <SheetShell onClose={onClose} dismissable={stage !== 'processing'}>
      {stage === 'list' && (
        <>
          <div className="row aic jcsb" style={{ marginBottom: 12, padding: '0 2px' }}>
            <div className="h2">Корзина <span className="mono t-mute" style={{ fontWeight: 600, fontSize: 18 }}>·{cart.length}</span></div>
            <div className="small t-mute">Баланс: <span className="mono" style={{ color: 'var(--text)', fontWeight: 600 }}>{fmtRub(balance)}</span></div>
          </div>

          <div className="col gap-6" style={{ maxHeight: 280, overflowY: 'auto', marginRight: -4, paddingRight: 4 }}>
            {cart.map(item => (
              <CartRow key={item.id} item={item} onRemove={onRemove}/>
            ))}
          </div>

          <div style={{
            marginTop: 14, padding: '14px 16px',
            borderRadius: 16,
            background: 'var(--bg-input)',
            border: '0.5px solid var(--border)',
          }}>
            <div className="row aic jcsb">
              <div className="small t-soft">Подарков</div>
              <div className="mono small" style={{ fontWeight: 600 }}>{cart.length}</div>
            </div>
            <div style={{ height: 0.5, background: 'var(--border)', margin: '10px 0' }}/>
            <div className="row aic jcsb">
              <div style={{ fontSize: 15, fontWeight: 600 }}>Итого</div>
              <div className="mono" style={{ fontSize: 22, fontWeight: 700 }}>{fmtRub(total)}</div>
            </div>
          </div>

          <div className="col gap-8" style={{ marginTop: 14 }}>
            <button className="btn btn-primary center"
                    disabled={balance < total}
                    onClick={startCheckout}
                    style={{
                      justifyContent: 'center', padding: '15px',
                      fontSize: 16, fontWeight: 650,
                      opacity: balance >= total ? 1 : 0.5,
                    }}>
              <Icons.cart size={17}/> {balance >= total
                ? `Оплатить ${cart.length} подарк${cart.length === 1 ? '' : cart.length < 5 ? 'а' : 'ов'}`
                : 'Недостаточно средств'}
            </button>
            {balance < total && (
              <div className="small t-mute" style={{ textAlign: 'center', lineHeight: 1.5 }}>
                Пополни ещё на{' '}
                <span className="mono" style={{ color: 'var(--text)', fontWeight: 700 }}>{fmtRub(total - balance)}</span>
                {' '}в разделе Кошелёк
              </div>
            )}
          </div>
        </>
      )}

      {stage === 'processing' && (
        <div className="col aic" style={{ alignItems: 'center', textAlign: 'center', padding: '24px 16px 24px' }}>
          <div style={{
            display: 'flex', flexWrap: 'wrap', gap: 12,
            justifyContent: 'center', maxWidth: 280,
          }}>
            {purchasedItems.slice(0, 6).map((item, i) => (
              <div key={item.id} style={{
                width: 76, height: 76, borderRadius: 18, overflow: 'hidden',
                position: 'relative',
                boxShadow: '0 6px 20px rgba(0,0,0,0.35)',
                animation: `fadeUp 0.4s ${i * 0.06}s both`,
              }}>
                <GiftMedia kind={item.kind} num={item.num} rounded={18} photo={item.photo}/>
              </div>
            ))}
          </div>
          <div className="h2" style={{ marginTop: 22 }}>Оплачиваем покупку…</div>
          <div className="t-soft body" style={{ marginTop: 6 }}>
            {note || `${purchasedItems.length} подарк${purchasedItems.length === 1 ? '' : purchasedItems.length < 5 ? 'а' : 'ов'} на ${fmtRub(purchasedTotal)}`}
          </div>
          <div className="bar" style={{ alignSelf: 'stretch', marginTop: 22 }}>
            <div style={{ width: '100%', animation: 'fillBar 1.9s cubic-bezier(0.4, 0, 0.2, 1) infinite' }}/>
          </div>
        </div>
      )}

      {stage === 'error' && (
        <div className="col aic" style={{ alignItems: 'center', textAlign: 'center', padding: '24px 16px 8px' }}>
          <div style={{
            width: 72, height: 72, borderRadius: 22,
            background: 'var(--bg-input)', display: 'flex', alignItems: 'center', justifyContent: 'center',
            color: 'var(--red, #e25555)',
          }}>
            <Icons.close size={32}/>
          </div>
          <div className="h2" style={{ marginTop: 16, color: 'var(--red, #e25555)' }}>Не получилось</div>
          <div className="t-soft body" style={{ marginTop: 6, maxWidth: 280 }}>
            К сожалению, оплатить сейчас не получилось. Подарки остались в корзине — попробуй через минуту.
          </div>
          <div className="col gap-8" style={{ alignSelf: 'stretch', marginTop: 22 }}>
            <button className="btn btn-primary center" style={{
              justifyContent: 'center', padding: '14px', fontSize: 15, fontWeight: 650,
            }} onClick={() => setStage('list')}>
              <Icons.refresh size={16}/> Вернуться в корзину
            </button>
          </div>
        </div>
      )}

      {stage === 'success' && (
        <div className="col aic" style={{ alignItems: 'center', textAlign: 'center', padding: '24px 16px 8px', position: 'relative' }}>
          <Confetti/>
          <div style={{
            display: 'flex', flexWrap: 'wrap', gap: 12,
            justifyContent: 'center', maxWidth: 280, position: 'relative', zIndex: 1,
          }}>
            {okItems.slice(0, 6).map((item, i) => (
              <div key={item.id} style={{
                width: 84, height: 84, borderRadius: 20, overflow: 'hidden',
                position: 'relative',
                boxShadow: '0 8px 24px rgba(0,0,0,0.4)',
                animation: `fadeUp 0.5s ${i * 0.08}s both`,
              }}>
                <GiftMedia kind={item.kind} num={item.num} rounded={20} photo={item.photo}/>
              </div>
            ))}
          </div>
          <div style={{ fontSize: 22, fontWeight: 700, letterSpacing: '-0.015em', marginTop: 22 }}>
            Готово! 🎉
          </div>
          <div className="t-soft body" style={{ marginTop: 6 }}>
            {okItems.length} подарк{okItems.length === 1 ? '' : okItems.length < 5 ? 'а' : 'ов'} добавлено в твою коллекцию
          </div>
          {failItems.length > 0 && (
            <div className="small" style={{ color: 'var(--red, #e25555)', marginTop: 8, maxWidth: 280 }}>
              Не удалось: {failItems.map(f => f.item.name).join(', ')}
            </div>
          )}
          <div className="col gap-8" style={{ alignSelf: 'stretch', marginTop: 22 }}>
            <WithSheetClose>{close => (
              <button className="btn btn-primary center" style={{
                justifyContent: 'center', padding: '14px', fontSize: 15, fontWeight: 650,
              }} onClick={() => { close(); setTimeout(() => onCheckout('goto'), 320); }}>
                <Icons.box size={16}/> Перейти в Мои подарки
              </button>
            )}</WithSheetClose>
            <WithSheetClose>{close => (
              <button className="btn center" style={{
                justifyContent: 'center', padding: '12px', fontSize: 14,
              }} onClick={() => { close(); setTimeout(() => onCheckout('continue'), 320); }}>
                Продолжить покупки
              </button>
            )}</WithSheetClose>
          </div>
        </div>
      )}
    </SheetShell>
  );
}

window.CartSheet = CartSheet;
