/* TETR!Z PASS — App principal (vitrine + evento + login + admin/organizador) */
const { useState, useEffect, useCallback } = React;

// ─── helpers HTTP ───
async function api(method, url, body) {
  const opts = { method, credentials: 'same-origin', headers: {} };
  if (body !== undefined) { opts.headers['Content-Type'] = 'application/json'; opts.body = JSON.stringify(body); }
  const r = await fetch(url, opts);
  let data = {};
  try { data = await r.json(); } catch {}
  if (!r.ok || data.ok === false) throw new Error(data.msg || `HTTP ${r.status}`);
  return data;
}

// ─── router URL-based ───
function pathToRoute(p) {
  p = (p || '/').replace(/\/+$/,'') || '/';
  const m1 = p.match(/^\/evento\/(.+)$/);  if (m1) return { view: 'event',   slug: decodeURIComponent(m1[1]) };
  if (p === '/login')                       return { view: 'login' };
  if (p.startsWith('/admin'))               return { view: 'admin', sub: p.slice(7) || 'events' };
  if (p.startsWith('/organizador'))         return { view: 'org',   sub: p.slice(14) || 'events' };
  return { view: 'home' };
}
function routeToPath(r) {
  if (r.view === 'event') return '/evento/' + r.slug;
  if (r.view === 'login') return '/login';
  if (r.view === 'admin') return '/admin' + (r.sub ? '/' + r.sub : '');
  if (r.view === 'org')   return '/organizador' + (r.sub ? '/' + r.sub : '');
  return '/';
}

function fmtBRL(n) { return (n || 0).toLocaleString('pt-BR', { style: 'currency', currency: 'BRL' }); }
function fmtDate(iso) {
  if (!iso) return '';
  const d = new Date(iso); if (isNaN(d)) return iso;
  return d.toLocaleDateString('pt-BR', { day: '2-digit', month: 'short', year: 'numeric' }) + ' · ' + d.toLocaleTimeString('pt-BR', { hour: '2-digit', minute: '2-digit' });
}
function fmtDateInput(iso) {
  if (!iso) return '';
  const d = new Date(iso); if (isNaN(d)) return iso.slice(0, 16);
  const pad = (n) => String(n).padStart(2, '0');
  return `${d.getFullYear()}-${pad(d.getMonth()+1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}`;
}

// ─── Header ───
function Header({ route, navigate, me, onLogout }) {
  return (
    <header className="app-header">
      <div className="app-shell app-header-row">
        <div className="app-brand" onClick={() => navigate({ view: 'home' })}>
          TETR<span className="dot">!</span>Z PASS
        </div>
        <nav className="app-nav">
          <a className={route.view === 'home' ? 'active' : ''} onClick={() => navigate({ view: 'home' })}>Vitrine</a>
          {me && me.role === 'admin'     && <a className={route.view === 'admin' ? 'active' : ''} onClick={() => navigate({ view: 'admin' })}>Admin</a>}
          {me && me.role === 'organizer' && <a className={route.view === 'org'   ? 'active' : ''} onClick={() => navigate({ view: 'org' })}>Meus eventos</a>}
        </nav>
        <div className="row">
          {me ? (
            <>
              <span style={{ fontSize: 12, color: 'var(--muted)' }}>{me.name}</span>
              <button className="btn btn-ghost btn-sm" onClick={onLogout}>Sair</button>
            </>
          ) : (
            <button className="btn btn-primary btn-sm" onClick={() => navigate({ view: 'login' })}>Entrar</button>
          )}
        </div>
      </div>
    </header>
  );
}

// ─── Vitrine pública ───
function Vitrine({ navigate }) {
  const [events, setEvents] = useState(null);
  useEffect(() => {
    api('GET', '/api/public/events').then(r => setEvents(r.events || [])).catch(() => setEvents([]));
  }, []);
  if (!events) return <div className="empty">Carregando eventos…</div>;
  return (
    <div className="app-shell" style={{ padding: '32px 20px' }}>
      <h1 style={{ fontFamily: 'Sora', fontSize: 32, margin: '0 0 6px' }}>Eventos abertos</h1>
      <p style={{ color: 'var(--muted)', margin: '0 0 24px' }}>Os eventos publicados aparecem aqui.</p>
      {events.length === 0 ? (
        <div className="empty">Nenhum evento publicado por enquanto.</div>
      ) : (
        <div className="grid-events">
          {events.map(e => (
            <div key={e.id} className="event-card" onClick={() => navigate({ view: 'event', slug: e.slug })}>
              <div className="event-card__banner" style={e.bannerUrl ? { backgroundImage: `url(${e.bannerUrl})` } : {}}>
                {!e.bannerUrl && (e.title || 'Sem capa')}
              </div>
              <div className="event-card__body">
                <div className="app-pill yellow">{fmtDate(e.startsAt)}</div>
                <h3 className="event-card__title">{e.title}</h3>
                <div className="event-card__meta">
                  <span>📍 {e.venueName || e.city || '—'}</span>
                  <span>· {e.organizerName}</span>
                </div>
              </div>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

// ─── Página pública do evento ───
function EventPage({ slug, navigate }) {
  const [state, setState] = useState({ loading: true });
  useEffect(() => {
    api('GET', `/api/public/events/${encodeURIComponent(slug)}`)
      .then(r => setState({ loading: false, event: r.event, batches: r.batches }))
      .catch(err => setState({ loading: false, error: err.message }));
  }, [slug]);
  if (state.loading) return <div className="empty">Carregando…</div>;
  if (state.error)   return <div className="empty">Evento não encontrado.</div>;
  const { event: ev, batches } = state;
  return (
    <div className="app-shell" style={{ padding: '0 20px 40px' }}>
      <div className="hero-evt" style={ev.banner_url ? { backgroundImage: `url(${ev.banner_url})` } : {}}>
        <div className="hero-evt__content">
          <div className="app-pill yellow">{fmtDate(ev.starts_at)}</div>
          <h1 className="hero-evt__title">{ev.title}</h1>
          {ev.subtitle && <p style={{ color: 'var(--muted)', maxWidth: 600 }}>{ev.subtitle}</p>}
          <div style={{ display: 'flex', gap: 12, marginTop: 8, fontSize: 13, color: 'var(--muted)' }}>
            <span>📍 {ev.venue_name || '—'}{ev.city ? ' · ' + ev.city : ''}</span>
            <span>· por {ev.organizerName}</span>
          </div>
        </div>
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: '1.4fr 1fr', gap: 24, marginTop: 24 }}>
        <div>
          <h3 style={{ fontFamily: 'Sora', fontSize: 18 }}>Sobre o evento</h3>
          <p style={{ color: 'var(--muted)', lineHeight: 1.6, whiteSpace: 'pre-wrap' }}>{ev.description || 'Sem descrição.'}</p>
        </div>
        <div className="app-card">
          <h3 style={{ fontFamily: 'Sora', fontSize: 16, marginTop: 0 }}>Ingressos</h3>
          {batches.length === 0 ? (
            <p style={{ color: 'var(--muted)', fontSize: 13 }}>Ingressos serão liberados em breve.</p>
          ) : batches.map(b => (
            <div key={b.id} className="batch-row">
              <div>
                <div className="batch-row__name">{b.name}</div>
                <div style={{ fontSize: 11, color: 'var(--muted)' }}>{b.remaining > 0 ? `${b.remaining} disponíveis` : 'Esgotado'}</div>
              </div>
              <div className="batch-row__price">{fmtBRL(b.price)}</div>
            </div>
          ))}
          <button className="btn btn-primary btn-lg" style={{ width: '100%', marginTop: 12 }} disabled>
            Comprar (em breve)
          </button>
          <p style={{ fontSize: 11, color: 'var(--muted-2)', textAlign: 'center', marginTop: 8 }}>
            Checkout via Asaas será habilitado na próxima fase.
          </p>
        </div>
      </div>
    </div>
  );
}

// ─── Login ───
function LoginPage({ onLogin, navigate }) {
  const [email, setEmail] = useState('');
  const [pwd, setPwd] = useState('');
  const [busy, setBusy] = useState(false);
  const [err, setErr] = useState('');
  const submit = async (e) => {
    e.preventDefault();
    setBusy(true); setErr('');
    try {
      await api('POST', '/api/auth/login', { email, password: pwd });
      const me = await api('GET', '/api/auth/me');
      onLogin(me.user);
    } catch (e) { setErr(e.message); setBusy(false); }
  };
  return (
    <div className="app-shell" style={{ padding: '60px 20px', display: 'grid', placeItems: 'center' }}>
      <form onSubmit={submit} className="app-card" style={{ width: '100%', maxWidth: 400 }}>
        <h2 style={{ fontFamily: 'Sora', marginTop: 0 }}>Entrar</h2>
        <label className="field">
          <span className="lbl">Email</span>
          <input type="email" value={email} onChange={e => setEmail(e.target.value)} required autoFocus/>
        </label>
        <label className="field">
          <span className="lbl">Senha</span>
          <input type="password" value={pwd} onChange={e => setPwd(e.target.value)} required/>
        </label>
        {err && <div style={{ color: 'var(--red)', fontSize: 12, marginBottom: 10 }}>{err}</div>}
        <button className="btn btn-primary" type="submit" disabled={busy} style={{ width: '100%' }}>
          {busy ? 'Entrando…' : 'Entrar'}
        </button>
      </form>
    </div>
  );
}

// ─── Form de organizador (admin) ───
function OrganizerForm({ initial, onClose, onSaved }) {
  const isEdit = !!initial;
  const [form, setForm] = useState({
    name: initial?.name || '',
    legalName: initial?.legal_name || '',
    document: initial?.document || '',
    birthDate: initial?.birth_date || '',
    contactEmail: initial?.contact_email || '',
    contactPhone: initial?.contact_phone || '',
    description: initial?.description || '',
    address: initial?.address || '',
    addressNumber: initial?.address_number || '',
    province: initial?.province || '',
    postalCode: initial?.postal_code || '',
    bankCode: initial?.bank_code || '',
    bankAgency: initial?.bank_agency || '',
    bankAccount: initial?.bank_account || '',
    bankAccountType: initial?.bank_account_type || 'CONTA_CORRENTE',
    pixKey: initial?.pix_key || '',
    pixKeyType: initial?.pix_key_type || 'EMAIL',
    loginEmail: '',
    loginPassword: '',
  });
  const set = (k, v) => setForm(f => ({ ...f, [k]: v }));
  const save = async () => {
    if (!form.name.trim()) return alert('Nome obrigatório');
    if (!isEdit && (!form.loginEmail || !form.loginPassword)) return alert('Login e senha obrigatórios');
    try {
      if (isEdit) await api('PATCH', `/api/admin/organizers/${initial.id}`, form);
      else        await api('POST',  '/api/admin/organizers', form);
      onSaved();
    } catch (e) { alert('Erro: ' + e.message); }
  };
  return (
    <div onClick={onClose} style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.6)', zIndex: 100, display: 'grid', placeItems: 'center', padding: 20, overflowY: 'auto' }}>
      <div onClick={e => e.stopPropagation()} className="app-card" style={{ width: '100%', maxWidth: 560, maxHeight: '90vh', overflowY: 'auto' }}>
        <h3 style={{ fontFamily: 'Sora', marginTop: 0 }}>{isEdit ? 'Editar organizador' : 'Novo organizador'}</h3>

        <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--muted)', textTransform: 'uppercase', letterSpacing: 0.5, marginBottom: 8 }}>Identificação</div>
        <label className="field"><span className="lbl">Nome / Marca *</span><input value={form.name} onChange={e => set('name', e.target.value)}/></label>
        <label className="field"><span className="lbl">Razão social (titular da conta)</span><input value={form.legalName} onChange={e => set('legalName', e.target.value)}/></label>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
          <label className="field"><span className="lbl">CNPJ / CPF</span><input value={form.document} onChange={e => set('document', e.target.value)} placeholder="00.000.000/0000-00"/></label>
          <label className="field"><span className="lbl">Data nasc. (se CPF)</span><input type="date" value={form.birthDate} onChange={e => set('birthDate', e.target.value)}/></label>
        </div>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
          <label className="field"><span className="lbl">Email contato</span><input type="email" value={form.contactEmail} onChange={e => set('contactEmail', e.target.value)}/></label>
          <label className="field"><span className="lbl">Celular</span><input value={form.contactPhone} onChange={e => set('contactPhone', e.target.value)} placeholder="(19) 99999-9999"/></label>
        </div>
        <label className="field"><span className="lbl">Descrição (perfil público)</span><textarea rows={2} value={form.description} onChange={e => set('description', e.target.value)}/></label>

        <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--muted)', textTransform: 'uppercase', letterSpacing: 0.5, margin: '14px 0 8px' }}>Endereço (exigido pela Asaas)</div>
        <div style={{ display: 'grid', gridTemplateColumns: '2fr 1fr', gap: 10 }}>
          <label className="field"><span className="lbl">Logradouro</span><input value={form.address} onChange={e => set('address', e.target.value)}/></label>
          <label className="field"><span className="lbl">Número</span><input value={form.addressNumber} onChange={e => set('addressNumber', e.target.value)}/></label>
        </div>
        <div style={{ display: 'grid', gridTemplateColumns: '2fr 1fr', gap: 10 }}>
          <label className="field"><span className="lbl">Bairro</span><input value={form.province} onChange={e => set('province', e.target.value)}/></label>
          <label className="field"><span className="lbl">CEP</span><input value={form.postalCode} onChange={e => set('postalCode', e.target.value)} placeholder="00000-000"/></label>
        </div>

        <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--muted)', textTransform: 'uppercase', letterSpacing: 0.5, margin: '14px 0 8px' }}>Recebimento (Pix recomendado)</div>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 2fr', gap: 10 }}>
          <label className="field"><span className="lbl">Tipo Pix</span>
            <select value={form.pixKeyType} onChange={e => set('pixKeyType', e.target.value)}>
              <option value="EMAIL">Email</option>
              <option value="CPF">CPF</option>
              <option value="CNPJ">CNPJ</option>
              <option value="PHONE">Telefone</option>
              <option value="EVP">Chave aleatória</option>
            </select>
          </label>
          <label className="field"><span className="lbl">Chave Pix</span><input value={form.pixKey} onChange={e => set('pixKey', e.target.value)}/></label>
        </div>
        <details style={{ marginBottom: 10, color: 'var(--muted)', fontSize: 12 }}>
          <summary style={{ cursor: 'pointer', padding: '4px 0' }}>Conta bancária tradicional (alternativa ao Pix)</summary>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 10, marginTop: 8 }}>
            <label className="field"><span className="lbl">Banco (cód)</span><input value={form.bankCode} onChange={e => set('bankCode', e.target.value)} placeholder="237"/></label>
            <label className="field"><span className="lbl">Agência</span><input value={form.bankAgency} onChange={e => set('bankAgency', e.target.value)}/></label>
            <label className="field"><span className="lbl">Conta</span><input value={form.bankAccount} onChange={e => set('bankAccount', e.target.value)}/></label>
          </div>
        </details>

        {!isEdit && (
          <>
            <div style={{ fontSize: 11, fontWeight: 700, color: 'var(--muted)', textTransform: 'uppercase', letterSpacing: 0.5, margin: '14px 0 8px' }}>Login do organizador</div>
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
              <label className="field"><span className="lbl">Email *</span><input type="email" value={form.loginEmail} onChange={e => set('loginEmail', e.target.value)}/></label>
              <label className="field"><span className="lbl">Senha *</span><input type="text" value={form.loginPassword} onChange={e => set('loginPassword', e.target.value)}/></label>
            </div>
          </>
        )}
        <div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end', marginTop: 16 }}>
          <button className="btn btn-ghost btn-sm" onClick={onClose}>Cancelar</button>
          <button className="btn btn-primary btn-sm" onClick={save}>Salvar</button>
        </div>
      </div>
    </div>
  );
}

// ─── Admin: lista organizadores ───
function AdminOrganizers() {
  const [list, setList] = useState([]);
  const [editing, setEditing] = useState(null);
  const [showForm, setShowForm] = useState(false);
  const [busyId, setBusyId] = useState(null);
  const load = () => api('GET', '/api/admin/organizers').then(r => setList(r.organizers || []));
  useEffect(() => { load(); }, []);
  const onDelete = async (o) => {
    if (!confirm(`Excluir organizador "${o.name}" e TODOS os eventos/usuários dele?`)) return;
    try { await api('DELETE', `/api/admin/organizers/${o.id}`); load(); }
    catch (e) { alert('Erro: ' + e.message); }
  };
  const createSubaccount = async (o) => {
    if (!confirm(`Criar subconta Asaas pra "${o.name}"? Os dados bancários + endereço serão enviados pra Asaas.`)) return;
    setBusyId(o.id);
    try {
      const r = await api('POST', `/api/admin/organizers/${o.id}/asaas-subaccount`);
      alert(`✓ Subconta criada\nID: ${r.accountId}\nWallet: ${r.walletId || '(aguardando)'}`);
      load();
    } catch (e) { alert('Erro: ' + e.message); }
    setBusyId(null);
  };
  return (
    <>
      <div style={{ display: 'flex', alignItems: 'center', marginBottom: 16 }}>
        <h2 style={{ fontFamily: 'Sora', margin: 0 }}>Organizadores</h2>
        <button className="btn btn-primary btn-sm" style={{ marginLeft: 'auto' }} onClick={() => { setEditing(null); setShowForm(true); }}>+ Novo</button>
      </div>
      {list.length === 0 ? <div className="empty">Nenhum organizador cadastrado.</div> : (
        <table className="app-table">
          <thead><tr><th>Nome</th><th>Email</th><th>Asaas</th><th>Eventos</th><th></th></tr></thead>
          <tbody>
            {list.map(o => (
              <tr key={o.id}>
                <td><strong>{o.name}</strong>{!o.active && <span className="app-pill gray" style={{ marginLeft: 6 }}>inativo</span>}</td>
                <td style={{ color: 'var(--muted)' }}>{o.contact_email}</td>
                <td>
                  {o.asaas_account_id
                    ? <span className="app-pill green" title={o.asaas_account_id}>✓ Subconta</span>
                    : <button className="btn btn-ghost btn-sm" onClick={() => createSubaccount(o)} disabled={busyId === o.id}>
                        {busyId === o.id ? 'Criando…' : '+ Asaas'}
                      </button>}
                </td>
                <td>{o.eventsCount}</td>
                <td style={{ textAlign: 'right', whiteSpace: 'nowrap' }}>
                  <button className="btn btn-ghost btn-sm" onClick={() => { setEditing(o); setShowForm(true); }}>Editar</button>
                  <button className="btn btn-danger btn-sm" style={{ marginLeft: 6 }} onClick={() => onDelete(o)}>🗑</button>
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      )}
      {showForm && <OrganizerForm initial={editing} onClose={() => setShowForm(false)} onSaved={() => { setShowForm(false); load(); }}/>}
    </>
  );
}

// ─── Admin: Configurações Asaas ───
function AdminSettings() {
  const [data, setData] = useState(null);
  const [form, setForm] = useState({ asaas_master_key: '', asaas_env: 'sandbox', asaas_webhook_secret: '', platform_fee_percent: '' });
  const [busy, setBusy] = useState(false);
  const [msg, setMsg] = useState('');
  const load = () => api('GET', '/api/admin/settings').then(r => {
    setData(r.settings);
    setForm({
      asaas_master_key: '',
      asaas_env: r.settings.asaas_env || 'sandbox',
      asaas_webhook_secret: r.settings.asaas_webhook_secret || '',
      platform_fee_percent: r.settings.platform_fee_percent || '',
    });
  });
  useEffect(() => { load(); }, []);
  const save = async () => {
    setBusy(true); setMsg('');
    try {
      const payload = { ...form };
      if (!payload.asaas_master_key) delete payload.asaas_master_key; // não sobrescreve com vazio
      await api('PUT', '/api/admin/settings', payload);
      setMsg('Configurações salvas.');
      load();
    } catch (e) { setMsg('Erro: ' + e.message); }
    setBusy(false);
  };
  if (!data) return <div className="empty">Carregando…</div>;
  return (
    <>
      <h2 style={{ fontFamily: 'Sora', margin: '0 0 16px' }}>Configurações Asaas</h2>
      <div className="app-card">
        <label className="field">
          <span className="lbl">Ambiente</span>
          <select value={form.asaas_env} onChange={e => setForm(f => ({ ...f, asaas_env: e.target.value }))}>
            <option value="sandbox">Sandbox (testes)</option>
            <option value="production">Produção</option>
          </select>
        </label>
        <label className="field">
          <span className="lbl">API Key Master {data.asaas_master_key_set && <span className="app-pill green" style={{ marginLeft: 6 }}>configurada · {data.asaas_master_key}</span>}</span>
          <input type="text" value={form.asaas_master_key}
            placeholder={data.asaas_master_key_set ? 'deixe em branco pra manter a atual' : '$aact_prod_...'}
            onChange={e => setForm(f => ({ ...f, asaas_master_key: e.target.value }))}/>
        </label>
        <label className="field">
          <span className="lbl">Webhook Secret (Asaas-Access-Token enviado pelo Asaas no header)</span>
          <input type="text" value={form.asaas_webhook_secret}
            onChange={e => setForm(f => ({ ...f, asaas_webhook_secret: e.target.value }))}/>
          <div style={{ fontSize: 11, color: 'var(--muted-2)', marginTop: 4 }}>
            Configure este secret no painel Asaas em <strong>Notificações → Webhooks</strong> com URL: <code>https://tetrizpass.com.br/api/asaas/webhook</code>
          </div>
        </label>
        <label className="field">
          <span className="lbl">Taxa Tetriz (% por evento — opcional)</span>
          <input type="number" min="0" max="100" step="0.1" value={form.platform_fee_percent}
            onChange={e => setForm(f => ({ ...f, platform_fee_percent: e.target.value }))}
            placeholder="0"/>
          <div style={{ fontSize: 11, color: 'var(--muted-2)', marginTop: 4 }}>
            Se preenchido, Tetriz recebe essa % de cada venda automaticamente via split. Em branco = organizador recebe 100% (descontada só a taxa Asaas).
          </div>
        </label>
        {msg && <div style={{ fontSize: 12, color: msg.startsWith('Erro') ? 'var(--red)' : 'var(--green)', marginBottom: 10 }}>{msg}</div>}
        <button className="btn btn-primary" onClick={save} disabled={busy}>{busy ? 'Salvando…' : 'Salvar'}</button>
      </div>
      <div className="app-card" style={{ marginTop: 16, background: 'var(--surface-2)' }}>
        <h4 style={{ fontFamily: 'Sora', margin: '0 0 8px' }}>Status integração</h4>
        <div style={{ fontSize: 13 }}>
          {data.asaas_configured
            ? <span className="app-pill green">✓ Asaas configurado · ambiente: {data.asaas_env || 'sandbox'}</span>
            : <span className="app-pill gray">⚠ Asaas não configurado — checkout ainda não funciona</span>}
        </div>
        <details style={{ marginTop: 12, fontSize: 12, color: 'var(--muted)' }}>
          <summary style={{ cursor: 'pointer' }}>Como liberar Marketplace no Asaas?</summary>
          <ol style={{ marginTop: 8, paddingLeft: 18, lineHeight: 1.7 }}>
            <li>Logar no painel Asaas com a conta Tetriz</li>
            <li>Acessar <strong>Configurações → Integrações → API</strong></li>
            <li>Solicitar <strong>API de Marketplace / Subcontas</strong> (botão "Solicitar" ou via chat de suporte)</li>
            <li>Aprovação leva 1–3 dias úteis (KYC)</li>
            <li>Quando aprovar, gerar a <strong>API Key Master</strong> e colar acima</li>
            <li>Em <strong>Notificações → Webhooks</strong>, criar webhook apontando pra <code>/api/asaas/webhook</code> com o secret acima</li>
          </ol>
        </details>
      </div>
    </>
  );
}

// ─── Form de evento (admin + organizador) ───
function EventForm({ initial, organizers, defaultOrgId, onClose, onSaved }) {
  const isEdit = !!initial;
  const [form, setForm] = useState({
    organizerId: initial?.organizer_id || defaultOrgId || (organizers[0]?.id) || '',
    title: initial?.title || '',
    subtitle: initial?.subtitle || '',
    description: initial?.description || '',
    venueName: initial?.venue_name || '',
    venueAddress: initial?.venue_address || '',
    city: initial?.city || '',
    state: initial?.state || '',
    startsAt: initial?.starts_at ? fmtDateInput(initial.starts_at) : '',
    endsAt: initial?.ends_at ? fmtDateInput(initial.ends_at) : '',
    bannerUrl: initial?.banner_url || '',
    theme: initial?.theme || 'dark',
    status: initial?.status || 'draft',
  });
  const set = (k, v) => setForm(f => ({ ...f, [k]: v }));
  const handleUpload = async (e) => {
    const f = e.target.files?.[0]; if (!f) return;
    const fd = new FormData(); fd.append('file', f);
    const r = await fetch('/api/upload', { method: 'POST', body: fd, credentials: 'same-origin' });
    const data = await r.json();
    if (data.ok) set('bannerUrl', data.url);
    e.target.value = '';
  };
  const save = async () => {
    if (!form.title.trim()) return alert('Título obrigatório');
    if (!form.startsAt)     return alert('Data de início obrigatória');
    try {
      if (isEdit) await api('PATCH', `/api/events/${initial.id}`, form);
      else        await api('POST',  '/api/events', form);
      onSaved();
    } catch (e) { alert('Erro: ' + e.message); }
  };
  return (
    <div onClick={onClose} style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.6)', zIndex: 100, display: 'grid', placeItems: 'center', padding: 20, overflowY: 'auto' }}>
      <div onClick={e => e.stopPropagation()} className="app-card" style={{ width: '100%', maxWidth: 640, maxHeight: '90vh', overflowY: 'auto' }}>
        <h3 style={{ fontFamily: 'Sora', marginTop: 0 }}>{isEdit ? 'Editar evento' : 'Novo evento'}</h3>
        {organizers && organizers.length > 0 && (
          <label className="field"><span className="lbl">Organizador</span>
            <select value={form.organizerId} onChange={e => set('organizerId', e.target.value)}>
              {organizers.map(o => <option key={o.id} value={o.id}>{o.name}</option>)}
            </select>
          </label>
        )}
        <label className="field"><span className="lbl">Título *</span><input value={form.title} onChange={e => set('title', e.target.value)}/></label>
        <label className="field"><span className="lbl">Subtítulo</span><input value={form.subtitle} onChange={e => set('subtitle', e.target.value)}/></label>
        <label className="field"><span className="lbl">Descrição</span><textarea rows={4} value={form.description} onChange={e => set('description', e.target.value)}/></label>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
          <label className="field"><span className="lbl">Início *</span><input type="datetime-local" value={form.startsAt} onChange={e => set('startsAt', e.target.value)}/></label>
          <label className="field"><span className="lbl">Fim</span><input type="datetime-local" value={form.endsAt} onChange={e => set('endsAt', e.target.value)}/></label>
        </div>
        <label className="field"><span className="lbl">Local (nome)</span><input value={form.venueName} onChange={e => set('venueName', e.target.value)}/></label>
        <label className="field"><span className="lbl">Endereço</span><input value={form.venueAddress} onChange={e => set('venueAddress', e.target.value)}/></label>
        <div style={{ display: 'grid', gridTemplateColumns: '2fr 1fr', gap: 10 }}>
          <label className="field"><span className="lbl">Cidade</span><input value={form.city} onChange={e => set('city', e.target.value)}/></label>
          <label className="field"><span className="lbl">UF</span><input value={form.state} maxLength={2} onChange={e => set('state', e.target.value.toUpperCase())}/></label>
        </div>
        <label className="field"><span className="lbl">Capa</span>
          {form.bannerUrl && <div style={{ width: '100%', aspectRatio: '16/9', backgroundImage: `url(${form.bannerUrl})`, backgroundSize: 'cover', backgroundPosition: 'center', borderRadius: 10, marginBottom: 6 }}/>}
          <input type="file" accept="image/*" onChange={handleUpload}/>
        </label>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
          <label className="field"><span className="lbl">Tema</span>
            <select value={form.theme} onChange={e => set('theme', e.target.value)}>
              <option value="dark">Escuro</option><option value="light">Claro</option>
            </select>
          </label>
          <label className="field"><span className="lbl">Status</span>
            <select value={form.status} onChange={e => set('status', e.target.value)}>
              <option value="draft">Rascunho</option>
              <option value="published">Publicado</option>
              <option value="archived">Arquivado</option>
            </select>
          </label>
        </div>
        <div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end', marginTop: 16 }}>
          <button className="btn btn-ghost btn-sm" onClick={onClose}>Cancelar</button>
          <button className="btn btn-primary btn-sm" onClick={save}>Salvar</button>
        </div>
      </div>
    </div>
  );
}

// ─── Lotes de ingresso ───
function BatchesPanel({ eventId, onClose }) {
  const [batches, setBatches] = useState([]);
  const [editing, setEditing] = useState(null);
  const [showForm, setShowForm] = useState(false);
  const load = () => api('GET', `/api/events/${eventId}/batches`).then(r => setBatches(r.batches || []));
  useEffect(() => { load(); }, [eventId]);
  const del = async (b) => {
    if (!confirm(`Excluir lote "${b.name}"?`)) return;
    try { await api('DELETE', `/api/batches/${b.id}`); load(); }
    catch (e) { alert('Erro: ' + e.message); }
  };
  return (
    <div onClick={onClose} style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.6)', zIndex: 100, display: 'grid', placeItems: 'center', padding: 20 }}>
      <div onClick={e => e.stopPropagation()} className="app-card" style={{ width: '100%', maxWidth: 720, maxHeight: '90vh', overflowY: 'auto' }}>
        <div style={{ display: 'flex', alignItems: 'center', marginBottom: 12 }}>
          <h3 style={{ fontFamily: 'Sora', margin: 0 }}>Lotes de ingresso</h3>
          <button className="btn btn-primary btn-sm" style={{ marginLeft: 'auto' }} onClick={() => { setEditing(null); setShowForm(true); }}>+ Novo lote</button>
        </div>
        {batches.length === 0 ? <div className="empty">Nenhum lote cadastrado.</div> : (
          <table className="app-table">
            <thead><tr><th>Nome</th><th>Preço</th><th>Qtd</th><th>Vendidos</th><th></th></tr></thead>
            <tbody>
              {batches.map(b => (
                <tr key={b.id}>
                  <td><strong>{b.name}</strong></td>
                  <td>{fmtBRL(b.price)}</td>
                  <td>{b.quantity}</td>
                  <td>{b.sold}</td>
                  <td style={{ textAlign: 'right', whiteSpace: 'nowrap' }}>
                    <button className="btn btn-ghost btn-sm" onClick={() => { setEditing(b); setShowForm(true); }}>Editar</button>
                    <button className="btn btn-danger btn-sm" style={{ marginLeft: 6 }} onClick={() => del(b)}>🗑</button>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        )}
        <div style={{ display: 'flex', justifyContent: 'flex-end', marginTop: 12 }}>
          <button className="btn btn-ghost btn-sm" onClick={onClose}>Fechar</button>
        </div>
        {showForm && <BatchForm eventId={eventId} initial={editing} onClose={() => setShowForm(false)} onSaved={() => { setShowForm(false); load(); }}/>}
      </div>
    </div>
  );
}

function BatchForm({ eventId, initial, onClose, onSaved }) {
  const isEdit = !!initial;
  const [form, setForm] = useState({
    name: initial?.name || '',
    description: initial?.description || '',
    price: initial?.price ?? 0,
    quantity: initial?.quantity ?? 50,
    startsAt: initial?.starts_at ? fmtDateInput(initial.starts_at) : '',
    endsAt: initial?.ends_at ? fmtDateInput(initial.ends_at) : '',
  });
  const set = (k, v) => setForm(f => ({ ...f, [k]: v }));
  const save = async () => {
    if (!form.name.trim()) return alert('Nome obrigatório');
    try {
      if (isEdit) await api('PATCH', `/api/batches/${initial.id}`, form);
      else        await api('POST',  `/api/events/${eventId}/batches`, form);
      onSaved();
    } catch (e) { alert('Erro: ' + e.message); }
  };
  return (
    <div onClick={onClose} style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.7)', zIndex: 200, display: 'grid', placeItems: 'center', padding: 20 }}>
      <div onClick={e => e.stopPropagation()} className="app-card" style={{ width: '100%', maxWidth: 480 }}>
        <h3 style={{ fontFamily: 'Sora', marginTop: 0 }}>{isEdit ? 'Editar lote' : 'Novo lote'}</h3>
        <label className="field"><span className="lbl">Nome *</span><input value={form.name} onChange={e => set('name', e.target.value)} placeholder="Ex: Pista 1º Lote"/></label>
        <label className="field"><span className="lbl">Descrição</span><input value={form.description} onChange={e => set('description', e.target.value)}/></label>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
          <label className="field"><span className="lbl">Preço (R$)</span><input type="number" step="0.01" value={form.price} onChange={e => set('price', parseFloat(e.target.value) || 0)}/></label>
          <label className="field"><span className="lbl">Quantidade</span><input type="number" value={form.quantity} onChange={e => set('quantity', parseInt(e.target.value) || 0)}/></label>
        </div>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
          <label className="field"><span className="lbl">Vendas iniciam</span><input type="datetime-local" value={form.startsAt} onChange={e => set('startsAt', e.target.value)}/></label>
          <label className="field"><span className="lbl">Vendas encerram</span><input type="datetime-local" value={form.endsAt} onChange={e => set('endsAt', e.target.value)}/></label>
        </div>
        <div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end', marginTop: 16 }}>
          <button className="btn btn-ghost btn-sm" onClick={onClose}>Cancelar</button>
          <button className="btn btn-primary btn-sm" onClick={save}>Salvar</button>
        </div>
      </div>
    </div>
  );
}

// ─── Eventos (compartilhado: admin/organizer) ───
function EventsPanel({ me, navigate }) {
  const [events, setEvents] = useState([]);
  const [organizers, setOrganizers] = useState([]);
  const [editing, setEditing] = useState(null);
  const [showForm, setShowForm] = useState(false);
  const [batchesFor, setBatchesFor] = useState(null);
  const isAdmin = me.role === 'admin';

  const load = () => api('GET', '/api/events').then(r => setEvents(r.events || []));
  useEffect(() => {
    load();
    if (isAdmin) api('GET', '/api/admin/organizers').then(r => setOrganizers(r.organizers || []));
  }, []);
  const del = async (e) => {
    if (!confirm(`Excluir evento "${e.title}"?`)) return;
    try { await api('DELETE', `/api/events/${e.id}`); load(); }
    catch (err) { alert('Erro: ' + err.message); }
  };
  const togglePublish = async (e) => {
    try { await api('PATCH', `/api/events/${e.id}`, { status: e.status === 'published' ? 'draft' : 'published' }); load(); }
    catch (err) { alert('Erro: ' + err.message); }
  };
  return (
    <>
      <div style={{ display: 'flex', alignItems: 'center', marginBottom: 16 }}>
        <h2 style={{ fontFamily: 'Sora', margin: 0 }}>Eventos</h2>
        <button className="btn btn-primary btn-sm" style={{ marginLeft: 'auto' }}
          onClick={() => { setEditing(null); setShowForm(true); }}
          disabled={isAdmin && organizers.length === 0}
          title={isAdmin && organizers.length === 0 ? 'Cadastre um organizador antes' : ''}>
          + Novo evento
        </button>
      </div>
      {events.length === 0 ? <div className="empty">Nenhum evento ainda.</div> : (
        <table className="app-table">
          <thead><tr><th>Título</th><th>Data</th><th>Local</th><th>Status</th><th></th></tr></thead>
          <tbody>
            {events.map(e => (
              <tr key={e.id}>
                <td>
                  <strong>{e.title}</strong>
                  <div style={{ fontSize: 11, color: 'var(--muted)' }}>/evento/{e.slug}</div>
                </td>
                <td style={{ color: 'var(--muted)', fontSize: 12 }}>{fmtDate(e.starts_at)}</td>
                <td style={{ color: 'var(--muted)', fontSize: 12 }}>{e.city || '—'}</td>
                <td><span className={`app-pill ${e.status === 'published' ? 'green' : 'gray'}`}>{e.status === 'published' ? 'Publicado' : 'Rascunho'}</span></td>
                <td style={{ textAlign: 'right', whiteSpace: 'nowrap' }}>
                  <button className="btn btn-ghost btn-sm" onClick={() => setBatchesFor(e.id)}>Lotes</button>
                  <button className="btn btn-ghost btn-sm" style={{ marginLeft: 6 }} onClick={() => togglePublish(e)}>{e.status === 'published' ? 'Despublicar' : 'Publicar'}</button>
                  <button className="btn btn-ghost btn-sm" style={{ marginLeft: 6 }} onClick={() => { setEditing(e); setShowForm(true); }}>Editar</button>
                  <button className="btn btn-danger btn-sm" style={{ marginLeft: 6 }} onClick={() => del(e)}>🗑</button>
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      )}
      {showForm && (
        <EventForm
          initial={editing}
          organizers={isAdmin ? organizers : []}
          defaultOrgId={isAdmin ? (editing?.organizer_id || organizers[0]?.id) : me.organizerId}
          onClose={() => setShowForm(false)}
          onSaved={() => { setShowForm(false); load(); }}/>
      )}
      {batchesFor && <BatchesPanel eventId={batchesFor} onClose={() => setBatchesFor(null)}/>}
    </>
  );
}

// ─── Painel admin ───
function AdminPanel({ me, route, navigate }) {
  const sub = route.sub || 'events';
  return (
    <div className="app-shell" style={{ padding: '24px 20px' }}>
      <div style={{ display: 'flex', gap: 6, marginBottom: 24, flexWrap: 'wrap' }}>
        <button className={`btn btn-sm ${sub === 'events'      ? 'btn-primary' : 'btn-ghost'}`} onClick={() => navigate({ view: 'admin', sub: 'events' })}>Eventos</button>
        <button className={`btn btn-sm ${sub === 'organizers'  ? 'btn-primary' : 'btn-ghost'}`} onClick={() => navigate({ view: 'admin', sub: 'organizers' })}>Organizadores</button>
        <button className={`btn btn-sm ${sub === 'settings'    ? 'btn-primary' : 'btn-ghost'}`} onClick={() => navigate({ view: 'admin', sub: 'settings' })}>Configurações</button>
      </div>
      {sub === 'events'     && <EventsPanel me={me} navigate={navigate}/>}
      {sub === 'organizers' && <AdminOrganizers/>}
      {sub === 'settings'   && <AdminSettings/>}
    </div>
  );
}

// ─── Painel organizador ───
function OrgPanel({ me, route, navigate }) {
  return (
    <div className="app-shell" style={{ padding: '24px 20px' }}>
      <EventsPanel me={me} navigate={navigate}/>
    </div>
  );
}

// ─── App raiz ───
function App() {
  const [route, setRoute] = useState(() => pathToRoute(window.location.pathname));
  const [me, setMe] = useState(undefined); // undefined = carregando, null = não logado, obj = logado

  useEffect(() => {
    fetch('/api/auth/me', { credentials: 'same-origin' })
      .then(r => r.ok ? r.json() : Promise.reject())
      .then(d => setMe(d.user || null))
      .catch(() => setMe(null));
  }, []);

  const navigate = useCallback((next) => {
    const desired = routeToPath(next);
    if (desired !== window.location.pathname + window.location.search) {
      window.history.pushState(next, '', desired);
    }
    window.scrollTo(0, 0);
    setRoute(next);
  }, []);

  useEffect(() => {
    const handler = () => setRoute(pathToRoute(window.location.pathname));
    window.addEventListener('popstate', handler);
    return () => window.removeEventListener('popstate', handler);
  }, []);

  const logout = async () => {
    await fetch('/api/auth/logout', { method: 'POST', credentials: 'same-origin' });
    setMe(null);
    navigate({ view: 'home' });
  };

  if (me === undefined) return <div className="empty">Carregando…</div>;

  // Gating: admin/org só pra logado
  if ((route.view === 'admin' || route.view === 'org') && !me) {
    return <LoginPage onLogin={(u) => { setMe(u); navigate(u.role === 'admin' ? { view: 'admin' } : { view: 'org' }); }} navigate={navigate}/>;
  }
  if (route.view === 'admin' && me?.role !== 'admin') return <div className="empty">Acesso só pra admins.</div>;
  if (route.view === 'org'   && me?.role !== 'organizer' && me?.role !== 'admin') return <div className="empty">Acesso só pra organizadores.</div>;

  return (
    <>
      <Header route={route} navigate={navigate} me={me} onLogout={logout}/>
      {route.view === 'home'  && <Vitrine navigate={navigate}/>}
      {route.view === 'event' && <EventPage slug={route.slug} navigate={navigate}/>}
      {route.view === 'login' && <LoginPage onLogin={(u) => { setMe(u); navigate(u.role === 'admin' ? { view: 'admin' } : { view: 'org' }); }} navigate={navigate}/>}
      {route.view === 'admin' && <AdminPanel me={me} route={route} navigate={navigate}/>}
      {route.view === 'org'   && <OrgPanel   me={me} route={route} navigate={navigate}/>}
    </>
  );
}

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