/* ============================================================
   app.jsx — корневой контроллер: навигация, состояние, модалки.
   Монтируется в #root внутри iOS-фрейма.

   Подключён к реальному бэкенду через app/api.js (см. Api.*).
   При старте грузим каталог/кейсы/профиль/инвентарь/задания/историю,
   далее все действия идут через API — фронт только анимирует.
   ============================================================ */
const { useState:useS, useEffect:useE, useRef:useRf } = React;

function App(){
  const [tab,setTab] = useS('cases');
  const [items,setItems] = useS([]);
  const [tasks,setTasks] = useS([]);
  const [bal,setBal] = useS({ ton:0, star:0 });
  const [history,setHistory] = useS([]);
  const [openCase,setOpenCase] = useS(null);
  const [sheet,setSheet] = useS(null);          // 'wallet' | 'topup' | 'ton'
  const [toast,setToast] = useS(null);
  const [dev,setDev] = useS(false);
  const [devSheet,setDevSheet] = useS({ open:false, focus:null });
  const [ready,setReady] = useS(false);
  const [authError,setAuthError] = useS(null);
  const [tonInfo,setTonInfo] = useS(null);

  const devPin = makeDevPin((n)=> setDevSheet({ open:true, focus:n }));

  const flash = (msg)=>{ setToast(msg); clearTimeout(flash._t); flash._t=setTimeout(()=>setToast(null),1900); };
  const addHist = (h)=> setHistory(p=>[{id:'h'+Date.now()+Math.random(), ts:new Date().toISOString(), ...h},...p].slice(0,30));

  // ---- первичная загрузка данных с бэкенда -------------------------------
  useE(()=>{
    initTelegram();
    let cancelled = false;
    (async ()=>{
      try{
        const [gifts, cases, profile, inv, taskList, hist] = await Promise.all([
          Api.getGifts(), Api.getCases(), Api.getProfile(), Api.getInventory(), Api.getTasks(), Api.getHistory(),
        ]);
        if(cancelled) return;

        GIFTS.length = 0; GIFTS.push(...gifts);
        CASES.length = 0; CASES.push(...cases);
        TASKS.length = 0; TASKS.push(...taskList);
        Object.assign(USER, profile);

        setItems(inv.map(it=>({ uid:it.uid, giftId:it.giftId })));
        setTasks(taskList.map(t=>({...t})));
        setBal({ ton: profile.balanceTon, star: profile.balanceStar });
        setHistory(hist.items.map(h=>({...h})));
        setReady(true);
      }catch(err){
        console.error('loadAll error', err);
        setAuthError(err);
      }
    })();
    return ()=>{ cancelled = true; };
  },[]);

  const user = { ...USER, balanceTon:bal.ton, balanceStar:bal.star };

  // ---- кейс: API-розыгрыш, фронт только анимирует ------------------------
  async function spinCase(c, currency){
    const res = await Api.openCase(c.id, currency); // {gift, itemUid, balance}
    setBal({ ton: res.balance.balanceTon, star: res.balance.balanceStar });
    return res;
  }
  function handleWin(win, action, cur, itemUid){
    const c = openCase;
    if(action==='keep'){
      setItems(p=>[{uid:itemUid, giftId:win.id}, ...p]);
      addHist({ kind:'case', label:`Кейс «${c.title}»`, giftId:win.id, delta:'+' });
      flash(`«${win.title}» в инвентаре`);
    } else {
      // продажа сразу после открытия
      Api.sellItem(itemUid).then(res=>{
        setBal(b=>({...b, ton: res.balanceTon}));
        addHist({ kind:'sell', label:'Продажа дропа', giftId:win.id, delta:'ton', amountTon: res.soldFor });
        flash(`Продано за ${res.soldFor} TON`);
      }).catch(()=> flash('Не удалось продать'));
    }
  }

  // ---- инвентарь ----------------------------------------------------------
  async function sellItem(it){
    try{
      const g = giftById(it.giftId);
      const res = await Api.sellItem(it.uid);
      setItems(p=>p.filter(x=>x.uid!==it.uid));
      setBal(b=>({...b, ton: res.balanceTon}));
      addHist({ kind:'sell', label:'Продажа предмета', giftId:g.id, delta:'ton', amountTon: res.soldFor });
      flash(`Продано за ${res.soldFor} TON`);
    }catch(err){
      flash('Ошибка продажи');
    }
  }
  async function withdrawItem(it){
    try{
      await Api.withdrawItem(it.uid);
      const g = giftById(it.giftId);
      setItems(p=>p.filter(x=>x.uid!==it.uid));
      addHist({ kind:'withdraw', label:'Заявка на вывод', giftId:g.id, delta:'out' });
      flash('Заявка на вывод создана');
    }catch(err){
      flash('Ошибка заявки на вывод');
    }
  }

  // ---- апгрейдер: завершение (списание/добавление в инвентарь уже на сервере) --
  function handleUpgrade(result, stakeUids){
    setItems(p=>p.filter(x=>!stakeUids.includes(x.uid)));
    if(result && result.win){
      setItems(p=>[{uid:result.itemUid, giftId:result.gift.id}, ...p]);
      addHist({ kind:'upgrade', label:'Апгрейд', giftId:result.gift.id, delta:'+' });
    } else {
      addHist({ kind:'upgrade', label:'Апгрейд', giftId:null, delta:'lose' });
    }
  }

  // ---- задания --------------------------------------------------------------
  async function claimTask(t){
    try{
      const res = await Api.claimTask(t.id);
      setTasks(p=>p.map(x=>x.id===t.id?{...x,done:true}:x));
      setBal(b=>({...b, star: res.balanceStar}));
      flash(`+${res.reward} ⭐ получено`);
    }catch(err){
      const code = err.body && err.body.error;
      if(code==='not_subscribed') flash('Сначала подпишись на канал');
      else if(code==='already_claimed' || code==='already_claimed_today') flash('Уже получено');
      else flash('Не удалось получить награду');
    }
  }

  // ---- пополнение -------------------------------------------------------
  async function buyStars(amount){
    try{
      const { link } = await Api.starsInvoice(amount);
      if(window.tgWebApp && window.tgWebApp.openInvoice){
        window.tgWebApp.openInvoice(link, async (status)=>{
          if(status==='paid'){
            const b = await Api.getBalance();
            setBal({ ton:b.balanceTon, star:b.balanceStar });
            addHist({ kind:'topup', label:'Пополнение Stars', delta:'star', amountStar: amount });
            flash(`+${amount} ⭐ зачислено`);
          }
        });
      } else {
        window.open(link, '_blank');
      }
    }catch(err){
      flash('Не удалось создать инвойс');
    }
  }
  async function openTonSheet(){
    try{
      const info = await Api.tonDepositInfo();
      setTonInfo(info);
      setSheet('ton');
    }catch(err){
      flash('TON-депозиты пока недоступны');
    }
  }

  const badges = { tasks: tasks.filter(t=>!t.done).length || null };

  // ---- экран ошибки авторизации / загрузки --------------------------------
  if(authError){
    return (
      <div className="app" style={{display:'flex',alignItems:'center',justifyContent:'center',padding:24,textAlign:'center'}}>
        <div>
          <div style={{fontSize:48,marginBottom:12}}>🔒</div>
          <div className="h2" style={{marginBottom:8}}>Не удалось авторизоваться</div>
          <div style={{color:'var(--text-sec)',fontSize:14}}>
            Открой это приложение через кнопку в Telegram-боте — авторизация
            проверяется по данным Telegram WebApp.
          </div>
        </div>
      </div>
    );
  }
  if(!ready){
    return (
      <div className="app" style={{display:'flex',alignItems:'center',justifyContent:'center'}}>
        <div style={{color:'var(--text-sec)',fontSize:14}}>Загрузка…</div>
      </div>
    );
  }

  return (
    <div className="app">
      <TGHeader user={user} dev={dev} devPin={devPin}
        onWallet={()=>setSheet('wallet')} onBalance={()=>setSheet('topup')}/>

      {tab==='cases' && <CasesScreen onOpen={setOpenCase} dev={dev} devPin={devPin}/>}
      {tab==='inventory' && <InventoryScreen items={items} onSell={sellItem} onWithdraw={withdrawItem} dev={dev} devPin={devPin}/>}
      {tab==='upgrade' && <UpgraderScreen items={items} onUpgrade={handleUpgrade} flash={flash} dev={dev} devPin={devPin}/>}
      {tab==='tasks' && <TasksScreen tasks={tasks} onClaim={claimTask} dev={dev} devPin={devPin}/>}
      {tab==='profile' && <ProfileScreen user={user} history={history} onTopup={()=>setSheet('topup')} dev={dev} devPin={devPin}/>}

      <BottomNav tab={tab} setTab={setTab} user={user} badges={badges}/>

      {/* открытие кейса (поверх) */}
      {openCase && <CaseOpenView c={openCase} onClose={()=>setOpenCase(null)}
        onSpin={spinCase} onWin={handleWin} flash={flash} dev={dev} devPin={devPin}/>}

      {/* кошелёк / пополнение */}
      <Sheet open={sheet==='wallet'||sheet==='topup'} onClose={()=>setSheet(null)}>
        <TopupSheet user={user} dev={dev} devPin={devPin}
          onTon={()=>{ setSheet(null); openTonSheet(); }}
          onStar={(amount)=>{ setSheet(null); buyStars(amount); }}/>
      </Sheet>

      {/* TON-депозит: адрес + memo */}
      <Sheet open={sheet==='ton'} onClose={()=>setSheet(null)}>
        <TonDepositSheet info={tonInfo} flash={flash}/>
      </Sheet>

      {/* dev */}
      <div style={{position:'absolute',left:14,bottom:118,zIndex:55,display:'flex',gap:8}}>
        <button className={'dev-fab'+(dev?' on':'')} style={{position:'static'}} onClick={()=>setDev(d=>!d)}>
          <IconCode size={15}/> {dev?'Dev ON':'Dev'}
        </button>
        {dev && (
          <button className="dev-fab on" style={{position:'static'}} onClick={()=>setDevSheet({open:true,focus:null})}>
            Заметки
          </button>
        )}
      </div>
      <DevNotesSheet open={devSheet.open} focus={devSheet.focus} onClose={()=>setDevSheet({open:false,focus:null})}/>

      {/* toast */}
      {toast && (
        <div style={{position:'absolute',left:'50%',bottom:120,transform:'translateX(-50%)',zIndex:60,
          background:'rgba(40,40,44,.96)',backdropFilter:'blur(10px)',color:'#fff',fontWeight:600,fontSize:14,
          padding:'11px 18px',borderRadius:999,boxShadow:'0 10px 30px rgba(0,0,0,.5)',
          animation:'pop .3s var(--ease)',whiteSpace:'nowrap'}}>{toast}</div>
      )}
    </div>
  );
}

// ---- пополнение/кошелёк -------------------------------------------------
function TopupSheet({ user, onTon, onStar, dev, devPin }){
  const [amount,setAmount] = useS(250);
  const presets = [100, 250, 500, 1000];
  return (
    <div style={{position:'relative'}}>
      {dev && devPin(15,{right:2,top:-2})}
      <span className="h2" style={{fontSize:19}}>Пополнить баланс</span>
      <div style={{color:'var(--text-sec)',fontSize:13,margin:'4px 0 16px'}}>
        Текущий баланс: <Price value={user.balanceTon} currency="ton" size={13}/> · <Price value={user.balanceStar} currency="star" size={13}/>
      </div>
      <button className="btn btn-block" style={{background:'var(--surface)',justifyContent:'space-between',
        padding:'0 18px',height:60,marginBottom:11}} onClick={onTon}>
        <span style={{display:'flex',alignItems:'center',gap:11}}>
          <TonGlyph size={26}/><span style={{fontWeight:700}}>Пополнить TON</span>
        </span>
        <span style={{color:'var(--text-sec)',fontSize:13,fontWeight:600}}>TON Connect ›</span>
      </button>

      <div style={{color:'var(--text-sec)',fontSize:13,fontWeight:700,marginBottom:8}}>Купить Stars</div>
      <div style={{display:'grid',gridTemplateColumns:'1fr 1fr 1fr 1fr',gap:7,marginBottom:11}}>
        {presets.map(p=>(
          <button key={p} onClick={()=>setAmount(p)} style={{
            height:42,borderRadius:12,cursor:'pointer',fontFamily:'var(--font)',fontWeight:700,color:'#fff',
            background:amount===p?'var(--accent-soft)':'var(--surface)',
            border:amount===p?'1.5px solid var(--accent)':'1px solid var(--hairline)'}}>
            {p}⭐
          </button>
        ))}
      </div>
      <button className="btn btn-primary btn-block" style={{height:54,gap:9}} onClick={()=>onStar(amount)}>
        <StarGlyph size={20}/> Купить {amount} Stars
      </button>
      <div style={{color:'var(--text-ter)',fontSize:12,marginTop:14,textAlign:'center'}}>
        TON — через TON Connect, Stars — через Telegram invoice (XTR)
      </div>
    </div>
  );
}

// ---- TON депозит (адрес + memo) -----------------------------------------
function TonDepositSheet({ info, flash }){
  if(!info) return null;
  function copy(text){
    navigator.clipboard?.writeText(text);
    flash && flash('Скопировано');
  }
  return (
    <div>
      <span className="h2" style={{fontSize:19}}>Пополнение TON</span>
      <div style={{color:'var(--text-sec)',fontSize:13,margin:'4px 0 16px',lineHeight:1.5}}>
        {info.note}
      </div>
      <div style={{marginBottom:12}}>
        <div style={{color:'var(--text-sec)',fontSize:12,fontWeight:700,marginBottom:5}}>Адрес</div>
        <button className="btn btn-block" style={{background:'var(--surface)',justifyContent:'space-between',
          padding:'0 14px',height:48,fontSize:13,wordBreak:'break-all'}} onClick={()=>copy(info.address)}>
          <span style={{overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap',textAlign:'left'}}>{info.address}</span>
          <span style={{color:'var(--accent)',flex:'0 0 auto',marginLeft:8}}>Copy</span>
        </button>
      </div>
      <div>
        <div style={{color:'var(--text-sec)',fontSize:12,fontWeight:700,marginBottom:5}}>Комментарий (обязательно!)</div>
        <button className="btn btn-block" style={{background:'var(--surface)',justifyContent:'space-between',
          padding:'0 14px',height:48,fontSize:14,fontWeight:800}} onClick={()=>copy(info.comment)}>
          <span>{info.comment}</span>
          <span style={{color:'var(--accent)'}}>Copy</span>
        </button>
      </div>
    </div>
  );
}

// ---- масштабируемый корень (фрейм телефона по центру) -------------------
function Root(){
  const wrapRef = useRf(null);
  useE(()=>{
    const W=402, H=874;
    const fit=()=>{
      const s=Math.min(1, (window.innerWidth-16)/W, (window.innerHeight-16)/H);
      if(wrapRef.current) wrapRef.current.style.transform=`scale(${s})`;
    };
    fit(); window.addEventListener('resize',fit);
    return ()=>window.removeEventListener('resize',fit);
  },[]);
  return (
    <div ref={wrapRef} style={{transformOrigin:'center center'}}>
      <IOSDevice dark width={402} height={874}>
        <App/>
      </IOSDevice>
    </div>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<Root/>);
