const state = {
  token: '',
  authConfig: null,
  authenticated: false,
  authMode: 'login',
  verificationEmail: '',
  verificationCode: '',
  resetEmail: '',
  resetToken: '',
  resetSent: false,
  verificationDeliveryError: '',
  wallets: [],
  presaleSummary: null,
  recoveryToken: '',
  walletConfirmation: null,
  page: location.hash.replace('#', '') || 'home',
  config: null,
  site: null,
  payments: null,
  game: null,
  quests: [],
  referrals: null,
  wallet: null,
  leaderboard: [],
  vip: null,
  wheel: null,
  pendingTaps: 0,
  tapTimer: null,
  tapSending: false,
  wheelRotation: 0,
  wheelSpinning: false,
  wheelRequestKey: '',
  ad: null
};

const app = document.querySelector('#app');
const toastRoot = document.querySelector('#toast-root');
const modalRoot = document.querySelector('#modal-root');

const fmt = new Intl.NumberFormat('tr-TR');
const money = (value) => fmt.format(Math.max(0, Number(value || 0)));
const escapeHtml = (value) => String(value ?? '').replace(/[&<>'"]/g, (char) => ({ '&':'&amp;', '<':'&lt;', '>':'&gt;', "'":'&#39;', '"':'&quot;' }[char]));
const idempotency = () => crypto.randomUUID();

function currencyDecimals(code) {
  if (code === 'USDT') return 6;
  return Number(state.payments?.currencies?.find((item) => item.code === code)?.decimals ?? 2);
}

function formatPaymentAmount(amountMinor, code) {
  const decimals = currencyDecimals(code);
  const value = Number(amountMinor || 0) / (10 ** decimals);
  const symbol = state.payments?.currencies?.find((item) => item.code === code)?.symbol || code;
  return `${new Intl.NumberFormat('tr-TR', { minimumFractionDigits: 0, maximumFractionDigits: Math.min(decimals, 8) }).format(value)} ${symbol}`;
}

function vipPricesForTier(tier) {
  return (state.payments?.vipPrices || []).filter((row) => Number(row.tier) === Number(tier) && row.enabled);
}

function toast(message, type = 'success') {
  const el = document.createElement('div');
  el.className = `toast ${type}`;
  el.textContent = message;
  toastRoot.appendChild(el);
  setTimeout(() => el.remove(), 3600);
}

async function api(path, { method = 'GET', body, idempotencyKey, auth = true } = {}) {
  const headers = { 'Content-Type': 'application/json', 'X-Request-ID': crypto.randomUUID() };
  if (idempotencyKey) headers['Idempotency-Key'] = idempotencyKey;
  const response = await fetch(path, { method, headers, credentials: 'same-origin', body: body == null ? undefined : JSON.stringify(body) });
  const data = await response.json().catch(() => ({}));
  if (!response.ok) {
    const error = new Error(data.message || 'İşlem tamamlanamadı.');
    error.code = data.code;
    error.details = data.details;
    throw error;
  }
  return data;
}

function referralCodeFromContext() {
  const query = new URLSearchParams(location.search);
  const telegramStart = window.Telegram?.WebApp?.initDataUnsafe?.start_param || '';
  return query.get('ref') || telegramStart || localStorage.getItem('oc_ref') || '';
}

async function authenticate() {
  const query = new URLSearchParams(location.search);
  const resetToken = query.get('reset_token');
  const resetEmail = query.get('email');
  if (resetToken && resetEmail) {
    state.resetToken = resetToken;
    state.resetEmail = resetEmail;
    state.authMode = 'reset-confirm';
    return false;
  }
  const loginCode = query.get('login_code');
  if (loginCode) {
    await api('/api/auth/oauth/exchange', { method: 'POST', auth: false, body: { code: loginCode } });
    query.delete('login_code');
    history.replaceState({}, '', `${location.pathname}${query.toString() ? `?${query}` : ''}${location.hash}`);
  }
  try {
    await api('/api/game/state');
    state.authenticated = true;
    return true;
  } catch (error) {
    if (!['AUTH_REQUIRED', 'SESSION_EXPIRED', 'SESSION_REVOKED'].includes(error.code)) throw error;
  }
  const referralCode = referralCodeFromContext();
  if (referralCode) localStorage.setItem('oc_ref', referralCode);
  const initData = window.Telegram?.WebApp?.initData;
  if (initData) {
    window.Telegram.WebApp.ready();
    window.Telegram.WebApp.expand();
    await api('/api/auth/telegram', { method: 'POST', auth: false, body: { initData, referralCode } });
    state.authenticated = true;
    return true;
  }
  return false;
}

function authScreen() {
  const providers = state.authConfig?.providers || [];
  const deliveryWarning = state.verificationDeliveryError ? `<div class="auth-warning">${escapeHtml(state.verificationDeliveryError)}</div>` : '';
  const verification = state.verificationEmail ? `<form id="verify-email-form" class="auth-form"><div class="auth-icon">✉</div><h2>E-postanı Doğrula</h2><p><b>${escapeHtml(state.verificationEmail)}</b> adresine gönderilen 6 haneli kodu girin.</p>${deliveryWarning}<input class="input" name="code" inputmode="numeric" maxlength="6" placeholder="Doğrulama kodu" required><button class="primary full-button">Doğrula ve Giriş Yap</button><button type="button" class="text-button" data-action="resend-verification">Kodu yeniden gönder</button></form>` : '';
  let form;
  if (state.authMode === 'register') {
    form = `<form id="register-form" class="auth-form"><h2>OnlyCoin Hesabı Oluştur</h2><p>Presale, oyun bakiyesi ve cüzdan işlemleri için tek hesap.</p><input class="input" name="displayName" maxlength="60" placeholder="Ad Soyad" required><input class="input" name="username" maxlength="32" placeholder="Kullanıcı adı" required><input class="input" name="email" type="email" placeholder="E-posta" required><input class="input" name="password" type="password" minlength="12" placeholder="Güçlü parola" required><input class="input" name="confirmPassword" type="password" minlength="12" placeholder="Parolayı doğrula" required><label class="auth-check"><input type="checkbox" name="terms" required><span>Kullanım koşullarını ve presale risk açıklamasını okudum.</span></label><button class="primary full-button">Kayıt Ol</button></form>`;
  } else if (state.authMode === 'reset') {
    form = `<form id="password-request-form" class="auth-form"><h2>Parola Yenile</h2><p>E-posta adresinize tek kullanımlık parola yenileme bağlantısı gönderilir.</p><input class="input" name="email" type="email" value="${escapeHtml(state.resetEmail)}" placeholder="E-posta" required><button class="primary full-button">Yenileme Bağlantısı Gönder</button><button type="button" class="text-button" data-action="auth-mode" data-mode="login">Girişe dön</button></form>`;
  } else if (state.authMode === 'reset-sent') {
    form = `<div class="auth-form"><div class="auth-icon">✉</div><h2>E-postanızı Kontrol Edin</h2><p>Hesap mevcutsa parola yenileme bağlantısı <b>${escapeHtml(state.resetEmail)}</b> adresine gönderildi.</p><button type="button" class="primary full-button" data-action="auth-mode" data-mode="login">Giriş Ekranına Dön</button></div>`;
  } else if (state.authMode === 'reset-confirm') {
    form = `<form id="password-reset-form" class="auth-form"><h2>Yeni Parola Belirle</h2><input class="input" name="email" type="email" value="${escapeHtml(state.resetEmail)}" readonly><input type="hidden" name="token" value="${escapeHtml(state.resetToken)}"><input class="input" name="password" type="password" minlength="12" placeholder="Yeni güçlü parola" required><input class="input" name="confirmPassword" type="password" minlength="12" placeholder="Yeni parolayı doğrula" required><button class="primary full-button">Parolayı Güncelle</button></form>`;
  } else {
    form = `<form id="login-form" class="auth-form"><h2>Hesabına Giriş Yap</h2><p>OnlyCoin oyununa, presale paneline ve cüzdanına eriş.</p><input class="input" name="email" type="email" placeholder="E-posta" required><input class="input" name="password" type="password" placeholder="Parola" required><button class="primary full-button">Giriş Yap</button><button type="button" class="text-button" data-action="auth-mode" data-mode="reset">Parolamı unuttum</button></form>`;
  }
  const social = providers.length ? `<div class="auth-divider"><span>veya</span></div><div class="social-login-grid">${providers.map((provider) => `<button class="social-login" data-action="social-login" data-provider="${escapeHtml(provider.id)}"><span>${provider.id === 'google' ? 'G' : provider.id === 'apple' ? '' : provider.id === 'facebook' ? 'f' : provider.id === 'x' ? '𝕏' : 'OC'}</span>${escapeHtml(provider.name)}</button>`).join('')}</div>` : '';
  const tabs = ['login','register'].includes(state.authMode) ? `<div class="auth-tabs"><button class="${state.authMode === 'login' ? 'active' : ''}" data-action="auth-mode" data-mode="login">Giriş</button><button class="${state.authMode === 'register' ? 'active' : ''}" data-action="auth-mode" data-mode="register">Kayıt</button></div>` : '';
  app.innerHTML = `<div class="auth-page"><div class="auth-brand"><img src="/game/assets/onlycoin-token.png" alt="OnlyCoin"><span>ONLYCOIN</span><small>TAP · PRESALE · WALLET</small></div><section class="card auth-card">${verification || `${tabs}${form}${['login','register'].includes(state.authMode) ? social : ''}`}</section><p class="auth-foot">Cüzdan parolası ve private key e-posta ile gönderilmez. Anahtarlar yalnızca şifreli kurtarma paketiyle kullanıcıya teslim edilir.</p></div>`;
}

async function finishUserLogin(result) {
  state.authenticated = true;
  state.verificationEmail = '';
  await refreshAll();
}

function countdownParts() {
  const target = new Date(state.config?.launchAt || Date.now()).getTime();
  const diff = Math.max(0, target - Date.now());
  const total = Math.floor(diff / 1000);
  return {
    done: diff <= 0,
    days: Math.floor(total / 86400),
    hours: Math.floor((total % 86400) / 3600),
    minutes: Math.floor((total % 3600) / 60),
    seconds: total % 60
  };
}

function countdownHtml() {
  const c = countdownParts();
  if (c.done) return '<b>Lansman başladı</b>';
  return `<span>${String(c.days).padStart(2,'0')}G</span><span>${String(c.hours).padStart(2,'0')}S</span><span>${String(c.minutes).padStart(2,'0')}D</span><span>${String(c.seconds).padStart(2,'0')}SN</span>`;
}

function updateCountdowns() {
  document.querySelectorAll('[data-countdown]').forEach((node) => { node.innerHTML = countdownHtml(); });
}

function navHtml() {
  const items = [
    ['home','⌂','Ana Sayfa'],
    ['wheel','◉','Çark'],
    ['quests','▣','Görevler'],
    ['friends','♟','Arkadaşlar'],
    ['wallet','▰','Cüzdan']
  ];
  return `<nav class="bottom-nav">${items.map(([page, icon, label]) => `<button class="${state.page===page?'active':''}" data-page="${page}" aria-label="${label}"><span class="nav-icon">${icon}</span><span>${label}</span></button>`).join('')}</nav>`;
}

function shell(content, title = '', subtitle = '') {
  const user = state.game?.user || {};
  const announcement = state.config?.announcement || '';
  return `
    <div class="global-countdown"><span>${escapeHtml(state.config?.launchMessage || 'Lansmana kalan süre')}</span><b class="countdown-parts" data-countdown>${countdownHtml()}</b></div>
    <header class="topbar">
      <button class="avatar-button" data-page="profile" aria-label="Profil">🦁</button>
      <div class="brand"><img src="/game/assets/onlycoin-token.png" alt=""><strong>ONLYCOIN</strong></div>
      <button class="icon-button" data-page="profile" aria-label="Ayarlar">⚙</button>
    </header>
    ${title ? `<div class="page-title"><h1>${escapeHtml(title)}</h1>${subtitle?`<p>${escapeHtml(subtitle)}</p>`:''}</div>`:''}
    ${announcement ? `<div class="announcement"><span>✦</span><span>${escapeHtml(announcement)}</span></div>` : ''}
    <main class="content">${content}</main>
    ${navHtml()}
  `;
}

function homePage() {
  const g = state.game;
  const energyPercent = Math.min(100, Math.round(g.state.energy / g.state.energyCapacity * 100));
  const booster = g.state.activeBooster;
  return shell(`
    <section class="card balance-card">
      <div class="balance-label">Toplam OC_POINTS</div>
      <div class="balance-number" id="points-balance">${money(g.balances.OC_POINTS)}</div>
      <div class="balance-sub">+${money(g.state.autoPointsPerHour)} OC_POINTS / saat</div>
      <div class="token-badge">OC_TOKEN: <b>${money(g.balances.OC_TOKEN)}</b> · Dönüşüm oranı %${state.config.conversion.ratePercent}</div>
    </section>
    <section class="tap-stage">
      <div class="combo-pill">KOMBO<b id="combo-value">x1.0</b><span id="tap-queue">Hazır</span></div>
      <button class="tap-coin" data-action="tap" aria-label="Dokun ve kazan"><img src="/game/assets/onlycoin-token.png" alt="OnlyCoin"></button>
      <div class="tap-caption">Dokun ve Kazan</div>
    </section>
    <section class="card stats-grid">
      <div class="stat"><small>Enerji</small><strong>${money(g.state.energy)} / ${money(g.state.energyCapacity)}</strong><div class="energy-bar"><i style="width:${energyPercent}%"></i></div></div>
      <div class="stat"><small>Tap Gücü</small><strong>${money(g.state.tapReward)} OC</strong><em>VIP ${g.state.vipTier || 0}</em></div>
      <div class="stat"><small>Otomatik Kazanç</small><strong>${money(g.state.autoPointsPerHour)}/s</strong><em>Seviye ${g.state.level}</em></div>
    </section>
    <section class="quick-grid">
      <button class="quick-action" data-page="vip"><span class="emoji">♛</span><strong>VIP</strong><span>Daha fazla kazan</span></button>
      <button class="quick-action" data-page="wheel"><span class="emoji">◉</span><strong>ÇARK</strong><span>Ücretsiz / reklam / ücretli</span></button>
      <button class="quick-action" data-page="quests"><span class="emoji">▣</span><strong>GÖREVLER</strong><span>Ödülleri topla</span></button>
      <button class="quick-action" data-page="friends"><span class="emoji">♟</span><strong>DAVET</strong><span>Birlikte kazan</span></button>
    </section>
    <section class="mini-grid">
      <div class="card mini-card"><small>Günlük Seri</small><strong>${g.state.streakDays} Gün</strong><p>Her gün giriş yaparak serini koru.</p></div>
      <div class="card mini-card"><small>Ücretsiz Ödül</small><strong>+250 OC</strong><p>Ödüllü reklamı tamamla.</p><button class="primary full-button" data-action="watch-ad">Reklam İzle</button></div>
      <div class="card mini-card"><small>Aktif Booster</small><strong class="${booster?'green':''}">${booster ? `x${booster.multiplier}` : 'Yok'}</strong><p>${booster ? new Date(booster.expiresAt).toLocaleTimeString('tr-TR') + ' saatine kadar' : 'Çarktan veya marketten kazan.'}</p></div>
    </section>
    <div class="section-head"><h2>Günlük Görevler</h2><button data-page="quests">Tümünü Gör ›</button></div>
    <section id="home-quests" class="quest-list">${questsPreview()}</section>
    <section class="card event-banner">
      <small>ÖZEL ETKİNLİK</small><h3>ALTIN YAĞMURU</h3><p>Daha fazla dokun, daha fazla OC_POINTS kazan. VIP çarpanını yükselt.</p><span class="chest">🧰</span><button class="primary" data-page="vip">Hemen Katıl</button>
    </section>
    <div class="section-head"><h2>Topluluk</h2><button data-page="leaderboard">Liderlik ›</button></div>
  `);
}

function questsPreview() {
  if (!state.quests.length) return '<div class="empty card">Görevler yükleniyor…</div>';
  return state.quests.slice(0,3).map(questCard).join('');
}

function wheelGradient(segments) {
  if (!segments.length) return '#17140d';
  const angle = 360 / segments.length;
  return `conic-gradient(from 0deg, ${segments.map((segment, index) => {
    const start = index * angle;
    const end = (index + 1) * angle;
    return `${segment.color || (index % 2 ? '#17150f' : '#2a2110')} ${start}deg ${end}deg`;
  }).join(',')})`;
}

function wheelIcon(type) {
  return ({ points:'OC', energy:'ϟ', booster:'➤', vip_trial:'♛', ad_spin:'▶' })[type] || '✦';
}

function wheelLabels(segments) {
  if (!segments.length) return '';
  const angle = 360 / segments.length;
  return segments.map((segment, index) => {
    const center = index * angle + angle / 2;
    return `<span class="wheel-label" style="--segment-angle:${center}deg"><i>${wheelIcon(segment.reward_type)}</i><b>${escapeHtml(segment.label)}</b></span>`;
  }).join('');
}

function wheelPage() {
  const segments = state.wheel?.segments || state.config.wheelSegments || [];
  const paidCost = state.wheel?.paidSpinCost || state.config.game.paidSpinCost;
  const status = state.wheel?.state?.state?.wheel || state.game?.state?.wheel || {};
  const freeRemaining = Number(status.freeSpinsRemaining ?? state.config.game.wheelDailyFreeSpins ?? 3);
  const totalRemaining = Number(status.totalSpinsRemaining ?? state.config.game.wheelDailyTotalLimit ?? 10);
  const adCredits = Number(status.adSpinCredits ?? state.game?.state?.adSpinCredits ?? 0);
  const disabled = state.wheelSpinning || totalRemaining <= 0;
  return shell(`
    <section class="wheel-hero card">
      <div class="wheel-status-row">
        <div><small>Ücretsiz Hak</small><strong>${freeRemaining} / ${status.freeSpinsAllowed ?? freeRemaining}</strong></div>
        <div><small>Günlük Toplam</small><strong>${totalRemaining} Kaldı</strong></div>
        <div><small>Reklam Hakkı</small><strong>${adCredits}</strong></div>
      </div>
      <div class="wheel-machine ${state.wheelSpinning ? 'is-spinning' : ''}" aria-busy="${state.wheelSpinning ? 'true' : 'false'}">
        <div class="wheel-pointer" aria-hidden="true"><span></span></div>
        <div class="wheel-light-ring" aria-hidden="true"></div>
        <div class="wheel-wrap">
          <div id="lucky-wheel" class="wheel" style="--wheel-gradient:${wheelGradient(segments)};transform:rotate(${state.wheelRotation}deg)">
            <div class="wheel-dividers" style="--segment-count:${Math.max(1, segments.length)}"></div>
            ${wheelLabels(segments)}
            <div class="wheel-center"><img src="/game/assets/onlycoin-token.png" alt="OC"><span>ÇEVİR</span></div>
          </div>
        </div>
        <div class="wheel-floor" aria-hidden="true"></div>
      </div>
      <div class="spin-progress ${state.wheelSpinning ? 'active' : ''}"><i></i><span>${state.wheelSpinning ? 'Çark dönüyor… Sonuç bekleniyor' : 'İğne sabit, yalnızca ödül diski döner'}</span></div>
      <div class="spin-options">
        <div class="card spin-option"><small>Ücretsiz Çevirme</small><strong>${freeRemaining} Hak Kaldı</strong><button class="primary full-button" data-action="spin" data-mode="free" ${disabled || freeRemaining <= 0 ? 'disabled' : ''}>${state.wheelSpinning ? 'Dönüyor…' : 'Ücretsiz Çevir'}</button></div>
        <div class="card spin-option"><small>OC_POINTS ile</small><strong>${money(paidCost)} OC_POINTS</strong><button class="secondary full-button" data-action="spin" data-mode="points" ${disabled ? 'disabled' : ''}>Puanla Çevir</button></div>
        ${state.config.game?.adSpinEnabled ? `<div class="card spin-option"><small>Reklam Hakkı</small><strong>${adCredits} Kullanılabilir</strong><button class="secondary full-button" data-action="${adCredits > 0 ? 'spin' : 'watch-ad'}" ${adCredits > 0 ? 'data-mode="ad"' : ''} ${disabled ? 'disabled' : ''}>${adCredits > 0 ? 'Hakkı Kullan' : 'Reklam İzle'}</button></div>` : ''}
      </div>
      <div class="lock-notice" style="margin-top:10px">Peş peşe tıklama hem arayüzde hem sunucuda engellenir. Hak tüketimi ve ödül tek bir atomik transaction içinde yazılır.</div>
    </section>
    <div class="section-head"><h2>Olası Ödüller</h2><span class="wheel-limit-note">Admin yönetimli</span></div>
    <section class="wheel-prize-grid">${segments.map((segment)=>`<div class="card wheel-prize"><span style="--prize-color:${segment.color || '#d9a928'}">${wheelIcon(segment.reward_type)}</span><div><small>${escapeHtml(segment.reward_type)}</small><strong>${escapeHtml(segment.label)}</strong><p>Ağırlık: ${segment.weight}</p></div></div>`).join('')}</section>
  `, 'Şans Çarkı', 'Günlük hak, toplam limit, bekleme süresi ve ödüller yönetim panelinden belirlenir.');
}

function questIcon(type) {
  return ({ tap:'☝', spin:'◉', ad:'▶', referral:'♟', convert:'⇄' })[type] || '✦';
}

function questCard(q) {
  const pct = Math.min(100, Math.round((q.progress || 0) / q.target_count * 100));
  return `<article class="card quest">
    <div class="quest-icon">${questIcon(q.event_type)}</div>
    <div><h3>${escapeHtml(q.title)}</h3><p>${escapeHtml(q.description)}</p><div class="progress"><i style="width:${pct}%"></i></div><p>${money(q.progress)} / ${money(q.target_count)}</p></div>
    <div class="quest-reward"><strong>+${money(q.reward_points)} OC</strong><button class="${q.completed&&!q.claimed?'primary':'secondary'}" data-action="claim-quest" data-id="${escapeHtml(q.id)}" ${!q.completed||q.claimed?'disabled':''}>${q.claimed?'Alındı':q.completed?'AL':'Devam'}</button></div>
  </article>`;
}

function questsPage() {
  return shell(`
    <div class="tabs"><button class="active">Günlük</button><button>Haftalık</button><button>Özel</button></div>
    <section class="card page-panel" style="display:grid;grid-template-columns:1fr;gap:10px;align-items:center">
      <div><small>GÜNLÜK SERİ</small><strong style="display:block;font-size:30px;color:var(--gold-3)">${state.game.state.streakDays} Gün</strong><p style="color:var(--muted);font-size:11px">Serini bozma, bonus ödülleri büyüt.</p></div>
    </section>
    <div class="section-head"><h2>Aktif Görevler</h2><span>${state.quests.filter(q=>q.completed).length}/${state.quests.length}</span></div>
    <section class="quest-list">${state.quests.map(questCard).join('') || '<div class="empty card">Görev bulunamadı.</div>'}</section>
  `, 'Görevler', 'Görevleri tamamla, OC_POINTS ödüllerini sunucudan güvenle al.');
}

function friendsPage() {
  const r = state.referrals;
  if (!r) return shell('<div class="empty card">Davet verileri yükleniyor…</div>', 'Arkadaş Daveti');
  return shell(`
    <section class="card ref-summary"><div><strong>${money(r.invited)}</strong><small>Davet Edilen</small></div><div><strong>${money(r.totalEarnedPoints)}</strong><small>Toplam Kazanç</small></div><div><strong>${money(r.qualified)}</strong><small>Nitelikli Takım</small></div></section>
    <section class="card ref-code"><small>DAVET KODUN</small><div class="code-box">${escapeHtml(r.referralCode)} <button class="text-button" data-action="copy" data-value="${escapeHtml(r.referralCode)}">⧉</button></div><div class="share-grid"><button class="secondary" data-action="copy" data-value="${escapeHtml(r.referralLink)}">Bağlantıyı Kopyala</button><button class="primary" data-action="share-ref">Paylaş</button></div></section>
    <div class="section-head"><h2>Ekip Yapın & Kazanın</h2><span></span></div>
    <section class="level-grid">${r.levels.map((level)=>`<div class="card level-card" style="opacity:${level.enabled?1:.45}"><small>${level.level}. SEVİYE</small><strong>%${level.percentage}</strong><small>${level.enabled?'Aktif komisyon':'Admin panelinden kapalı'}</small></div>`).join('')}</section>
    <div class="section-head"><h2>Son Davetler</h2><span>${r.recent.length}</span></div>
    <section class="quest-list">${r.recent.length ? r.recent.map((item)=>`<div class="card quest"><div class="quest-icon">🦁</div><div><h3>${escapeHtml(item.display_name)}</h3><p>@${escapeHtml(item.username)} · ${escapeHtml(item.status)}</p></div><div class="quest-reward"><strong>${item.status==='rewarded'?'+Ödül':'Bekliyor'}</strong></div></div>`).join('') : '<div class="empty card">Henüz davet bulunmuyor. Bağlantını paylaşarak ekibini kur.</div>'}</section>
    <section class="card event-banner"><small>HAFTALIK DAVET BONUSU</small><h3>+1.000 OC</h3><p>Nitelikli bir arkadaşın 100 doğrulanmış dokunuşa ulaştığında ödül otomatik aktarılır.</p><span class="chest">🎁</span></section>
    <button class="secondary full-button" data-page="leaderboard">Liderlik Tablosunu Gör</button>
  `, 'Arkadaş Daveti', 'Arkadaşlarını davet et, nitelikli ekip aktivitesiyle birlikte kazan.');
}

function txLabel(tx) {
  const labels = { tap_reward:'Tap Ödülü', automatic_earning:'Otomatik Kazanç', wheel_reward:'Çark Ödülü', quest_reward:'Görev Ödülü', referral_reward:'Davet Ödülü', points_conversion_burn:'OC_POINTS Dönüşümü', token_conversion_credit:'OC_TOKEN Dönüşümü', vip_purchase_points:'VIP Satın Alımı', ad_reward:'Reklam Ödülü', welcome_reward:'Hoş Geldin Ödülü', admin_grant:'Yönetici Dağıtımı' };
  return labels[tx.type] || tx.type;
}

function walletPage() {
  const w = state.wallet;
  if (!w) return shell('<div class="empty card">Cüzdan yükleniyor…</div>', 'Cüzdan');
  const conversion = state.config.conversion;
  const launchLocked = conversion.unlockAtLaunch && new Date(state.config.launchAt).getTime() > Date.now();
  const presale = state.site?.presale;
  const activeStage = presale?.activeStage;
  const methods = state.payments?.providers || [];
  const ps = state.presaleSummary || { totalDepositUsdtMicros: 0, estimatedTokenDisplay: '0', finalizedTokenDisplay: '0', policy: 'launch_price', locked: false, purchases: [] };
  const generated = (state.wallets || []).find((item) => item.walletType === 'generated_testnet');
  const mainnet = (state.wallets || []).find((item) => item.walletType === 'external_mainnet' && item.verificationStatus === 'email_confirmed');
  const allWallets = (state.wallets || []).map((item) => `<article class="card managed-wallet"><div class="wallet-network"><span>${item.walletType === 'generated_testnet' ? 'TESTNET' : 'MAINNET'}</span><b>${escapeHtml(item.network)}</b></div><code>${escapeHtml(item.address)}</code><div class="wallet-meta"><span>${escapeHtml(item.label || '')}</span><span>${escapeHtml(item.verificationStatus)}</span><span>${escapeHtml(item.status)}</span></div></article>`).join('');
  const walletSetup = generated ? '' : `<section class="card wallet-setup"><div class="section-head" style="margin-top:0"><h2>Testnet Cüzdanı Oluştur</h2><span>Parola Korumalı</span></div><p>Mainnet öncesi dağıtım ve cüzdan kullanımını test edin. Parola OnlyCoin tarafından okunamaz veya e-postayla gönderilmez.</p><form id="testnet-wallet-form" class="wallet-form"><input class="input" name="label" value="OnlyCoin Testnet Cüzdanı" placeholder="Cüzdan etiketi"><input class="input" name="password" type="password" minlength="12" placeholder="Cüzdan parolası" required><input class="input" name="confirmPassword" type="password" minlength="12" placeholder="Cüzdan parolasını doğrula" required><label class="auth-check"><input type="checkbox" name="acknowledgeBackup" value="true" required><span>Parolamı ayrı bir parola yöneticisinde saklayacağımı ve OnlyCoin'in parolayı kurtaramayacağını anlıyorum.</span></label><button class="primary full-button">Testnet Cüzdanı Oluştur</button></form></section>`;
  const recovery = state.recoveryToken ? `<section class="card recovery-alert"><h3>Şifreli Kurtarma Paketiniz Hazır</h3><p>Bu bağlantı tek kullanımlıktır ve kısa sürede sona erer. Dosyayı şimdi indirip çevrimdışı saklayın.</p><a class="primary full-button" href="/api/account/wallets/recovery/${encodeURIComponent(state.recoveryToken)}" download>Şifreli Keystore Paketini İndir</a><small>Cüzdan parolası bu dosyanın içinde bulunmaz.</small></section>` : '';
  const mainnetForm = mainnet ? '' : `<section class="card wallet-setup"><div class="section-head" style="margin-top:0"><h2>Mainnet Dağıtım Adresi</h2><span>Lansman</span></div><p>Contract dağıtımı veya manuel çekim için kendi EVM cüzdan adresinizi kaydedin. Yeni adres e-posta koduyla doğrulanır ve güvenlik bekleme süresine alınabilir.</p><form id="mainnet-wallet-form" class="wallet-form"><input class="input" name="network" value="${escapeHtml(state.config?.network?.name || 'EVM Mainnet')}" placeholder="Ağ"><input class="input" name="address" placeholder="0x..." required><input class="input" name="confirmAddress" placeholder="Adresi tekrar girin" required><input class="input" name="label" value="Ana Ağ Cüzdanım" placeholder="Etiket"><button class="secondary full-button">Mainnet Adresi Ekle</button></form>${state.walletConfirmation ? `<form id="wallet-confirm-form" class="wallet-form confirm-form"><input type="hidden" name="walletId" value="${escapeHtml(state.walletConfirmation.walletId)}"><input class="input" name="code" inputmode="numeric" maxlength="6" value="${escapeHtml(state.walletConfirmation.debugCode || '')}" placeholder="E-posta doğrulama kodu" required><button class="primary full-button">Adresi Doğrula</button></form>` : ''}</section>`;
  const distributions = (w.distributions || []).map((row) => `<article class="card distribution-card"><div><small>${escapeHtml(row.campaign_name || 'Lansman Dağıtımı')}</small><h3>${escapeHtml(row.amount_token_display || '0')} OC</h3><p>Presale: ${escapeHtml(row.presale_token_display || '0')} OC · Biriken: ${money(row.game_token_whole || 0)} OC</p></div><div class="distribution-status"><span>${escapeHtml(row.status)}</span><small>${escapeHtml(row.network || '')}</small>${row.tx_hash ? `<code>${escapeHtml(row.tx_hash.slice(0, 14))}…</code>` : ''}</div></article>`).join('');
  return shell(`
    <section class="card wallet-balance"><small>TOPLAM VARLIKLAR</small><div class="dual"><div class="asset-card"><span>OC_POINTS</span><strong>${money(w.balances.OC_POINTS)}</strong></div><div class="asset-card"><span>OC_TOKEN</span><strong>${money(w.balances.OC_TOKEN)}</strong></div></div></section>
    <section class="card presale-balance"><div class="section-head" style="margin-top:0"><h2>Presale Hakedişim</h2><span>${escapeHtml(ps.policy)}</span></div><div class="presale-balance-grid"><div><small>YATIRILAN DEPOSIT</small><strong>${money(Number(ps.totalDepositUsdtMicros || 0) / 1e6)} USDT</strong></div><div><small>GÜNCEL TAHMİN</small><strong>${escapeHtml(ps.estimatedTokenDisplay || '0')} OC</strong></div><div><small>KESİNLEŞMİŞ</small><strong>${escapeHtml(ps.finalizedTokenDisplay || '0')} OC</strong></div></div><p>Esas kayıt yatırdığınız doğrulanmış USDT miktarıdır. Tahmini coin miktarı admin tarafından belirlenen arz, fiyat ve tahsisat politikasına göre finalizasyona kadar değişebilir.</p><button class="primary full-button" data-action="open-presale-payment" ${!presale?.enabled || !activeStage || ps.locked ? 'disabled' : ''}>USDT Deposit ile Presale'e Katıl</button></section>
    <section class="card convert-box"><div class="section-head" style="margin-top:0"><h2>OC_POINTS → OC_TOKEN</h2><span>%${conversion.ratePercent}</span></div>
      <div class="convert-row"><input id="convert-amount" class="input" inputmode="numeric" type="number" min="${conversion.minPoints}" value="${conversion.minPoints}" aria-label="Dönüştürülecek puan"><button class="primary" data-action="convert" ${launchLocked || !conversion.enabled ? 'disabled' : ''}>Dönüştür</button></div>
      <div id="convert-preview" class="convert-preview">${money(conversion.minPoints)} OC_POINTS → ${money(Math.floor(conversion.minPoints * conversion.ratePercent / 100))} OC_TOKEN</div>
      ${launchLocked ? `<div class="lock-notice">🔒 Dönüşüm lansmanda açılacak. Kalan süre: <b data-countdown>${countdownHtml()}</b></div>` : '<div class="lock-notice">Dönüşüm oranı ve günlük limit yönetim panelinden değiştirilebilir. İşlem çift taraflı ledger kaydıyla gerçekleştirilir.</div>'}
    </section>
    ${walletSetup}${recovery}
    <div class="section-head"><h2>Dağıtım Cüzdanları</h2><span>${state.wallets.length}</span></div>
    <section class="managed-wallet-list">${allWallets || '<div class="empty card">Henüz cüzdan adresi bulunmuyor.</div>'}</section>
    ${mainnetForm}
    <div class="section-head"><h2>Lansman Dağıtımı</h2><span>${(w.distributions || []).length}</span></div>
    <section class="distribution-list">${distributions || '<div class="empty card">Henüz lansman dağıtım kaydı oluşturulmadı. Presale kesinleştirilip kampanya açıldığında satın aldığınız ve biriktirdiğiniz OC burada birlikte gösterilir.</div>'}</section>
    <section class="card finance-action-card"><div><small>ONLYCOIN PRESALE</small><h3>${activeStage ? escapeHtml(activeStage.name) : 'Presale'}</h3><p>${activeStage ? `Referans fiyat ${(Number(activeStage.price_usdt_micros) / 1e6).toFixed(6)} USDT · Bonus %${Number(activeStage.bonus_bps) / 100}` : 'Aktif satış aşaması yönetim panelinden belirlenir.'}</p></div><button class="primary" data-action="open-presale-payment" ${!presale?.enabled || !activeStage || ps.locked ? 'disabled' : ''}>Deposit Oluştur</button></section>
    <div class="section-head"><h2>Aktif Ödeme Yöntemleri</h2><span>${methods.length}</span></div>
    <section class="payment-method-grid">${methods.length ? methods.map((provider) => `<div class="card payment-method"><span class="payment-method-icon">${provider.category === 'crypto' ? '₿' : provider.category === 'bank' ? '🏦' : '💳'}</span><div><strong>${escapeHtml(provider.name)}</strong><small>${escapeHtml(provider.description)}</small><em>${provider.category === 'crypto' ? (state.payments.cryptoAssets || []).map((a) => a.symbol).join(' · ') : (provider.currencies || []).map((c) => c.currency_code).join(' · ')}</em></div></div>`).join('') : '<div class="empty card">Yönetim panelinden ödeme yöntemi etkinleştirilmedi.</div>'}</section>
    <div class="section-head"><h2>İşlem Geçmişi</h2><span>${w.transactions.length}</span></div>
    <section class="tx-list">${w.transactions.length ? w.transactions.map((tx) => `<div class="card tx"><div><strong>${escapeHtml(txLabel(tx))}</strong><small>${new Date(tx.created_at).toLocaleString('tr-TR')} · ${escapeHtml(tx.asset)}</small></div><b class="${tx.amount > 0 ? 'positive' : 'negative'}">${tx.amount > 0 ? '+' : ''}${money(tx.amount)}</b></div>`).join('') : '<div class="empty card">Henüz işlem yok.</div>'}</section>
  `, 'Cüzdan', 'Deposit, tahmini hakediş, testnet cüzdan ve lansman dağıtım adresi.');
}

function vipPage() {
  const v = state.vip;
  if (!v) return shell('<div class="empty card">VIP paketleri yükleniyor…</div>', 'VIP & Market');
  return shell(`
    <section class="card vip-current"><div class="crown">♛</div><div><small>MEVCUT VIP SEVİYEN</small><strong style="display:block;color:var(--gold-3);font-size:24px">VIP ${v.state.state.vipTier || 0}</strong><span style="color:var(--muted);font-size:11px">Tap, enerji, otomatik kazanç ve ücretsiz çark avantajları</span></div></section>
    <div class="tabs"><button class="active">VIP Paketleri</button><button>Boostlar</button><button>Satın Alımlar</button></div>
    <section class="vip-list">${v.plans.map((plan) => {
      const prices = vipPricesForTier(plan.tier);
      return `<article class="card vip-card ${plan.tier === v.state.state.vipTier ? 'active' : ''}"><div style="display:flex;justify-content:space-between;align-items:start"><div><small>${escapeHtml(plan.subtitle)}</small><h3>${escapeHtml(plan.name)}</h3></div><span class="price">${money(plan.price_points)} OC</span></div><div class="vip-benefits"><span>Tap x${plan.tap_multiplier_bps / 10000}</span><span>Enerji x${plan.energy_multiplier_bps / 10000}</span><span>Otomatik x${plan.auto_multiplier_bps / 10000}</span><span>+${plan.daily_free_spins} Ek Ücretsiz Çark</span><span>Referans x${plan.referral_multiplier_bps / 10000}</span><span>Admin yönetimli süre</span></div><div class="vip-price-row">${prices.slice(0, 4).map((price) => `<span>${formatPaymentAmount(price.amount_minor, price.currency_code)} <b>${escapeHtml(price.currency_code)}</b></span>`).join('')}</div><div class="vip-buy-grid"><button class="secondary" data-action="buy-vip" data-tier="${plan.tier}" ${plan.tier <= v.state.state.vipTier ? 'disabled' : ''}>OC_POINTS İLE AL</button><button class="primary" data-action="open-vip-payment" data-tier="${plan.tier}" ${plan.tier <= v.state.state.vipTier || !(state.payments?.providers || []).length ? 'disabled' : ''}>KART / DÖVİZ / KRİPTO</button></div></article>`;
    }).join('')}</section>
    <div class="lock-notice" style="margin-top:12px">Kart, banka, SWIFT ve kripto seçenekleri yönetim panelindeki bölgesel ve sağlayıcı ayarlarına göre görünür. Türkiye mağaza sürümlerinde dijital VIP satışı ilgili mağaza içi satın alma kurallarına ayrıca bağlanmalıdır.</div>
  `, 'VIP & Market', 'VIP seviyeni yükselt; ödeme para birimini ve yöntemi güvenli checkout ekranından seç.');
}

function leaderboardPage() {
  const rows = state.leaderboard;
  const top = rows.slice(0,3);
  return shell(`
    <div class="tabs"><button class="active">Günlük</button><button>Haftalık</button><button>Tüm Zamanlar</button></div>
    <section class="leader-podium">${[1,0,2].map((idx)=>{const row=top[idx]; if(!row)return '<div></div>'; return `<div class="card podium-card ${idx===0?'first':''}"><div class="podium-avatar">${idx===0?'🦁':idx===1?'🦅':'🐺'}</div><strong>${escapeHtml(row.display_name)}</strong><small>VIP ${row.vip_tier}</small><b>${money(row.points)} OC</b></div>`}).join('')}</section>
    <section class="rank-list">${rows.map((row)=>`<div class="card rank"><b>${row.rank}</b><div class="avatar">${row.rank===1?'🦁':'◈'}</div><div><strong>${escapeHtml(row.display_name)}</strong><small>Seviye ${row.level} · VIP ${row.vip_tier}</small></div><b>${money(row.points)} OC</b></div>`).join('')}</section>
  `, 'Liderlik Tablosu', 'Sunucu tarafından doğrulanan OC_POINTS bakiyesine göre sıralama.');
}

function profilePage() {
  const g = state.game;
  return shell(`
    <section class="card profile-card"><div class="profile-avatar">🦁</div><div><h2>${escapeHtml(g.user.displayName)}</h2><p>@${escapeHtml(g.user.username)} · Seviye ${g.state.level}</p><p>Davet Kodu: ${escapeHtml(g.user.referralCode)}</p></div></section>
    <section class="card stats-grid"><div class="stat"><small>Toplam Dokunma</small><strong>${money(g.state.tapTotal)}</strong></div><div class="stat"><small>Günlük Seri</small><strong>${g.state.streakDays} Gün</strong></div><div class="stat"><small>VIP</small><strong>${g.state.vipTier}</strong></div></section>
    <section class="card menu-list"><div class="menu-row"><span>Bağlı Cüzdan</span><b>OC Oyun Cüzdanı</b></div><div class="menu-row"><span>Bildirimler</span><b>Açık</b></div><div class="menu-row"><span>Dil</span><b>Türkçe</b></div><div class="menu-row"><span>Destek</span><b>${escapeHtml(state.config?.supportEmail || 'support@onlycoin.io')}</b></div><div class="menu-row"><span>Güvenlik</span><b>Sunucu Otoriteli</b></div></section>
    <button class="secondary full-button" data-action="refresh">Verileri Yenile</button>
    <button class="danger full-button" data-action="logout">Çıkış Yap</button>
  `, 'Profil', 'Hesap, oyun istatistikleri ve güvenlik bilgileri.');
}

function maintenancePage() {
  return shell(`<section class="card page-panel" style="text-align:center;padding:45px 20px"><div style="font-size:58px">⚙</div><h2 style="color:var(--gold-3)">Planlı Bakım</h2><p style="color:var(--muted)">OnlyCoin oyun motoru kısa süreli bakımda. Bakiyeler ve ledger kayıtları güvende; lütfen biraz sonra yeniden deneyin.</p><button class="primary" data-action="refresh">Yeniden Dene</button></section>`, 'Bakım Modu', 'Yönetim paneli tarafından merkezi olarak etkinleştirildi.');
}

function render() {
  if (!state.config || !state.game) return;
  if (state.config.maintenanceMode && state.page !== 'profile') { app.innerHTML = maintenancePage(); updateCountdowns(); return; }
  const renderers = { home:homePage, wheel:wheelPage, quests:questsPage, friends:friendsPage, wallet:walletPage, vip:vipPage, leaderboard:leaderboardPage, profile:profilePage };
  const renderer = renderers[state.page] || homePage;
  app.innerHTML = renderer();
  updateCountdowns();
}

async function loadPageData(page, force = false) {
  if (page === 'quests' || page === 'home') state.quests = await api('/api/game/quests');
  if (page === 'wheel' && (!state.wheel || force)) state.wheel = await api('/api/game/wheel');
  if (page === 'friends' && (!state.referrals || force)) state.referrals = await api('/api/game/referrals');
  if (page === 'wallet' && (!state.wallet || force)) {
    [state.wallet, state.wallets, state.presaleSummary] = await Promise.all([api('/api/game/wallet'), api('/api/account/wallets'), api('/api/game/presale/summary')]);
  }
  if (page === 'vip' && (!state.vip || force)) state.vip = await api('/api/game/vip');
  if (page === 'leaderboard' && (!state.leaderboard.length || force)) state.leaderboard = await api('/api/game/leaderboard?limit=50');
}

async function navigate(page) {
  state.page = page;
  location.hash = page;
  try { await loadPageData(page); } catch (error) { toast(error.message, 'error'); }
  render();
  window.scrollTo({ top: 0, behavior: 'smooth' });
}

function updateGameFromResponse(response) {
  if (response.user && response.state && response.balances) {
    state.game = { user:response.user, state:response.state, balances:response.balances, vipPlan:response.vipPlan, launchAt:response.launchAt, conversionEnabled:response.conversionEnabled, conversionRatePercent:response.conversionRatePercent };
  }
}

function tapVisual(event) {
  const reward = state.game.state.tapReward;
  state.pendingTaps += 1;
  state.game.balances.OC_POINTS += reward;
  state.game.state.energy = Math.max(0, state.game.state.energy - 1);
  const balance = document.querySelector('#points-balance');
  if (balance) balance.textContent = money(state.game.balances.OC_POINTS);
  const queue = document.querySelector('#tap-queue');
  if (queue) queue.textContent = `${state.pendingTaps} bekliyor`;
  const coin = event.currentTarget;
  coin.classList.add('pressed');
  setTimeout(() => coin.classList.remove('pressed'), 80);
  const float = document.createElement('span');
  float.className = 'float-reward';
  float.textContent = `+${reward}`;
  float.style.left = `${event.clientX || window.innerWidth/2}px`;
  float.style.top = `${event.clientY || window.innerHeight/2}px`;
  document.body.appendChild(float);
  setTimeout(() => float.remove(), 950);
  clearTimeout(state.tapTimer);
  state.tapTimer = setTimeout(flushTaps, 750);
}

async function flushTaps() {
  if (state.tapSending || state.pendingTaps <= 0) return;
  state.tapSending = true;
  const count = Math.min(state.pendingTaps, 50);
  state.pendingTaps -= count;
  try {
    const result = await api('/api/game/tap', { method:'POST', body:{ count }, idempotencyKey:idempotency() });
    updateGameFromResponse(result);
    if (state.pendingTaps > 0) setTimeout(flushTaps, 100);
  } catch (error) {
    toast(error.message, 'error');
    state.game = await api('/api/game/state');
    state.pendingTaps = 0;
  } finally {
    state.tapSending = false;
    if (!state.pendingTaps) render();
  }
}

async function spin(mode) {
  if (state.wheelSpinning) return;
  state.wheelSpinning = true;
  state.wheelRequestKey = idempotency();
  render();
  try {
    const result = await api('/api/game/wheel/spin', { method:'POST', body:{ mode }, idempotencyKey:state.wheelRequestKey });
    const count = Math.max(1, Number(result.segmentCount || state.wheel?.segments?.length || 1));
    const index = Math.max(0, Number(result.segmentIndex || 0));
    const angle = 360 / count;
    const target = (360 - ((index * angle + angle / 2) % 360)) % 360;
    const current = ((state.wheelRotation % 360) + 360) % 360;
    const delta = ((target - current + 360) % 360) + 360 * 6;
    state.wheelRotation += delta;
    const wheel = document.querySelector('#lucky-wheel');
    const animationMs = Number(result.state?.wheel?.animationMs || state.game?.state?.wheel?.animationMs || 4600);
    if (wheel) {
      wheel.style.transitionDuration = `${animationMs}ms`;
      requestAnimationFrame(() => { wheel.style.transform = `rotate(${state.wheelRotation}deg)`; });
    }
    await new Promise((resolve) => setTimeout(resolve, animationMs + 250));
    updateGameFromResponse(result);
    state.wheel = await api('/api/game/wheel');
    toast(`Kazandınız: ${result.segment.label}`);
  } catch (error) {
    if (error.code === 'SPIN_IN_PROGRESS') toast('Çark hâlâ dönüyor. Sonucu bekleyin.', 'error');
    else toast(error.message, 'error');
    try { state.wheel = await api('/api/game/wheel'); } catch {}
  } finally {
    state.wheelSpinning = false;
    state.wheelRequestKey = '';
    render();
  }
}

async function claimQuest(id) {
  try {
    const result = await api(`/api/game/quests/${encodeURIComponent(id)}/claim`, { method:'POST', body:{}, idempotencyKey:idempotency() });
    updateGameFromResponse(result);
    state.quests = await api('/api/game/quests');
    toast(`+${result.rewardPoints} OC_POINTS alındı.`);
    render();
  } catch (error) { toast(error.message, 'error'); }
}

function showAdModal(session) {
  state.ad = session;
  let remaining = session.minimumWatchSeconds;
  modalRoot.innerHTML = `<div class="modal-backdrop"><div class="modal card"><h2>Ödüllü Reklam</h2><p>Ödül yalnızca yapılandırılmış reklam sağlayıcısının sunucu doğrulaması tamamlandığında verilir.</p><div class="ad-player">▶</div><div class="ad-count" id="ad-count">${remaining}</div><div class="modal-actions"><button class="secondary" data-action="close-modal">İptal</button><button id="ad-complete" class="primary" data-action="complete-ad" disabled>Ödülü Al</button></div></div></div>`;
  const timer = setInterval(() => {
    remaining -= 1;
    const count = document.querySelector('#ad-count');
    if (count) count.textContent = Math.max(0, remaining);
    if (remaining <= 0) {
      clearInterval(timer);
      document.querySelector('#ad-complete')?.removeAttribute('disabled');
    }
  }, 1000);
}

async function watchAd() {
  try { showAdModal(await api('/api/game/ads/start', { method:'POST', body:{} })); }
  catch (error) { toast(error.message, 'error'); }
}

async function completeAd() {
  if (!state.ad) return;
  try {
    const result = await api('/api/game/ads/complete', { method:'POST', body:{ adToken:state.ad.adToken } });
    updateGameFromResponse(result);
    state.ad = null;
    modalRoot.innerHTML = '';
    toast(`Reklam ödülü: +${result.rewardPoints} OC_POINTS ve +1 çark hakkı`);
    state.quests = await api('/api/game/quests');
    render();
  } catch (error) { toast(error.message, 'error'); }
}

async function convert() {
  const input = document.querySelector('#convert-amount');
  const points = Number(input?.value || 0);
  try {
    const result = await api('/api/game/convert', { method:'POST', body:{ points }, idempotencyKey:idempotency() });
    updateGameFromResponse(result);
    state.wallet = await api('/api/game/wallet');
    state.quests = await api('/api/game/quests');
    toast(`${money(result.pointsSpent)} OC_POINTS → ${money(result.tokensReceived)} OC_TOKEN`);
    render();
  } catch (error) {
    if (error.details?.launchAt) toast(`Dönüşüm ${new Date(error.details.launchAt).toLocaleString('tr-TR')} tarihinde açılacak.`, 'error');
    else toast(error.message, 'error');
  }
}

async function buyVip(tier) {
  if (!confirm(`VIP ${tier} paketini OC_POINTS ile satın almak istiyor musunuz?`)) return;
  try {
    const result = await api('/api/game/vip/purchase-points', { method:'POST', body:{ tier }, idempotencyKey:idempotency() });
    updateGameFromResponse(result);
    state.vip = await api('/api/game/vip');
    toast(`VIP ${tier} aktif edildi.`);
    render();
  } catch (error) { toast(error.message, 'error'); }
}

async function copy(value) {
  try { await navigator.clipboard.writeText(value); toast('Panoya kopyalandı.'); }
  catch { toast('Kopyalama izni verilemedi.', 'error'); }
}

async function shareReferral() {
  const r = state.referrals;
  const data = { title:'OnlyCoin', text:`OnlyCoin ücretsiz dağıtım oyununa katıl. Davet kodum: ${r.referralCode}`, url:r.referralLink };
  if (navigator.share) await navigator.share(data).catch(()=>{});
  else await copy(r.referralLink);
}


function selectedProvider() {
  const id = document.querySelector('#payment-provider')?.value;
  return state.payments?.providers?.find((provider) => provider.id === id) || null;
}

function updatePaymentModalOptions() {
  const provider = selectedProvider();
  const currencyWrap = document.querySelector('#payment-currency-wrap');
  const cryptoWrap = document.querySelector('#payment-crypto-wrap');
  const currencySelect = document.querySelector('#payment-currency');
  const cryptoSelect = document.querySelector('#payment-crypto');
  if (!provider) return;
  if (provider.category === 'crypto') {
    currencyWrap?.classList.add('hidden');
    cryptoWrap?.classList.remove('hidden');
    if (cryptoSelect) cryptoSelect.innerHTML = (state.payments.cryptoAssets || []).map((asset) => `<option value="${escapeHtml(asset.id)}">${escapeHtml(asset.symbol)} · ${escapeHtml(asset.network)}</option>`).join('');
  } else {
    cryptoWrap?.classList.add('hidden');
    currencyWrap?.classList.remove('hidden');
    if (currencySelect) currencySelect.innerHTML = (provider.currencies || []).map((currency) => `<option value="${escapeHtml(currency.currency_code)}">${escapeHtml(currency.currency_code)} · ${escapeHtml(currency.name || '')}</option>`).join('');
  }
  updatePaymentPricePreview();
}

function updatePaymentPricePreview() {
  const form = document.querySelector('#payment-checkout-form');
  const preview = document.querySelector('#payment-price-preview');
  if (!form || !preview) return;
  const purpose = form.dataset.purpose;
  if (purpose === 'vip') {
    const tier = Number(form.dataset.tier);
    const provider = selectedProvider();
    if (provider?.category === 'crypto') {
      const usdt = vipPricesForTier(tier).find((row) => row.currency_code === 'USDT');
      preview.textContent = usdt ? `Settlement: ${formatPaymentAmount(usdt.amount_minor, 'USDT')}` : 'USDT settlement fiyatı sunucuda hesaplanır.';
    } else {
      const code = document.querySelector('#payment-currency')?.value;
      const price = vipPricesForTier(tier).find((row) => row.currency_code === code);
      preview.textContent = price ? `Ödenecek: ${formatPaymentAmount(price.amount_minor, code)} (${code})` : `${code || 'Seçili döviz'} fiyatı güncel kurla hesaplanır.`;
    }
  } else {
    const amount = Number(document.querySelector('#presale-usdt-amount')?.value || 0);
    preview.textContent = `Presale tutarı: ${new Intl.NumberFormat('tr-TR', { maximumFractionDigits: 6 }).format(amount)} USDT`; 
  }
}

function openPaymentModal(purpose, options = {}) {
  const providers = state.payments?.providers || [];
  if (!providers.length) return toast('Aktif ödeme yöntemi bulunmuyor.', 'error');
  const providerOptions = providers.map((provider) => `<option value="${escapeHtml(provider.id)}">${escapeHtml(provider.name)} · ${provider.category === 'crypto' ? 'Kripto' : provider.category === 'bank' ? 'Banka/SWIFT' : 'Kart/Ödeme'}</option>`).join('');
  const activeStage = state.site?.presale?.activeStage;
  modalRoot.innerHTML = `<div class="modal-backdrop"><div class="modal card payment-modal"><button class="modal-close" data-action="close-modal">×</button><h2>${purpose === 'vip' ? `VIP ${options.tier} Satın Al` : 'OnlyCoin Presale'}</h2><p>Ödeme yöntemi ve para birimini seçin. Tutar ve yetki sunucuda doğrulanır.</p><form id="payment-checkout-form" data-purpose="${purpose}" data-tier="${options.tier || ''}" data-stage="${escapeHtml(activeStage?.id || '')}"><div class="payment-form-grid"><div class="field"><label>Ödeme Yöntemi</label><select id="payment-provider" class="input">${providerOptions}</select></div><div class="field" id="payment-currency-wrap"><label>Para Birimi</label><select id="payment-currency" class="input"></select></div><div class="field hidden" id="payment-crypto-wrap"><label>Kripto Varlık / Ağ</label><select id="payment-crypto" class="input"></select></div>${purpose === 'presale' ? `<div class="field"><label>Tutar (USDT)</label><input id="presale-usdt-amount" class="input" type="number" step="0.01" min="${Number(state.site?.presale?.minUsdtMicros || 10_000_000) / 1e6}" max="${Number(state.site?.presale?.maxUsdtMicros || 100_000_000_000) / 1e6}" value="${Number(state.site?.presale?.minUsdtMicros || 10_000_000) / 1e6}"></div>` : ''}</div><div id="payment-price-preview" class="payment-preview"></div><div class="modal-actions"><button type="button" class="secondary" data-action="close-modal">Vazgeç</button><button type="submit" class="primary">Ödeme Emri Oluştur</button></div></form></div></div>`;
  updatePaymentModalOptions();
}

function showCheckoutResult(result) {
  const session = result.session || {};
  const instructions = session.instructions || {};
  let content = '';
  if (session.checkout_url) {
    content = `<div class="checkout-result-icon">↗</div><h2>Güvenli Ödeme Sayfası Hazır</h2><p>Ödeme sağlayıcısının güvenli sayfasında işlemi tamamlayın. Ödeme sonucu webhook ile doğrulanacaktır.</p><a class="primary checkout-link" href="${escapeHtml(session.checkout_url)}" target="_blank" rel="noopener">Ödeme Sayfasını Aç</a>`;
  } else if (instructions.type === 'bank_transfer') {
    const bank = instructions.bank || {};
    content = `<div class="checkout-result-icon">🏦</div><h2>Banka / SWIFT Talimatı</h2><div class="checkout-details"><span>Banka<b>${escapeHtml(bank.bank_name)}</b></span><span>Hesap Sahibi<b>${escapeHtml(bank.account_holder)}</b></span><span>IBAN<b>${escapeHtml(bank.iban || '-')}</b></span><span>SWIFT/BIC<b>${escapeHtml(bank.swift_bic || '-')}</b></span><span>Para Birimi<b>${escapeHtml(bank.currency_code)}</b></span><span>Referans<b>${escapeHtml(instructions.reference)}</b></span></div><p>${escapeHtml(bank.instructions || 'Ödeme referansını açıklamaya yazın.')}</p>`;
  } else if (instructions.type === 'crypto_transfer') {
    content = `<div class="checkout-result-icon">₿</div><h2>Kripto Transfer Talimatı</h2><div class="checkout-details"><span>Varlık / Ağ<b>${escapeHtml(instructions.asset?.symbol)} · ${escapeHtml(instructions.asset?.network)}</b></span><span>Tutar<b>${escapeHtml(instructions.amountFormatted)} ${escapeHtml(instructions.asset?.symbol)}</b></span><span>Adres<b class="break-all">${escapeHtml(instructions.address)}</b></span><span>Referans<b>${escapeHtml(instructions.reference)}</b></span><span>Onay Sayısı<b>${escapeHtml(instructions.confirmationsRequired)}</b></span></div><p>Yalnızca belirtilen ağdan gönderin. Yanlış ağ veya varlık kalıcı kayba yol açabilir.</p>`;
  } else {
    content = '<h2>Ödeme Emri Oluşturuldu</h2><p>İşlem yönetim paneli ve ödeme sağlayıcısı üzerinden takip edilecektir.</p>';
  }
  modalRoot.innerHTML = `<div class="modal-backdrop"><div class="modal card payment-modal"><button class="modal-close" data-action="close-modal">×</button>${content}<button class="secondary full-button" data-action="close-modal">Kapat</button></div></div>`;
  if (session.checkout_url) window.open(session.checkout_url, '_blank', 'noopener');
}

async function submitPaymentCheckout(form) {
  const provider = selectedProvider();
  if (!provider) return toast('Ödeme yöntemi seçin.', 'error');
  const purpose = form.dataset.purpose;
  const body = {
    purpose,
    providerId: provider.id,
    currencyCode: document.querySelector('#payment-currency')?.value || 'TRY',
    cryptoAssetId: document.querySelector('#payment-crypto')?.value || ''
  };
  if (purpose === 'vip') body.tier = Number(form.dataset.tier);
  else {
    body.stageId = form.dataset.stage || undefined;
    body.amountUsdtMicros = Math.round(Number(document.querySelector('#presale-usdt-amount')?.value || 0) * 1e6);
  }
  const result = await api('/api/game/payment-checkout', { method: 'POST', body, idempotencyKey: idempotency() });
  showCheckoutResult(result);
  state.wallet = null;
  state.vip = null;
}

async function socialLogin(providerId) {
  const result = await api(`/api/auth/oauth/${encodeURIComponent(providerId)}/start?redirect=${encodeURIComponent('/game/')}&ref=${encodeURIComponent(referralCodeFromContext())}`, { auth: false });
  location.href = result.url;
}

async function submitLogin(form) {
  const data = Object.fromEntries(new FormData(form));
  await finishUserLogin(await api('/api/auth/email/login', { method: 'POST', auth: false, body: data }));
}

async function submitRegister(form) {
  const data = Object.fromEntries(new FormData(form));
  delete data.terms;
  data.referralCode = referralCodeFromContext();
  const result = await api('/api/auth/register', { method: 'POST', auth: false, body: data });
  if (result.verificationRequired) {
    state.verificationEmail = data.email;
    state.verificationCode = '';
    state.verificationDeliveryError = result.emailDelivery?.delivered ? '' : 'Doğrulama e-postası teslim edilemedi. Kodu yeniden göndermeyi deneyin veya destek birimine başvurun.';
    authScreen();
    toast(result.emailDelivery?.delivered ? 'Doğrulama kodu e-posta adresinize gönderildi.' : state.verificationDeliveryError, result.emailDelivery?.delivered ? 'success' : 'error');
    return;
  }
  await finishUserLogin(result);
}

async function submitEmailVerification(form) {
  const data = Object.fromEntries(new FormData(form));
  await finishUserLogin(await api('/api/auth/email/verify', { method: 'POST', auth: false, body: { email: state.verificationEmail, code: data.code } }));
}

async function requestPassword(form) {
  const data = Object.fromEntries(new FormData(form));
  await api('/api/auth/password/request', { method: 'POST', auth: false, body: data });
  state.resetEmail = data.email;
  state.resetSent = true;
  state.authMode = 'reset-sent';
  authScreen();
  toast('Hesap mevcutsa parola yenileme bağlantısı e-posta adresinize gönderildi.');
}

async function resetPasswordForm(form) {
  const data = Object.fromEntries(new FormData(form));
  await api('/api/auth/password/reset', { method: 'POST', auth: false, body: data });
  modalRoot.innerHTML = '';
  state.authMode = 'login';
  state.resetToken = '';
  const clean = new URL(location.href); clean.searchParams.delete('reset_token'); clean.searchParams.delete('email'); history.replaceState({}, '', `${clean.pathname}${clean.search}${clean.hash}`);
  authScreen();
  toast('Parolanız güncellendi. Giriş yapabilirsiniz.');
}

async function createTestnetWalletForm(form) {
  const data = Object.fromEntries(new FormData(form));
  const result = await api('/api/account/wallets/testnet', { method: 'POST', body: data, idempotencyKey: idempotency() });
  state.recoveryToken = result.recoveryToken;
  state.wallets = await api('/api/account/wallets');
  state.wallet = await api('/api/game/wallet');
  render();
  toast('Testnet cüzdanı oluşturuldu. Kurtarma paketini hemen indirin.');
}

async function addMainnetWalletForm(form) {
  const data = Object.fromEntries(new FormData(form));
  const result = await api('/api/account/wallets/mainnet', { method: 'POST', body: data, idempotencyKey: idempotency() });
  state.walletConfirmation = { walletId: result.wallet.id, debugCode: result.debugConfirmationCode || '' };
  state.wallets = await api('/api/account/wallets');
  render();
  toast(result.confirmationRequired ? 'Doğrulama kodu e-posta kuyruğuna alındı.' : 'Mainnet adresi kaydedildi.');
}

async function confirmMainnetWalletForm(form) {
  const data = Object.fromEntries(new FormData(form));
  await api(`/api/account/wallets/${encodeURIComponent(data.walletId)}/confirm`, { method: 'POST', body: { code: data.code } });
  state.walletConfirmation = null;
  state.wallets = await api('/api/account/wallets');
  render();
  toast('Mainnet cüzdan adresi doğrulandı.');
}

async function refreshAll() {
  state.config = await api('/api/public/config', { auth:false });
  state.site = await api('/api/public/site', { auth:false });
  state.payments = await api('/api/public/payments?country=TR', { auth:false });
  state.authConfig = await api('/api/public/auth', { auth:false });
  state.game = await api('/api/game/state');
  state.quests = await api('/api/game/quests');
  state.wallet = state.referrals = state.vip = state.wheel = null;
  state.leaderboard = [];
  await loadPageData(state.page, true);
  render();
  toast('Veriler yenilendi.');
}

async function logout() {
  try { await api('/api/auth/logout', { method:'POST', body:{} }); } catch {}
  state.authenticated = false;
  location.reload();
}

document.addEventListener('click', async (event) => {
  const pageButton = event.target.closest('[data-page]');
  if (pageButton) { event.preventDefault(); return navigate(pageButton.dataset.page); }
  const action = event.target.closest('[data-action]');
  if (!action) return;
  event.preventDefault();
  const type = action.dataset.action;
  if (type === 'auth-mode') { state.authMode = action.dataset.mode || 'login'; state.verificationEmail = ''; return authScreen(); }
  if (type === 'social-login') return socialLogin(action.dataset.provider);
  if (type === 'resend-verification') {
    const result = await api('/api/auth/email/resend', { method: 'POST', auth: false, body: { email: state.verificationEmail } });
    state.verificationCode = '';
    state.verificationDeliveryError = result.emailDelivery?.delivered ? '' : 'Doğrulama e-postası teslim edilemedi. SMTP ayarlarını kontrol etmek için destek birimine başvurun.';
    authScreen();
    return toast(result.emailDelivery?.delivered ? 'Yeni doğrulama kodu gönderildi.' : state.verificationDeliveryError, result.emailDelivery?.delivered ? 'success' : 'error');
  }
  if (type === 'tap') return tapVisual(event);
  if (type === 'spin') return spin(action.dataset.mode);
  if (type === 'claim-quest') return claimQuest(action.dataset.id);
  if (type === 'watch-ad') return watchAd();
  if (type === 'complete-ad') return completeAd();
  if (type === 'close-modal') { state.ad = null; modalRoot.innerHTML=''; return; }
  if (type === 'convert') return convert();
  if (type === 'buy-vip') return buyVip(Number(action.dataset.tier));
  if (type === 'open-vip-payment') return openPaymentModal('vip', { tier:Number(action.dataset.tier) });
  if (type === 'open-presale-payment') return openPaymentModal('presale');
  if (type === 'copy') return copy(action.dataset.value || '');
  if (type === 'share-ref') return shareReferral();
  if (type === 'refresh') return refreshAll();
  if (type === 'logout') return logout();
});

document.addEventListener('input', (event) => {
  if (['payment-currency','presale-usdt-amount'].includes(event.target.id)) updatePaymentPricePreview();
  if (event.target.id === 'convert-amount') {
    const points = Number(event.target.value || 0);
    const tokens = Math.floor(points * state.config.conversion.ratePercent / 100);
    const preview = document.querySelector('#convert-preview');
    if (preview) preview.textContent = `${money(points)} OC_POINTS → ${money(tokens)} OC_TOKEN`;
  }
});

document.addEventListener('change', (event) => {
  if (event.target.id === 'payment-provider') updatePaymentModalOptions();
  if (event.target.id === 'payment-currency') updatePaymentPricePreview();
});

document.addEventListener('submit', async (event) => {
  event.preventDefault();
  try {
    if (event.target.id === 'payment-checkout-form') return await submitPaymentCheckout(event.target);
    if (event.target.id === 'login-form') return await submitLogin(event.target);
    if (event.target.id === 'register-form') return await submitRegister(event.target);
    if (event.target.id === 'verify-email-form') return await submitEmailVerification(event.target);
    if (event.target.id === 'password-request-form') return await requestPassword(event.target);
    if (event.target.id === 'password-reset-form') return await resetPasswordForm(event.target);
    if (event.target.id === 'testnet-wallet-form') return await createTestnetWalletForm(event.target);
    if (event.target.id === 'mainnet-wallet-form') return await addMainnetWalletForm(event.target);
    if (event.target.id === 'wallet-confirm-form') return await confirmMainnetWalletForm(event.target);
  } catch (error) { toast(error.message, 'error'); }
});

window.addEventListener('hashchange', () => navigate(location.hash.replace('#','') || 'home'));

async function bootstrap() {
  try {
    [state.config, state.site, state.payments, state.authConfig] = await Promise.all([
      api('/api/public/config', { auth:false }),
      api('/api/public/site', { auth:false }),
      api('/api/public/payments?country=TR', { auth:false }),
      api('/api/public/auth', { auth:false })
    ]);
    if (!window.Telegram) await new Promise((resolve) => setTimeout(resolve, 350));
    const authenticated = await authenticate();
    if (!authenticated) {
      authScreen();
      return;
    }
    state.game = await api('/api/game/state');
    await loadPageData(state.page);
    render();
    setInterval(updateCountdowns, 1000);
    setInterval(async () => {
      if (document.hidden || state.tapSending || state.pendingTaps || !state.authenticated) return;
      try { state.game = await api('/api/game/state'); if (state.page === 'home') render(); } catch {}
    }, 30000);
    if ('serviceWorker' in navigator) navigator.serviceWorker.register('/game/service-worker.js').catch(()=>{});
  } catch (error) {
    app.innerHTML = `<div class="boot-screen"><img src="/game/assets/onlycoin-token.png" alt="OnlyCoin" class="boot-logo"><strong>BAĞLANTI HATASI</strong><span>${escapeHtml(error.message)}</span><button class="primary" onclick="location.reload()">Tekrar Dene</button></div>`;
  }
}

bootstrap();
