/* PURA — Página de Captura
 * Meta Pixel + CAPI: PageView / ViewContent / Lead
 * Pixel ID: 1587694082922255
 * Reportana: data-rptn-form="87550"
 */

const { useState, useEffect, useRef } = React;

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "palette": "copper",
  "glow": 60,
  "layout": "split",
  "showManifesto": true,
  "eventDate": "25.07.26",
  "eventTime": "__H — __H",
  "eventLocation": "CHAPECÓ - SC"
}/*EDITMODE-END*/;

// ═══════════════════════════════════════════════════════════
// PIXEL + CAPI
// ═══════════════════════════════════════════════════════════
const PIXEL_ID = '1587694082922255';
const CAPI_URL = 'capi.php';

function uuidv4() {
  return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c =>
    (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16));
}

async function sha256(str) {
  if (!str) return null;
  const clean = String(str).toLowerCase().trim();
  if (!clean) return null;
  const buf = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(clean));
  return Array.from(new Uint8Array(buf)).map(b => b.toString(16).padStart(2,'0')).join('');
}

function getFbp() {
  const m = document.cookie.match(/_fbp=([^;]+)/); return m ? m[1] : null;
}
function getFbc() {
  const m = document.cookie.match(/_fbc=([^;]+)/);
  if (m) return m[1];
  const p = new URLSearchParams(location.search).get('fbclid');
  return p ? `fb.1.${Date.now()}.${p}` : null;
}

// Busca geo (ipapi.co) e gender (genderize.io) em paralelo
// firstName opcional — se vazio, só retorna geo
async function getGeoGender(firstName) {
  const [geoRes, genRes] = await Promise.allSettled([
    fetch('https://ipapi.co/json/', { signal: AbortSignal.timeout(4000) }).then(r => r.json()),
    firstName
      ? fetch(`https://api.genderize.io/?name=${encodeURIComponent(firstName)}&country_id=BR`,
              { signal: AbortSignal.timeout(4000) }).then(r => r.json())
      : Promise.resolve(null),
  ]);
  const geo = geoRes.status === 'fulfilled' ? (geoRes.value || {}) : {};
  const gen = genRes.status === 'fulfilled' ? genRes.value : null;

  let ge = null;
  if (gen && gen.gender && (gen.probability || 0) >= 0.8) {
    ge = await sha256(gen.gender === 'male' ? 'm' : 'f');
  }

  return {
    ip      : geo.ip       || null,
    city    : (geo.city    || '').toLowerCase(),
    region  : (geo.region  || '').toLowerCase(),
    country : (geo.country_code || 'BR').toLowerCase(),
    postal  : geo.postal   || null,
    ge,
  };
}

// Cache do geo para não buscar 3x (PageView, ViewContent, Lead)
let _geoCache = null;
async function getGeoCached(firstName) {
  if (!_geoCache) _geoCache = getGeoGender(firstName || '');
  return _geoCache;
}

// ── Pixel browser ────────────────────────────────────────────────────────────
function pixelTrack(event, params, options) {
  try { if (typeof window.fbq === 'function') window.fbq('track', event, params || {}, options || {}); }
  catch(e) {}
}

// ── CAPI server-side ─────────────────────────────────────────────────────────
// userData: { em, ph, fn, ln, ct, st, country, zp, ge } — todos já hasheados
// geo:      { ip, city, region, country, postal, ge }   — raw, o PHP faz o resto
async function capiSend({ eventName, eventId, userData = {}, geo = {} }) {
  const payload = {
    event_name : eventName,
    event_id   : eventId,
    event_time : Math.floor(Date.now() / 1000),
    source_url : location.href,
    user_agent : navigator.userAgent,
    client_ip  : geo.ip  || '',
    fbp        : getFbp(),
    fbc        : getFbc(),
    // PII hasheado (sha256 feito aqui no cliente)
    em      : userData.em      || null,
    ph      : userData.ph      || null,
    fn      : userData.fn      || null,
    ln      : userData.ln      || null,
    ct      : userData.ct      || null,
    st      : userData.st      || null,
    country : userData.country || null,
    zp      : userData.zp      || null,
    ge      : userData.ge      || null,
  };
  const blob = new Blob([JSON.stringify(payload)], { type: 'application/json' });
  try {
    navigator.sendBeacon
      ? navigator.sendBeacon(CAPI_URL, blob)
      : fetch(CAPI_URL, { method: 'POST', body: blob, keepalive: true }).catch(()=>{});
  } catch(e) {}
}

// ── Helpers de hash de geo ───────────────────────────────────────────────────
async function hashGeo(geo) {
  const [ct, st, country, zp] = await Promise.all([
    sha256(geo.city),
    sha256(geo.region),
    sha256(geo.country),
    geo.postal ? sha256(geo.postal) : Promise.resolve(null),
  ]);
  return { ct, st, country, zp, ge: geo.ge };
}

// ─────────────────────────────────────────────────────────────────────────────
// PageView CAPI — dispara assim que o módulo carrega (antes do React montar)
// Geo sem firstName; sem PII de usuário
(async () => {
  try {
    const pvId = uuidv4();
    // Pixel já disparou no <head>; aqui só o CAPI
    const geo = await getGeoCached('');
    const geoH = await hashGeo(geo);
    await capiSend({ eventName: 'PageView', eventId: pvId, geo, userData: geoH });
  } catch(e) {}
})();

// ═══════════════════════════════════════════════════════════
// COMPONENTES
// ═══════════════════════════════════════════════════════════

function RingMark({ size = 56, stroke = 1.1, color = "currentColor", style }) {
  return (
    <svg width={size} height={size} viewBox="0 0 100 100" fill="none" style={style} aria-hidden="true">
      <defs>
        <filter id="ring-rough">
          <feTurbulence type="fractalNoise" baseFrequency="0.9" numOctaves="2" seed="3"/>
          <feDisplacementMap in="SourceGraphic" scale="1.4"/>
        </filter>
      </defs>
      <circle cx="50" cy="50" r="38" stroke={color} strokeWidth={stroke*1.6} fill="none" opacity="0.18" filter="url(#ring-rough)"/>
      <circle cx="50" cy="50" r="38" stroke={color} strokeWidth={stroke} fill="none" opacity="0.95"
              strokeDasharray="190 50" strokeDashoffset="-12" strokeLinecap="round" transform="rotate(18 50 50)"/>
      <circle cx="50" cy="50" r="38" stroke={color} strokeWidth={stroke*0.6} fill="none" opacity="0.55"
              strokeDasharray="60 200" strokeDashoffset="-180" strokeLinecap="round" transform="rotate(-30 50 50)"/>
    </svg>
  );
}

function PuraLogo({ width = 200, className = "" }) {
  return (
    <img src="assets/pura-logo.png?v=5" alt="PURA — A State of Feeling"
         className={`pura-logo-img ${className}`} style={{ width: `${width}px` }} draggable="false" />
  );
}

function AtmosphereStage({ glow, palette }) {
  const accent = palette === "olive" ? "#4D5B46" : "#8A6A52";
  return (
    <div className="atmosphere" aria-hidden="true">
      <div className="atm-vignette" />
      <div className="atm-grain" />
      <div className="atm-ring-wrap" style={{ "--glow": glow/100, "--accent": accent }}>
        <div className="atm-ring-halo" />
        <div className="atm-ring-core" />
        <div className="atm-ring-inner" />
        <div className="atm-shaft" />
      </div>
      <div className="atm-smoke smoke-a" />
      <div className="atm-smoke smoke-b" />
      <svg className="atm-palm" viewBox="0 0 400 600" preserveAspectRatio="xMaxYMin slice" aria-hidden="true">
        <g fill="#000" opacity="0.55">
          <path d="M380,-20 C 360,80 300,140 240,170 C 280,150 320,140 360,150 L 380,150 Z"/>
          <path d="M395,10 C 370,90 320,160 250,210 C 300,180 350,170 395,180 L 395,180 Z" opacity="0.7"/>
          <path d="M385,60 C 340,140 270,200 200,240 C 260,220 320,220 380,230 L 395,230 Z" opacity="0.5"/>
        </g>
      </svg>
      <div className="atm-corner-mark"><RingMark size={28} color="var(--off-white)" /></div>
    </div>
  );
}

function maskPhone(v) {
  const d = v.replace(/\D/g,"").slice(0,11);
  if (d.length<=2) return d.length?`(${d}`:"";
  if (d.length<=6) return `(${d.slice(0,2)}) ${d.slice(2)}`;
  if (d.length<=10) return `(${d.slice(0,2)}) ${d.slice(2,6)}-${d.slice(6)}`;
  return `(${d.slice(0,2)}) ${d.slice(2,7)}-${d.slice(7)}`;
}

// ───────── Form
function CaptureForm() {
  const [form, setForm]       = useState({ nome:"", email:"", whats:"" });
  const [touched, setTouched] = useState({});
  const [submitting, setSub]  = useState(false);
  const [done, setDone]       = useState(false);
  const vcFired               = useRef(false);

  // ViewContent — uma vez só
  useEffect(() => {
    if (vcFired.current) return;
    vcFired.current = true;

    (async () => {
      try {
        const vcId = uuidv4();
        // Browser
        pixelTrack('ViewContent', {
          content_name: 'PURA — Pré-venda',
          content_category: 'Evento',
        }, { eventID: vcId });
        // CAPI com geo (sem PII ainda)
        const geo  = await getGeoCached('');
        const geoH = await hashGeo(geo);
        await capiSend({ eventName: 'ViewContent', eventId: vcId, geo, userData: geoH });
      } catch(e) {}
    })();
  }, []);

  const v = {
    nome:  form.nome.trim().split(/\s+/).filter(Boolean).length >= 2,
    email: /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(form.email),
    whats: form.whats.replace(/\D/g,"").length >= 10,
  };
  const valid = v.nome && v.email && v.whats;

  const handleSubmit = async (e) => {
    e.preventDefault();
    setTouched({ nome:true, email:true, whats:true });
    if (!valid) return;
    setSub(true);

    try {
      const leadId = uuidv4();
      const nameParts = form.nome.trim().split(/\s+/);
      const fn = nameParts[0] || '';
      const ln = nameParts.slice(1).join(' ') || '';
      const phoneDigits = form.whats.replace(/\D/g,'');
      // E.164 Brasil
      const phoneE164 = phoneDigits.length === 11
        ? '55' + phoneDigits : phoneDigits.length === 10
        ? '55' + phoneDigits : phoneDigits;

      // Geo + gender com firstName disponível agora
      _geoCache = getGeoGender(fn); // atualiza cache com firstName real
      const geo = await _geoCache;
      const geoH = await hashGeo(geo);

      // Hash PII
      const [emH, fnH, lnH, phH] = await Promise.all([
        sha256(form.email),
        sha256(fn),
        sha256(ln),
        sha256(phoneE164),
      ]);

      const userData = {
        em: emH, ph: phH, fn: fnH, ln: lnH,
        ct: geoH.ct, st: geoH.st, country: geoH.country,
        zp: geoH.zp, ge: geoH.ge,
      };

      // Pixel browser — envia PII hasheado também no client-side
      pixelTrack('Lead', {
        content_name    : 'PURA — Pré-venda',
        content_category: 'Evento',
        em: emH, fn: fnH, ln: lnH, ph: phH,
        ct: geoH.ct, st: geoH.st, country: geoH.country,
        zp: geoH.zp,
      }, { eventID: leadId });

      // CAPI server-side — todos os dados
      await capiSend({ eventName: 'Lead', eventId: leadId, geo, userData });

    } catch(e) {}

    setTimeout(() => { window.location.href = 'https://purastate.com.br/manifesto/001/grupos.php'; }, 1200);
  };

  if (done) {
    return (
      <div className="form-done">
        <RingMark size={64} color="var(--copper)" />
        <h3>SUA PRESENÇA FOI REGISTRADA.</h3>
        <p className="done-body">
          Em breve, você receberá uma mensagem.<br />
          Pouco será dito. O suficiente, sim.
        </p>
        <div className="done-meta">
          <span>MUSIC.</span><span className="dot">·</span>
          <span>PRESENCE.</span><span className="dot">·</span>
          <span>CONNECTION.</span>
        </div>
      </div>
    );
  }

  return (
    <form onSubmit={handleSubmit} noValidate className="capture-form"
          method="POST" action="/" data-rptn-form="87550">
      <Field label="NOME COMPLETO" value={form.nome}
             onChange={val => setForm({...form, nome:val})}
             onBlur={() => setTouched({...touched, nome:true})}
             error={touched.nome && !v.nome && "Inclua nome e sobrenome."}
             autoComplete="name" rptnField="name" />
      <Field label="E-MAIL" type="email" value={form.email}
             onChange={val => setForm({...form, email:val})}
             onBlur={() => setTouched({...touched, email:true})}
             error={touched.email && !v.email && "E-mail inválido."}
             autoComplete="email" rptnField="email" />
      <Field label="WHATSAPP" type="tel" value={form.whats}
             onChange={val => setForm({...form, whats:maskPhone(val)})}
             onBlur={() => setTouched({...touched, whats:true})}
             error={touched.whats && !v.whats && "Número incompleto."}
             placeholder="(11) 99999-9999" autoComplete="tel" rptnField="phone" />

      <button type="submit" className="submit-btn" disabled={submitting}>
        <span className="btn-line" />
        <span className="btn-label">{submitting ? "REGISTRANDO" : "FINALIZAR CADASTRO"}</span>
        <span className="btn-arrow">→</span>
      </button>

      <p className="form-fine">
        Ao finalizar, você será redirecionado para a nossa comunidade para receber
        o link exclusivo da pré-venda e informação sobre o evento.
      </p>
    </form>
  );
}

function Field({ label, value, onChange, onBlur, error, type="text", placeholder, autoComplete, rptnField }) {
  const [focused, setFocused] = useState(false);
  const filled = value && value.length > 0;
  return (
    <label className={`field ${focused?"is-focused":""} ${filled?"is-filled":""} ${error?"has-error":""}`}>
      <span className="field-label">{label}</span>
      <input type={type} value={value}
             onChange={e => onChange(e.target.value)}
             onFocus={() => setFocused(true)}
             onBlur={() => { setFocused(false); onBlur && onBlur(); }}
             placeholder={focused ? placeholder : ""}
             autoComplete={autoComplete} spellCheck="false"
             data-rptn-field={rptnField} />
      <span className="field-rule" />
      {error && <span className="field-error">{error}</span>}
    </label>
  );
}

function Manifesto({ eventDate, eventTime, eventLocation }) {
  return (
    <div className="manifesto">
      <div className="manifesto-quote">
        <p className="quote-line quote-line--em">Registre-se na pré-venda exclusiva ↓</p>
      </div>
      <div className="event-meta">
        <div className="meta-row"><span className="meta-key">DATA</span><span className="meta-val">{eventDate}</span></div>
        <div className="meta-row"><span className="meta-key">LOCAL</span><span className="meta-val">{eventLocation}</span></div>
      </div>
      <div className="brand-signature">
        <span>PRESENÇA.</span><span>CONEXÃO.</span><span>VANGUARDA.</span>
        <span>ENTREGA.</span><span>LIBERDADE.</span>
      </div>
    </div>
  );
}

function App() {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
  useEffect(() => { document.documentElement.dataset.palette = t.palette; }, [t.palette]);

  return (
    <>
      <main className={`pura-shell layout-${t.layout}`}>
        <section className="stage-pane">
          <AtmosphereStage glow={t.glow} palette={t.palette} />
          <div className="stage-top"><div className="kicker">MANIFESTO · 001</div></div>
          {t.layout !== "split" && (
            <div className="stage-center">
              <PuraLogo width={420} />
              <div className="centered-meta">
                <span>{t.eventDate}</span><span className="meta-sep">·</span>
                <span>{t.eventTime}</span><span className="meta-sep">·</span>
                <span>{t.eventLocation}</span>
              </div>
            </div>
          )}
          {t.layout === "split" && (
            <div className="stage-center stage-center--split"><PuraLogo width={340} /></div>
          )}
          <div className="stage-bottom">
            <div className="kicker"></div>
            <div className="kicker kicker--right">PURA © 2026</div>
          </div>
        </section>

        <section className="capture-pane">
          <div className="capture-inner">
            {t.layout === "split" && t.showManifesto && (
              <Manifesto eventDate={t.eventDate} eventTime={t.eventTime} eventLocation={t.eventLocation} />
            )}
            {t.layout !== "split" && (
              <div className="form-header">
                <p className="form-eyebrow">RESERVA DE PRESENÇA</p>
                <h2 className="form-title">Garanta seu acesso<br/>a uma noite que não se repete.</h2>
              </div>
            )}
            <CaptureForm />
          </div>
        </section>
      </main>

      <TweaksPanel title="Tweaks">
        <TweakSection label="Atmosfera" />
        <TweakRadio label="Paleta" value={t.palette} onChange={v => setTweak("palette",v)}
          options={[{value:"noir",label:"Noir"},{value:"copper",label:"Copper"},{value:"olive",label:"Olive"}]} />
        <TweakSlider label="Glow do anel" value={t.glow} onChange={v => setTweak("glow",v)} min={0} max={100} step={5} unit="%" />
        <TweakSection label="Layout" />
        <TweakRadio label="Composição" value={t.layout} onChange={v => setTweak("layout",v)}
          options={[{value:"split",label:"Split"},{value:"stack",label:"Stack"},{value:"overlay",label:"Overlay"}]} />
        {t.layout === "split" && (
          <TweakToggle label="Manifesto" value={t.showManifesto} onChange={v => setTweak("showManifesto",v)} />
        )}
        <TweakSection label="Evento" />
        <TweakText label="Data"  value={t.eventDate}     onChange={v => setTweak("eventDate",v)} />
        <TweakText label="Local" value={t.eventLocation} onChange={v => setTweak("eventLocation",v)} />
      </TweaksPanel>
    </>
  );
}

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