// site-jogador/js/donate.jsx
//
// DONATE: o jogador doa (livre/espontaneo) e ganha Z Bucks de agradecimento.
// Cards 3D (estilo recompensas) com as artes zbucks-*.png + politica de donate com
// SCROLL OBRIGATORIO ate o fim + CHECKBOX de concordancia antes de seguir pro
// pagamento (Mercado Pago). Pagamento real roda atras das Functions /donate/* (PAYMENTS_ENABLED).
// Copy: linguagem profissional brasileira (voce/seu/sua), com acentuacao normal (web = UTF-8).

const DN_ACCENT = '#a8ff00';
const ZB_ICON = 'uploads/zbucks/zbucks-icon.png';

function dnFmt(n) { return Number(n || 0).toLocaleString('pt-BR'); }
function dnBRL(n) { return Number(n || 0).toLocaleString('pt-BR', { minimumFractionDigits: 2 }); }

// Texto da politica de donate (scroll obrigatorio + aceite). Canon: cronos-lore/legal/politica-donate.md
const DONATE_POLICY = [
  { h: 'O que é o Donate', p: 'O Donate é uma contribuição voluntária e espontânea para ajudar a manter o Project Gen Z no ar. Você contribui porque quer apoiar o servidor, e nada além disso. Não é obrigatório para jogar, e tudo no servidor continua acessível sem doar.' },
  { h: 'Os Z Bucks são um agradecimento', p: 'Os Z Bucks (ZB), e qualquer item virtual obtido com eles, são um presente de agradecimento pelo seu apoio, concedido como uma licença de uso pessoal, limitada, revogável e intransferível, sem valor monetário fora do servidor. Não podem ser vendidos, cedidos, trocados, sacados, convertidos em dinheiro real nem transferidos para outro jogador ou conta. Existem apenas dentro do Project Gen Z.' },
  { h: 'Onde o seu Donate é investido', p: '100% do que entra vai para manter o projeto vivo: pagamento do host (a máquina onde o servidor roda) e infraestrutura (banco de dados, site, ferramentas). O Project Gen Z é comunitário, sem fins lucrativos, sem CNPJ, e ninguém tira salário disso.' },
  { h: 'Entrega no jogo', p: 'A entrega dos itens dentro do jogo pode não ser imediata: depende de você estar no servidor e da sincronização da sua conta. O prazo razoável de entrega é de até 72 horas.' },
  { h: 'Confirmação e arrependimento', p: 'Ao confirmar, você solicita e autoriza expressamente a entrega imediata dos Z Bucks na sua conta. Por se tratar de conteúdo digital de execução imediata, o creditamento encerra a prestação. Uma vez creditados e utilizados, não há direito de arrependimento sobre os Z Bucks já entregues, ressalvado o que a lei determinar.' },
  { h: 'Estorno e chargeback', p: 'Se algo deu errado, fale com a gente primeiro no #abrir-ticket: a gente resolve. Abrir um estorno, contestação ou chargeback sem falar com o suporte antes faz com que os Z Bucks e os itens correspondentes sejam revogados, e a sua conta poderá ser suspensa ou removida (inclusive impedindo a criação de novas contas), sem prejuízo das medidas cabíveis.' },
  { h: 'Idade e responsável', p: 'As contribuições são restritas a maiores de 18 anos. Ao contribuir, você declara ser o titular do meio de pagamento utilizado ou ter autorização expressa do responsável. Contribuições feitas por menores sem autorização poderão ser canceladas e os Z Bucks revogados.' },
  { h: 'Pagamento', p: 'A forma preferencial é o PIX; o cartão também está disponível. O pagamento é processado pelo Mercado Pago, um terceiro, sujeito aos termos da plataforma dele. O Project Gen Z não vê nem guarda os dados do seu cartão ou conta bancária. Nós só recebemos a confirmação de que o pagamento foi aprovado para creditar os seus Z Bucks.' },
  { h: 'Mudanças e encerramento', p: 'Podemos alterar, suspender ou encerrar o servidor, a loja, os Z Bucks ou qualquer item virtual, e reajustar os valores dos pacotes, o preço dos itens e a economia de Z Bucks, a qualquer momento. Se a sua conta for banida por quebrar as regras, você perde o acesso aos itens e aos Z Bucks, sem reembolso. Caso o servidor deixe de operar, os itens e os Z Bucks são perdidos, sem direito a reembolso, ressalvado o que a lei exigir.' },
  { h: 'Project Zomboid', p: 'O Project Gen Z é um servidor e mod independente, de comunidade. Não é afiliado, patrocinado nem endossado pela The Indie Stone nem por Project Zomboid. As marcas pertencem aos seus respectivos titulares.' },
  { h: 'Suporte e foro', p: 'Dúvidas ou problemas com uma contribuição: abra um ticket no canal #abrir-ticket do nosso Discord. Fica eleito o foro brasileiro, e os dados ligados ao pagamento são tratados conforme a nossa Política de Privacidade e a LGPD.' },
];

// icone da moeda Z Bucks (reusavel ao lado de qualquer saldo)
function ZbIcon({ size = 20 }) {
  return <img src={ZB_ICON} alt="ZB" style={{ width: size, height: size, objectFit: 'contain', verticalAlign: 'middle', flexShrink: 0 }} />;
}

// ── Card 3D de pacote de doacao (tilt + glare seguindo o mouse) ─────────
function DonateCard({ pkg, onPick }) {
  const ref = React.useRef(null);
  const hot = !!pkg.highlight;
  const accent = DN_ACCENT;

  const onMove = (e) => {
    const el = ref.current; if (!el) return;
    const r = el.getBoundingClientRect();
    const px = (e.clientX - r.left) / r.width;
    const py = (e.clientY - r.top) / r.height;
    const MAX = 9;
    el.style.transform = `rotateX(${((0.5 - py) * 2 * MAX).toFixed(2)}deg) rotateY(${((px - 0.5) * 2 * MAX).toFixed(2)}deg) scale(1.03)`;
    el.style.setProperty('--gx', (px * 100).toFixed(1) + '%');
    el.style.setProperty('--gy', (py * 100).toFixed(1) + '%');
  };
  const reset = () => { if (ref.current) ref.current.style.transform = 'rotateX(0deg) rotateY(0deg) scale(1)'; };

  return (
    <div style={{ perspective: 1000 }}>
      <div ref={ref} onMouseMove={onMove} onMouseLeave={reset}
        style={{
          position: 'relative', transformStyle: 'preserve-3d', willChange: 'transform',
          transition: 'transform 0.25s ease', height: '100%', paddingBottom: 22,
          background: hot
            ? 'linear-gradient(160deg, rgba(30,40,12,0.92) 0%, rgba(18,18,18,0.96) 62%)'
            : 'rgba(22,22,22,0.86)',
          border: `1px solid ${hot ? 'rgba(168,255,0,0.4)' : 'rgba(255,255,255,0.08)'}`,
          borderTop: `3px solid ${accent}`,
          boxShadow: hot ? '0 18px 44px rgba(0,0,0,0.45)' : 'none',
        }}>
        {/* brilho que segue o mouse */}
        <div style={{ position: 'absolute', inset: 0, pointerEvents: 'none', zIndex: 5,
          background: `radial-gradient(circle at var(--gx,50%) var(--gy,50%), rgba(168,255,0,0.15) 0%, transparent 46%)` }} />

        {hot && (
          <div style={{ position: 'absolute', top: 14, right: 14, zIndex: 6,
            fontFamily: 'Share Tech Mono', fontSize: 9, fontWeight: 700, letterSpacing: '0.14em',
            color: '#0b0b0b', background: accent, padding: '4px 9px', transform: 'translateZ(40px)' }}>
            ★ MELHOR VALOR
          </div>
        )}

        {/* arte do pacote (pop pra frente no 3D) */}
        <div style={{ position: 'relative', height: 200, display: 'flex', alignItems: 'center', justifyContent: 'center',
          background: 'radial-gradient(circle at 50% 45%, rgba(168,255,0,0.10) 0%, transparent 66%)',
          transform: 'translateZ(46px)' }}>
          {pkg.image
            ? <img src={pkg.image} alt={pkg.label} style={{ maxWidth: '74%', maxHeight: '92%', objectFit: 'contain', filter: 'drop-shadow(0 10px 22px rgba(0,0,0,0.6))' }} />
            : <ZbIcon size={90} />}
        </div>

        {/* corpo */}
        <div style={{ padding: '0 22px', transform: 'translateZ(22px)' }}>
          <div style={{ fontFamily: 'Share Tech Mono', fontSize: 9, color: accent, letterSpacing: '0.16em', marginBottom: 4 }}>
            {(pkg.label || '').toUpperCase()}
          </div>

          {/* total de ZB */}
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 2 }}>
            <ZbIcon size={26} />
            <span style={{ fontFamily: 'Rajdhani', fontWeight: 700, fontSize: 30, color: '#fff', lineHeight: 1 }}>{dnFmt(pkg.total_zb)}</span>
            <span style={{ fontFamily: 'Share Tech Mono', fontSize: 12, color: 'rgba(255,255,255,0.45)' }}>ZB</span>
          </div>

          {/* bonus */}
          <div style={{ fontFamily: 'Rajdhani', fontWeight: 600, fontSize: 13, color: pkg.bonus_pct > 0 ? accent : 'rgba(255,255,255,0.35)', minHeight: 20, marginBottom: 14 }}>
            {pkg.bonus_pct > 0 ? `+${pkg.bonus_pct}% de bônus (${dnFmt(pkg.bonus_zb)} ZB extra)` : 'valor base'}
          </div>

          {/* botao doar */}
          <button onClick={() => onPick(pkg)} style={{
            width: '100%', background: accent, border: 'none', color: '#111',
            fontFamily: 'Rajdhani', fontWeight: 700, fontSize: 15, letterSpacing: '0.05em',
            padding: '12px 16px', cursor: 'pointer', textTransform: 'uppercase',
            clipPath: 'polygon(0 0, calc(100% - 9px) 0, 100% 9px, 100% 100%, 9px 100%, 0 calc(100% - 9px))',
            transition: 'box-shadow .2s',
          }}
            onMouseEnter={e => e.currentTarget.style.boxShadow = '0 0 20px rgba(168,255,0,0.5)'}
            onMouseLeave={e => e.currentTarget.style.boxShadow = 'none'}
          >Doar R$ {dnBRL(pkg.price_brl)}</button>
        </div>
      </div>
    </div>
  );
}

// ── Modal: politica com SCROLL OBRIGATORIO + CHECKBOX de concordancia ────
function DonatePolicyModal({ pkg, onClose, onConfirm, busy, err }) {
  const [reachedEnd, setReachedEnd] = React.useState(false);
  const [agreed, setAgreed] = React.useState(false);
  const scrollRef = React.useRef(null);

  const onScroll = () => {
    const el = scrollRef.current; if (!el) return;
    if (el.scrollTop + el.clientHeight >= el.scrollHeight - 24) setReachedEnd(true);
  };
  // se o conteudo couber sem rolar, ja considera lido
  React.useEffect(() => {
    const el = scrollRef.current; if (!el) return;
    if (el.scrollHeight <= el.clientHeight + 24) setReachedEnd(true);
  }, []);

  const canContinue = reachedEnd && agreed && !busy;

  return (
    <div onClick={onClose} style={{
      position: 'fixed', inset: 0, zIndex: 10000, background: 'rgba(0,0,0,0.72)',
      backdropFilter: 'blur(4px)', display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '5vw',
    }}>
      <div onClick={e => e.stopPropagation()} style={{
        width: '100%', maxWidth: 560, maxHeight: '88vh', display: 'flex', flexDirection: 'column',
        background: '#101310', border: '1px solid rgba(168,255,0,0.22)',
        clipPath: 'polygon(0 0, calc(100% - 14px) 0, 100% 14px, 100% 100%, 14px 100%, 0 calc(100% - 14px))',
      }}>
        {/* cabecalho */}
        <div style={{ padding: '20px 24px 14px', borderBottom: '1px solid rgba(255,255,255,0.08)' }}>
          <div style={{ fontFamily: 'Share Tech Mono', fontSize: 10, color: DN_ACCENT, letterSpacing: '0.16em', marginBottom: 6 }}>POLÍTICA DE DONATE</div>
          <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
            <ZbIcon size={28} />
            <span style={{ fontFamily: 'Rajdhani', fontWeight: 700, fontSize: 20, color: '#fff' }}>
              Doar R$ {dnBRL(pkg.price_brl)} <span style={{ color: DN_ACCENT }}>= {dnFmt(pkg.total_zb)} ZB</span>
            </span>
          </div>
        </div>

        {/* texto rolavel */}
        <div ref={scrollRef} onScroll={onScroll} style={{ overflowY: 'auto', padding: '18px 24px', flex: 1 }}>
          {DONATE_POLICY.map((b, i) => (
            <div key={i} style={{ marginBottom: 16 }}>
              <div style={{ fontFamily: 'Rajdhani', fontWeight: 700, fontSize: 15, color: DN_ACCENT, textTransform: 'uppercase', letterSpacing: '0.03em', marginBottom: 5 }}>{b.h}</div>
              <p style={{ margin: 0, fontFamily: 'Rajdhani', fontWeight: 500, fontSize: 14, lineHeight: 1.6, color: 'rgba(255,255,255,0.72)' }}>{b.p}</p>
            </div>
          ))}
          <div style={{ fontFamily: 'Share Tech Mono', fontSize: 11, color: 'rgba(255,255,255,0.3)', textAlign: 'center', padding: '6px 0 2px' }}>— fim da política —</div>
        </div>

        {/* rodape / acao */}
        <div style={{ padding: '14px 24px 20px', borderTop: '1px solid rgba(255,255,255,0.08)' }}>
          {err && <p style={{ color: '#ff8a8a', fontSize: 12.5, margin: '0 0 10px' }}>{err}</p>}
          {!reachedEnd && (
            <p style={{ fontFamily: 'Share Tech Mono', fontSize: 11, color: 'rgba(255,255,255,0.4)', margin: '0 0 12px', textAlign: 'center' }}>
              role a política até o fim para liberar
            </p>
          )}

          {/* checkbox de concordancia (so libera depois de rolar) */}
          <label style={{ display: 'flex', alignItems: 'flex-start', gap: 10, marginBottom: 14, cursor: reachedEnd ? 'pointer' : 'not-allowed', opacity: reachedEnd ? 1 : 0.45 }}>
            <input type="checkbox" checked={agreed} disabled={!reachedEnd}
              onChange={e => setAgreed(e.target.checked)}
              style={{ marginTop: 2, width: 17, height: 17, accentColor: DN_ACCENT, flexShrink: 0, cursor: reachedEnd ? 'pointer' : 'not-allowed' }} />
            <span style={{ fontFamily: 'Rajdhani', fontWeight: 500, fontSize: 13.5, lineHeight: 1.5, color: 'rgba(255,255,255,0.78)' }}>
              Li e concordo com a Política de Donate e confirmo que tenho 18 anos ou mais.
            </span>
          </label>

          <div style={{ display: 'flex', gap: 10 }}>
            <button onClick={onClose} style={{
              background: 'transparent', border: '1px solid rgba(255,255,255,0.2)', color: 'rgba(255,255,255,0.6)',
              fontFamily: 'Rajdhani', fontWeight: 700, fontSize: 13, letterSpacing: '0.06em',
              padding: '12px 18px', cursor: 'pointer', textTransform: 'uppercase',
            }}>Cancelar</button>
            <button onClick={() => onConfirm(pkg)} disabled={!canContinue} style={{
              flex: 1, background: canContinue ? DN_ACCENT : 'rgba(255,255,255,0.07)',
              color: canContinue ? '#111' : 'rgba(255,255,255,0.35)', border: 'none',
              fontFamily: 'Rajdhani', fontWeight: 700, fontSize: 14, letterSpacing: '0.06em',
              padding: '12px 18px', cursor: canContinue ? 'pointer' : 'not-allowed', textTransform: 'uppercase',
              clipPath: 'polygon(0 0, calc(100% - 9px) 0, 100% 9px, 100% 100%, 9px 100%, 0 calc(100% - 9px))',
            }}>{busy ? 'Abrindo pagamento...' : 'Continuar para o pagamento'}</button>
          </div>
        </div>
      </div>
    </div>
  );
}

// ── Aviso de retorno do Mercado Pago (?donate=ok|fail) ─────────────────
function readDonateReturn() {
  try {
    const q = new URLSearchParams(window.location.search);
    const s = q.get('donate');
    if (!s) return null;
    const clean = window.location.origin + window.location.pathname + window.location.hash;
    window.history.replaceState({}, '', clean);
    if (s === 'ok') return { ok: true, msg: 'Doação recebida! Seus Z Bucks já estão na sua conta. Valeu pelo apoio!' };
    if (s === 'pending') return { ok: true, msg: 'Pagamento em processamento. Assim que aprovar, os Z Bucks entram na sua conta.' };
    return { ok: false, msg: 'A doação não foi concluída. Nada foi cobrado. Você pode tentar de novo quando quiser.' };
  } catch (e) { return null; }
}

// ── Pagina DONATE ───────────────────────────────────────────────────────
function DonatePage({ onNavigate }) {
  const session = window.useGzAuth ? window.useGzAuth() : null;
  const [pkgs, setPkgs] = React.useState(undefined);
  const [wallet, setWallet] = React.useState(undefined);
  const [picked, setPicked] = React.useState(null);
  const [busy, setBusy] = React.useState(false);
  const [flowErr, setFlowErr] = React.useState('');
  const [ret, setRet] = React.useState(() => readDonateReturn());

  React.useEffect(() => {
    let alive = true;
    if (window.gzCreditPackages) window.gzCreditPackages().then(p => { if (alive) setPkgs(p || []); });
    return () => { alive = false; };
  }, []);

  React.useEffect(() => {
    if (!session || !window.gzWallet) { setWallet(null); return; }
    let alive = true;
    window.gzWallet().then(w => { if (alive) setWallet(w); });
    return () => { alive = false; };
  }, [session && session.user && session.user.id]);

  function pick(pkg) {
    if (!session) { onNavigate && onNavigate('auth'); return; }
    setFlowErr(''); setPicked(pkg);
  }

  function confirm(pkg) {
    setBusy(true); setFlowErr('');
    Promise.resolve(window.gzDonateStart(pkg.id)).then(r => {
      if (r && r.url) { window.location.href = r.url; return; } // vai pro Mercado Pago
      setBusy(false);
      if (r && r.error === 'payments_disabled') {
        setFlowErr('O pagamento ainda está sendo configurado. Volte em breve!');
      } else if (r && r.error === 'not_authenticated') {
        setFlowErr('Faça login de novo para continuar.');
      } else if (r && r.error === 'no_account') {
        setFlowErr('Complete seu cadastro de jogador antes de doar.');
      } else {
        setFlowErr('Não consegui abrir o pagamento agora. Tente de novo.');
      }
    }).catch(() => { setBusy(false); setFlowErr('Não consegui abrir o pagamento agora. Tente de novo.'); });
  }

  const wrap = { minHeight: '100vh', padding: '100px 5vw 80px' };
  const inner = { maxWidth: 1100, margin: '0 auto' };

  return (
    <div style={wrap}>
      <div style={inner}>

        {/* header + saldo */}
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', flexWrap: 'wrap', gap: 16, marginBottom: 18 }}>
          <div>
            <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 10 }}>
              <div style={{ width: 24, height: 2, background: DN_ACCENT }} />
              <span style={{ fontFamily: 'Share Tech Mono', fontSize: 11, color: DN_ACCENT, letterSpacing: '0.18em' }}>APOIE O SERVIDOR</span>
            </div>
            <h1 style={{ fontFamily: 'Rajdhani', fontWeight: 700, fontSize: 'clamp(28px,4vw,52px)', textTransform: 'uppercase', lineHeight: 1 }}>
              DOE E GANHE<br /><span style={{ color: DN_ACCENT }}>Z BUCKS</span>
            </h1>
          </div>

          {/* saldo (so logado) */}
          {session && (
            <div style={{ border: '1px solid rgba(168,255,0,0.3)', background: 'rgba(168,255,0,0.05)', padding: '14px 22px', textAlign: 'right', minWidth: 180,
              clipPath: 'polygon(0 0, calc(100% - 10px) 0, 100% 10px, 100% 100%, 10px 100%, 0 calc(100% - 10px))' }}>
              <div style={{ fontFamily: 'Share Tech Mono', fontSize: 10, color: 'rgba(255,255,255,.45)', letterSpacing: '.14em', marginBottom: 6 }}>SEU SALDO</div>
              <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'flex-end', gap: 8 }}>
                <ZbIcon size={22} />
                <span style={{ fontFamily: 'Share Tech Mono', fontSize: 26, color: '#a8ff00', lineHeight: 1 }}>
                  {wallet === undefined ? '...' : dnFmt(wallet && wallet.balance)}
                </span>
                <span style={{ fontSize: 12, color: 'rgba(255,255,255,.5)' }}>ZB</span>
              </div>
            </div>
          )}
        </div>

        {/* aviso de retorno do pagamento */}
        {ret && (
          <div style={{ marginBottom: 24, padding: '12px 18px', fontSize: 14,
            border: `1px solid ${ret.ok ? 'rgba(168,255,0,.4)' : 'rgba(255,90,90,.4)'}`,
            background: ret.ok ? 'rgba(168,255,0,.08)' : 'rgba(255,90,90,.08)',
            color: ret.ok ? '#a8ff00' : '#ff8a8a' }}>{ret.msg}</div>
        )}

        {/* cards 3D */}
        {pkgs === undefined ? (
          <div style={{ fontFamily: 'Share Tech Mono', fontSize: 13, color: 'rgba(255,255,255,.4)', padding: '40px 0' }}>CARREGANDO PACOTES...</div>
        ) : pkgs.length === 0 ? (
          <div style={{ fontFamily: 'Rajdhani', fontSize: 16, color: 'rgba(255,255,255,.4)', padding: '40px 0' }}>Pacotes de doação em breve.</div>
        ) : (
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(230px, 1fr))', gap: 20, marginBottom: 56 }}>
            {pkgs.map(p => <DonateCard key={p.id} pkg={p} onPick={pick} />)}
          </div>
        )}

        {/* por que / onde investido */}
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(300px, 1fr))', gap: 22 }}>
          <div style={{ background: 'rgba(28,28,28,0.7)', border: '1px solid rgba(255,255,255,0.08)', borderTop: `2px solid ${DN_ACCENT}`, padding: '24px 26px' }}>
            <h3 style={{ fontFamily: 'Rajdhani', fontWeight: 700, fontSize: 19, color: '#fff', textTransform: 'uppercase', letterSpacing: '0.03em', margin: '0 0 10px' }}>Por que ganhar créditos?</h3>
            <p style={{ margin: 0, fontFamily: 'Rajdhani', fontWeight: 500, fontSize: 14.5, lineHeight: 1.65, color: 'rgba(255,255,255,0.68)' }}>
              O Donate você faz de livre e espontânea vontade para ajudar o servidor. Os Z Bucks são apenas um agradecimento pelo seu apoio, nunca uma cobrança para jogar.
            </p>
          </div>
          <div style={{ background: 'rgba(28,28,28,0.7)', border: '1px solid rgba(255,255,255,0.08)', borderTop: `2px solid ${DN_ACCENT}`, padding: '24px 26px' }}>
            <h3 style={{ fontFamily: 'Rajdhani', fontWeight: 700, fontSize: 19, color: '#fff', textTransform: 'uppercase', letterSpacing: '0.03em', margin: '0 0 10px' }}>Onde o Donate é investido?</h3>
            <p style={{ margin: 0, fontFamily: 'Rajdhani', fontWeight: 500, fontSize: 14.5, lineHeight: 1.65, color: 'rgba(255,255,255,0.68)' }}>
              100% vai para o pagamento do host e para a infraestrutura do servidor (o banco, o site, as ferramentas que seguram tudo de pé). Projeto comunitário, sem fins lucrativos.
            </p>
          </div>
        </div>

      </div>

      {picked && (
        <DonatePolicyModal pkg={picked} busy={busy} err={flowErr}
          onClose={() => { if (!busy) { setPicked(null); setFlowErr(''); } }}
          onConfirm={confirm} />
      )}
    </div>
  );
}

Object.assign(window, { DonatePage, ZbIcon });
