// Componentes de seções
const { useState, useEffect, useMemo, useRef } = React;

// Interpreta o negrito marcado no painel admin ("**texto**" -> <strong>).
function renderRich(texto) {
  if (!texto) return texto;
  const partes = String(texto).split(/(\*\*[^*]+\*\*)/g);
  return partes.map((parte, i) =>
    parte.startsWith("**") && parte.endsWith("**") && parte.length > 4
      ? <strong key={i}>{parte.slice(2, -2)}</strong>
      : parte
  );
}

// === Mini Calendário ===
function MiniCalendar({ data }) {
  const dias = ['DOM','SEG','TER','QUA','QUI','SEX','SÁB'];
  // O desenho do calendário é fixo; apenas a grade acompanha a data escolhida.
  const ano = data.dataExibicao.anoNum || parseInt(data.dataExibicao.ano, 10);
  const mes0 = (data.dataExibicao.mesNum || 12) - 1;
  const firstDay = new Date(ano, mes0, 1).getDay();
  const totalDays = new Date(ano, mes0 + 1, 0).getDate();
  const weddingDay = parseInt(data.dataExibicao.dia);

  const cells = [];
  for (let i = 0; i < firstDay; i++) cells.push(null);
  for (let d = 1; d <= totalDays; d++) cells.push(d);
  while (cells.length % 7 !== 0) cells.push(null);

  const rows = [];
  for (let i = 0; i < cells.length; i += 7) rows.push(cells.slice(i, i + 7));

  return (
    <div className="mini-cal">
      <div className="mini-cal-header">
        <span className="mini-cal-year">{data.dataExibicao.ano}</span>
        <span className="mini-cal-month">{data.dataExibicao.mes.toUpperCase()}</span>
      </div>
      <div className="mini-cal-grid">
        {dias.map(d => <div key={d} className="mini-cal-dayname">{d}</div>)}
        {rows.map((row, ri) => row.map((day, ci) => (
          <div key={`${ri}-${ci}`} className={`mini-cal-day${day === weddingDay ? ' wedding' : ''}${!day ? ' empty' : ''}`}>
            {day || ''}
          </div>
        )))}
      </div>
    </div>
  );
}

// === Mini Mapa ===
function MiniMap({ data }) {
  return (
    <a
      className="mini-map"
      href={data.local.mapsUrl}
      target="_blank"
      rel="noopener"
      aria-label={`Abrir ${data.local.nome} no Google Maps`}
    >
      <iframe
        className="mini-map-frame"
        src={data.local.mapsEmbedUrl}
        title={`Mapa — ${data.local.nome}`}
        loading="lazy"
        referrerPolicy="no-referrer-when-downgrade"
        tabIndex={-1}
      />
      <span className="mini-map-pin"><Icons.Pin size={14}/></span>
    </a>
  );
}

// === Countdown ===
function useCountdown(target) {
  const [now, setNow] = useState(() => new Date());
  useEffect(() => {
    const id = setInterval(() => setNow(new Date()), 1000);
    return () => clearInterval(id);
  }, []);
  const diff = Math.max(0, target.getTime() - now.getTime());
  const days = Math.floor(diff / 86400000);
  const hours = Math.floor((diff % 86400000) / 3600000);
  const minutes = Math.floor((diff % 3600000) / 60000);
  const seconds = Math.floor((diff % 60000) / 1000);
  return { days, hours, minutes, seconds };
}

function Countdown({ target }) {
  const { days, hours, minutes, seconds } = useCountdown(target);
  const cells = [
    { num: days, label: "Dias" },
    { num: hours, label: "Horas" },
    { num: minutes, label: "Minutos" },
    { num: seconds, label: "Segundos" },
  ];
  return (
    <div className="countdown" role="timer" aria-label="Contagem regressiva">
      {cells.map((c) => (
        <div className="countdown-cell" key={c.label}>
          <div className="num">{String(c.num).padStart(2, "0")}</div>
          <div className="label">{c.label}</div>
        </div>
      ))}
    </div>
  );
}

// === Hero ===
function Hero({ variant, data }) {
  const { iniciais } = data.noivos;
  const dateStr = `${data.dataExibicao.dia} · ${data.dataExibicao.mes} · ${data.dataExibicao.ano}`;
  return (
    <section id="inicio" className={`section hero variant-${variant}`} data-screen-label="Início">
      <div className="hero-inner">
        <div className="hero-eyebrow">CONVITE DE CASAMENTO</div>

        {variant === "monogram" && (
          <>
            <div className="hero-monogram-img">
              <img
                src="img/monograma.png"
                alt="G ♥ M"
              />
            </div>
            <div className="hero-names">{data.noivos.nome1} <em style={{fontStyle:'normal', color:'var(--accent-rose)'}}>e</em> {data.noivos.nome2}</div>
          </>
        )}

        {variant === "framed" && (
          <div className="framed-wrap">
            <div className="frame-border">
              <div className="frame-inner">
                <div className="frame-eyebrow">— Save the date —</div>
                <div className="frame-names">
                  <div>{data.noivos.nome1}</div>
                  <div className="frame-amp">&amp;</div>
                  <div>{data.noivos.nome2}</div>
                </div>
                <div className="frame-foot">{data.dataExibicao.dia}.{String(data.dataExibicao.mesNum || 12).padStart(2,'0')}.{data.dataExibicao.ano}</div>
              </div>
            </div>
          </div>
        )}

        {variant === "vertical-names" && (
          <div className="vert-names">
            {data.noivos.nome1}
            <span className="nm-sep">&amp;</span>
            {data.noivos.nome2}
          </div>
        )}

        <Divider />
        <div className="hero-date">
          <span>{data.dataExibicao.diaSemana.toUpperCase()}</span> · {dateStr} · <span>{data.dataExibicao.hora}</span>
        </div>

        <Countdown target={data.data} />
      </div>
    </section>
  );
}

// === Slideshow com crossfade (esmaece uma sobre a outra) ===
function PhotoSlideshow({ fotos, intervalo = 4000 }) {
  const [idx, setIdx] = useState(0);

  useEffect(() => {
    if (!fotos || fotos.length <= 1) return;
    const id = setInterval(() => {
      setIdx(i => (i + 1) % fotos.length);
    }, intervalo);
    return () => clearInterval(id);
  }, [fotos, intervalo]);

  if (!fotos || fotos.length === 0) return null;

  return (
    <div className="about-slideshow" aria-roledescription="apresentação de fotos">
      {fotos.map((src, i) => (
        <img
          key={src}
          className={`slide-photo${i === idx ? ' active' : ''}`}
          src={src}
          alt={`Giovanna e Miguel — foto ${i + 1}`}
          loading={i === 0 ? 'eager' : 'lazy'}
          aria-hidden={i === idx ? undefined : true}
          onError={e => { e.currentTarget.classList.add('missing'); }}
        />
      ))}
    </div>
  );
}

// === Sobre / Boas-vindas ===
function About({ data }) {
  const t = data.textos.sobre;
  return (
    <section id="sobre" className="section alt" data-screen-label="Sobre">
      <div className="section-inner">
        <div className="section-header">
          <div className="section-eyebrow">com alegria</div>
          <h2 className="section-title">Nosso Dia Especial</h2>
        </div>

        <div className="about-card">
          <div className="about-grid">
            <div className="about-text">
              <p>{renderRich(t.paragrafo1)}</p>
              <p>{renderRich(t.paragrafo2)}</p>
              <p>{renderRich(t.paragrafo3)}</p>
              <div className="signature">{data.noivos.nome1} &amp; {data.noivos.nome2}</div>
            </div>
            <div className="about-photo">
              <PhotoSlideshow fotos={data.fotosCasal} intervalo={4000} />
            </div>
          </div>
        </div>
      </div>
    </section>
  );
}

// === Detalhes do evento ===
function EventDetails({ data }) {
  const t = data.textos.detalhes;
  const cerimoniaTexto = (t.cerimoniaTemplate || "").replace("{hora}", data.dataExibicao.hora);
  return (
    <section id="detalhes" className="section" data-screen-label="Detalhes">
      <div className="section-inner">
        <div className="section-header">
          <div className="section-eyebrow">save the date</div>
          <h2 className="section-title">Detalhes do Evento</h2>
        </div>

        <div className="details-grid">
          <div className="detail-card">
            <Icons.Calendar className="icon" />
            <div className="label">QUANDO</div>
            <div className="value">{data.dataExibicao.diaSemana}<br/>{data.dataExibicao.dia} de {data.dataExibicao.mes}</div>
            <div className="sub">
              {renderRich(cerimoniaTexto)}
            </div>
            <MiniCalendar data={data}/>
          </div>

          <div className="detail-card">
            <Icons.Pin className="icon" />
            <div className="label">ONDE</div>
            <div className="value">{data.local.nome}</div>
            <div className="sub">{data.local.endereco}<br/>{data.local.cidade}</div>
            <a className="link" href={data.local.mapsUrl} target="_blank" rel="noopener">{t.verMapaTexto}</a>
            <MiniMap data={data}/>
          </div>

          <div className="detail-card">
            <Icons.Shirt className="icon" />
            <div className="label">DRESS CODE</div>
            <div className="value">{data.dressCode.titulo}</div>
            <div className="sub">{renderRich(data.dressCode.descricao)}</div>
            <div className="forbidden-colors">
              <div className="forbidden-colors-title">{t.coresProibidasTitulo}</div>
              <div className="forbidden-swatches">
                {data.dressCode.coresProibidas.map(cor => (
                  <div key={cor.hex} className="forbidden-item">
                    <span
                      className="forbidden-swatch"
                      style={{ '--swatch': cor.hex }}
                      title={`${cor.nome} (${cor.hex})`}
                      aria-label={`Cor não permitida: ${cor.nome}`}
                    />
                    <span className="forbidden-name">{cor.nome}</span>
                  </div>
                ))}
              </div>
            </div>
          </div>
        </div>

      </div>
    </section>
  );
}

// === Busca + RSVP (por grupo, confirmação individual) ===
function GuestSearch({ groups, onToast }) {
  const [query, setQuery] = useState("");
  const [selected, setSelected] = useState(null);   // grupo selecionado
  const [presentes, setPresentes] = useState({});   // { nome: bool }
  const [travados, setTravados] = useState({});      // { nome: bool } — já confirmados antes, não dá mais pra desmarcar
  const [salvando, setSalvando] = useState(false);
  const [feito, setFeito] = useState(null);          // { group, respostas }

  const lista = groups == null ? [] : groups;
  // Guarda o grupo atual para descartar respostas de buscas antigas (corrida).
  const selRef = useRef(null);
  selRef.current = selected;

  const results = useMemo(() => {
    const q = query.toLowerCase().trim();
    if (!q) return [];
    return lista.filter(g =>
      (g.membros || []).some(n => n.toLowerCase().includes(q)) ||
      (g.rotulo || "").toLowerCase().includes(q)
    );
  }, [query, lista]);

  function selecionar(g) {
    setSelected(g);
    // Começa com nenhum marcado; se já houver confirmação salva, ajusta ao buscá-la.
    const init = {};
    (g.membros || []).forEach(n => { init[n] = false; });
    setPresentes(init);
    setTravados({});

    // Busca só a confirmação DESTE grupo (não a lista toda) para pré-preencher.
    Store.getConfirmation(g.id).then(function (existente) {
      if (!existente || !existente.respostas) return;
      if (!selRef.current || selRef.current.id !== g.id) return; // trocou de grupo
      const upd = {};
      const trav = {};
      (g.membros || []).forEach(n => {
        const prev = existente.respostas[n];
        upd[n] = prev === undefined ? false : !!prev;
        // Quem já confirmou presença antes fica travado — não dá mais pra desmarcar por aqui.
        if (prev === true) trav[n] = true;
      });
      setPresentes(upd);
      setTravados(trav);
    });
  }

  function toggle(n) {
    if (travados[n]) return;
    setPresentes(p => Object.assign({}, p, { [n]: !p[n] }));
  }

  function confirmar() {
    if (!selected) return;
    setSalvando(true);
    // Antes de gravar, relê o estado mais recente do grupo: se alguém já
    // confirmou entre o carregamento da tela e este clique (outra pessoa do
    // mesmo grupo, outra aba/dispositivo), nunca deixamos essa presença
    // voltar para "não confirmado" por causa do estado desatualizado em memória.
    Store.getConfirmation(selected.id)
      .then(existente => {
        const respostasFinal = Object.assign({}, presentes);
        if (existente && existente.respostas) {
          Object.keys(existente.respostas).forEach(n => {
            if (existente.respostas[n] === true) respostasFinal[n] = true;
          });
        }
        return Store.saveConfirmation(selected.id, {
          respostas: respostasFinal,
          mesa: selected.mesa != null ? selected.mesa : null,
        }).then(() => respostasFinal);
      })
      .then(respostasFinal => {
        setFeito({ group: selected, respostas: respostasFinal });
        onToast && onToast("Presença registrada ✓");
      })
      .catch(() => {
        onToast && onToast("Não foi possível salvar. Tente novamente.");
      })
      .then(() => setSalvando(false));
  }

  function reset() {
    setFeito(null);
    setSelected(null);
    setQuery("");
    setPresentes({});
    setTravados({});
  }

  if (feito) {
    const vao = (feito.group.membros || []).filter(n => feito.respostas[n]);
    const naoVao = (feito.group.membros || []).filter(n => !feito.respostas[n]);
    return (
      <section id="rsvp" className="section alt" data-screen-label="RSVP">
        <div className="section-inner">
          <div className="section-header">
            <div className="section-eyebrow">obrigado</div>
            <h2 className="section-title">Presença Registrada</h2>
          </div>
          <div className="rsvp-card">
            <div className="rsvp-confirmed">
              <div className="check"><Icons.Check size={26}/></div>
              <h3>{vao.length ? "Esperamos vocês!" : "Resposta registrada"}</h3>
              {feito.group.mesa != null && vao.length > 0 && (
                <p style={{marginTop:6}}>Mesa <b style={{color:'var(--ink)'}}>{feito.group.mesa}</b></p>
              )}
              {vao.length > 0 && (
                <div className="rsvp-listagem">
                  <div className="rsvp-list-title">Confirmados</div>
                  {vao.map(n => (
                    <div className="rsvp-pessoa vai" key={n}><Icons.Check size={14}/> {n}</div>
                  ))}
                </div>
              )}
              {naoVao.length > 0 && (
                <div className="rsvp-listagem">
                  <div className="rsvp-list-title">Ainda não confirmados</div>
                  {naoVao.map(n => (
                    <div className="rsvp-pessoa nao" key={n}>{n}</div>
                  ))}
                </div>
              )}
              <div style={{marginTop:22}}>
                <button className="btn ghost small" onClick={reset}>Confirmar outro nome</button>
              </div>
            </div>
          </div>
        </div>
      </section>
    );
  }

  return (
    <section id="rsvp" className="section alt" data-screen-label="RSVP">
      <div className="section-inner">
        <div className="section-header">
          <div className="section-eyebrow">confirme sua presença</div>
          <h2 className="section-title">Você Está na Lista?</h2>
          <p className="section-sub">Digite seu nome para localizar seu convite.</p>
        </div>

        <div className="rsvp-card">
          <div className="search-row">
            <Icons.Search size={18} className="search-icon"/>
            <input
              type="text"
              className="search-input"
              placeholder="Digite seu nome…"
              value={query}
              onChange={e => { setQuery(e.target.value); setSelected(null); }}
              autoComplete="off"
            />
          </div>

          {groups == null && (
            <div className="empty-state"><p>Carregando lista de convidados…</p></div>
          )}

          {groups != null && query.trim() === "" && (
            <div className="empty-state"><p>Comece a digitar para buscar</p></div>
          )}

          {groups != null && query.trim() !== "" && !selected && results.length === 0 && (
            <div className="empty-state">
              <p>Nenhum convite encontrado com <b>"{query}"</b>.</p>
              <p style={{fontSize:14, marginTop:6}}>Verifique a grafia ou entre em contato com os noivos.</p>
            </div>
          )}

          {!selected && results.length > 0 && (
            <div className="results">
              {results.map(g => (
                <div key={g.id} className="result-item" onClick={() => selecionar(g)}>
                  <div>
                    <div className="nome">{g.rotulo || (g.membros || []).join(", ")}</div>
                    <div className="meta">
                      {(g.membros || []).length} pessoa{(g.membros || []).length > 1 ? "s" : ""}
                      {g.mesa != null ? ` · Mesa ${g.mesa}` : ""}
                    </div>
                  </div>
                  <Icons.Search size={16}/>
                </div>
              ))}
            </div>
          )}

          {selected && (
            <div className="rsvp-group">
              <div className="rsvp-group-head">
                <div className="nome">{selected.rotulo || "Seu convite"}</div>
                <button className="link-back" onClick={() => setSelected(null)}>← trocar</button>
              </div>
              <p className="rsvp-group-sub">Marque quem vai comparecer:</p>
              <div className="membros-check">
                {(selected.membros || []).map(n => (
                  <label
                    className={`membro-check${presentes[n] ? ' on' : ''}${travados[n] ? ' locked' : ''}`}
                    key={n}
                    title={travados[n] ? "Presença já confirmada" : undefined}
                  >
                    <input type="checkbox" checked={!!presentes[n]} disabled={!!travados[n]} onChange={() => toggle(n)}/>
                    <span className="box">{presentes[n] ? <Icons.Check size={14}/> : null}</span>
                    <span className="nm">{n}</span>
                  </label>
                ))}
              </div>
              <div style={{display:'flex', justifyContent:'center', marginTop:20}}>
                <button className="btn" disabled={salvando} onClick={confirmar}>
                  <Icons.Check size={16}/> {salvando ? "Salvando…" : "Confirmar presença"}
                </button>
              </div>
            </div>
          )}
        </div>
      </div>
    </section>
  );
}

// === Caixa de pagamento Pix (QR Code + Copia e Cola) — reutilizável ===
function PixQRBox({ data, valor, gift, onToast }) {
  const pix = (data && data.pix) || {};
  const cidade = String((data && data.local && data.local.cidade) || "").split(",")[0];
  const [copied, setCopied] = useState(false);

  // Identifica o presente dentro do próprio Pix (nome + trecho do id, para
  // não colidir se dois presentes tiverem nomes parecidos). Esse texto
  // costuma aparecer como "Identificador" no comprovante/extrato de quem
  // recebe, ajudando a saber depois qual presente aquele Pix pagou.
  const txid = gift ? String(gift.nome || "") + String(gift.id || "").slice(-6) : "";

  const payload = useMemo(() => (
    window.PixBR
      ? window.PixBR.montarPayload({
          chave: pix.chave,
          nome: pix.titular,
          cidade: cidade,
          valor: valor,
          txid: txid,
        })
      : ""
  ), [pix.chave, pix.titular, cidade, valor, txid]);

  const qr = useMemo(() => (
    window.PixBR ? window.PixBR.qrDataURL(payload) : ""
  ), [payload]);

  async function copy() {
    try {
      await navigator.clipboard.writeText(payload);
      setCopied(true);
      onToast?.("Código Pix copiado!");
      setTimeout(() => setCopied(false), 2000);
    } catch {
      onToast?.("Não foi possível copiar");
    }
  }

  if (!pix.chave) {
    return <div className="pix-qr-aviso">A chave Pix ainda não foi configurada pelos noivos.</div>;
  }

  return (
    <div className="pix-qr">
      {qr ? (
        <img className="pix-qr-img" src={qr} alt="QR Code para pagamento via Pix" width="220" height="220"/>
      ) : (
        <div className="pix-qr-aviso">Não foi possível gerar o QR Code.</div>
      )}
      <p className="pix-qr-help">
        Abra o app do seu banco, escolha <b>Pix &rsaquo; Ler QR Code</b> e aponte para a imagem acima.
      </p>
      <div className="pix-copia-label">Ou use o Pix Copia e Cola:</div>
      <div className="pix-copia-box"><code className="pix-copia-code">{payload}</code></div>
      <button className="btn ink pix-copia-btn" onClick={copy}>
        {copied ? <><Icons.Check size={16}/> Copiado!</> : <><Icons.Copy size={16}/> Copiar código Pix</>}
      </button>
    </div>
  );
}

// === Brick de cartão (Mercado Pago) — tokeniza o cartão e processa via backend ===
function CartaoBrick({ amount, descricao, onApproved, onToast }) {
  const containerId = useMemo(
    () => "mp-card-brick-" + Math.random().toString(36).slice(2),
    []
  );
  const cfg = window.MP_CONFIG || {};
  const configurado =
    !!cfg.publicKey && !String(cfg.publicKey).includes("COLE_") &&
    !!cfg.apiUrl && !String(cfg.apiUrl).includes("COLE_");

  const [estado, setEstado] = useState(configurado ? "carregando" : "nao-config");

  useEffect(() => {
    if (!configurado) return;

    let controller = null;
    let cancelado = false;
    let tentativas = 0;

    function iniciar() {
      if (cancelado) return;
      if (!window.MercadoPago) {
        // o SDK pode ainda estar carregando — tenta de novo por alguns segundos
        if (tentativas++ < 40) return void setTimeout(iniciar, 150);
        return setEstado("erro-sdk");
      }
      try {
        const mp = new window.MercadoPago(cfg.publicKey, { locale: "pt-BR" });
        mp.bricks()
          .create("cardPayment", containerId, {
            initialization: { amount: Number(amount) || 0 },
            customization: {
              paymentMethods: { maxInstallments: Number(cfg.maxParcelas) || 12 },
              visual: {
                style: {
                  customVariables: {
                    // Paleta do site (marinho + creme) aplicada aos campos
                    // nativos do Mercado Pago, incluindo o seletor de parcelas.
                    textPrimaryColor: "#15192c",
                    textSecondaryColor: "#595e78",
                    inputBackgroundColor: "#fffdf9",
                    formBackgroundColor: "#f4ead8",
                    baseColor: "#15192c",
                    borderRadiusMedium: "10px",
                    borderRadiusLarge: "10px",
                  },
                },
              },
            },
            callbacks: {
              onReady: () => { if (!cancelado) setEstado("pronto"); },
              onError: (err) => { console.error("[MP brick]", err); },
              onSubmit: (formData) =>
                fetch(cfg.apiUrl, {
                  method: "POST",
                  headers: { "Content-Type": "application/json" },
                  body: JSON.stringify(
                    Object.assign({}, formData, {
                      transaction_amount: Number(amount) || 0,
                      description: descricao,
                    })
                  ),
                })
                  .then((r) => r.json())
                  .then((res) => {
                    if (res.status === "approved" || res.status === "in_process") {
                      onApproved(res);
                      return res;
                    }
                    onToast?.(
                      res.status === "rejected"
                        ? "Pagamento recusado. Confira os dados ou tente outro cartão."
                        : (res.message || "Não foi possível processar o pagamento.")
                    );
                    throw new Error(res.status_detail || "rejeitado");
                  })
                  .catch((e) => {
                    if (e && e.message && e.message !== "rejeitado") {
                      onToast?.("Falha de conexão ao processar. Tente novamente.");
                    }
                    throw e;
                  }),
            },
          })
          .then((c) => {
            if (cancelado) c.unmount();
            else controller = c;
          })
          .catch((e) => {
            console.error("[MP brick] criar:", e);
            if (!cancelado) setEstado("erro-sdk");
          });
      } catch (e) {
        console.error("[MP brick] init:", e);
        setEstado("erro-sdk");
      }
    }

    iniciar();
    return () => {
      cancelado = true;
      if (controller) { try { controller.unmount(); } catch (e) {} }
    };
  }, []);

  if (estado === "nao-config") {
    return (
      <div className="pix-qr-aviso">
        O pagamento com cartão ainda está sendo ativado pelos noivos.<br/>
        Use o <b>Pix</b> ao lado — funciona normalmente. 💛
      </div>
    );
  }
  if (estado === "erro-sdk") {
    return (
      <div className="pix-qr-aviso">
        Não foi possível carregar o pagamento com cartão agora.<br/>
        Tente recarregar a página ou use o <b>Pix</b>.
      </div>
    );
  }

  return (
    <div className="cartao-brick-wrap">
      {estado === "carregando" && (
        <div className="cartao-brick-loading">Carregando pagamento seguro…</div>
      )}
      <div id={containerId}></div>
    </div>
  );
}

// === Modal de pagamento (Pix + Cartão de crédito com parcelamento) ===
function PagamentoModal({ gift, data, onClose, onToast }) {
  const [metodo, setMetodo] = useState("pix");   // "pix" | "cartao"
  const [doador, setDoador] = useState("");
  const [mensagem, setMensagem] = useState("");
  const [enviando, setEnviando] = useState(false);
  const [confirmado, setConfirmado] = useState(false);
  const [resultado, setResultado] = useState(null); // dados do pagamento aprovado (cartão)

  const valor = Number(gift.preco) || 0;

  // Mantém os campos nome/mensagem acessíveis dentro do callback do Brick.
  const extraRef = useRef({ doador: "", mensagem: "" });
  extraRef.current = { doador, mensagem };

  useEffect(() => {
    const onKey = (e) => { if (e.key === 'Escape') onClose(); };
    document.addEventListener('keydown', onKey);
    document.body.style.overflow = 'hidden';
    return () => {
      document.removeEventListener('keydown', onKey);
      document.body.style.overflow = '';
    };
  }, []);

  function jaPaguei() {
    if (!doador.trim()) {
      onToast?.("Digite seu nome para registrarmos seu presente 💛");
      return;
    }
    setEnviando(true);
    Store.addDoacao({
      presenteId: gift.id,
      presenteNome: gift.nome,
      valor: valor,
      doador: doador.trim(),
      mensagem: mensagem.trim(),
      metodo: "pix",
      status: "registrado",
    })
      .then(() => {
        setConfirmado(true);
        onToast?.("Presente registrado. Muito obrigado! 💛");
        Store.reserveGift(gift.id, "pix").catch(() => {});
      })
      .catch(() => {
        onToast?.("Não foi possível registrar. Tente novamente.");
      })
      .then(() => setEnviando(false));
  }

  // Chamado pelo Brick quando o cartão é aprovado/processando.
  function cartaoAprovado(res) {
    const extra = extraRef.current;
    setResultado(res);
    setConfirmado(true);
    Store.addDoacao({
      presenteId: gift.id,
      presenteNome: gift.nome,
      valor: Number(res.transaction_amount) || valor,
      doador: extra.doador.trim() || "Presente no cartão",
      mensagem: extra.mensagem.trim(),
      metodo: "cartao",
      parcelas: Number(res.installments) || 1,
      status: res.status || "approved",
      pagamentoId: res.id,
    }).catch(() => {});
    if (res.status === "approved") {
      Store.reserveGift(gift.id, "cartao").catch(() => {});
    }
    onToast?.("Pagamento aprovado. Muito obrigado! 💛");
  }

  const precoFmt = "R$ " + valor.toFixed(2).replace('.', ',');

  return (
    <div className="modal-overlay" onClick={onClose}>
      <div className="modal-card modal-pay" onClick={e => e.stopPropagation()}>
        <button className="modal-close" onClick={onClose} aria-label="Fechar">✕</button>

        {confirmado ? (
          <div className="modal-done">
            <div className="modal-done-check"><Icons.Check size={38}/></div>
            <div className="modal-title">
              Obrigado{(resultado ? "" : (doador.trim() ? ", " + doador.trim() : ""))}! 💛
            </div>
            {resultado && resultado.status === "in_process" ? (
              <p className="modal-note">
                Seu presente <b>{gift.nome}</b> está sendo processado pela operadora.<br/>
                Assim que for aprovado, está tudo certo. 💳
              </p>
            ) : resultado ? (
              <p className="modal-note">
                Seu presente <b>{gift.nome}</b> foi pago
                {Number(resultado.installments) > 1
                  ? ` em ${resultado.installments}x`
                  : ""} no cartão.<br/>
                Os noivos agradecem de coração. 💳
              </p>
            ) : (
              <p className="modal-note">
                Seu presente <b>{gift.nome}</b> foi registrado.<br/>
                Os noivos vão amar — assim que o Pix cair, está tudo certo.
              </p>
            )}
            <button className="btn ink" onClick={onClose}>Fechar</button>
          </div>
        ) : (
          <>
            <div className="modal-eyebrow">PRESENTE SELECIONADO</div>
            <div className="modal-title">Giovanna &amp; Miguel</div>

            <div className="modal-gift-name">{gift.nome}</div>
            <div className="modal-gift-price">{precoFmt}</div>

            <div className="pay-tabs">
              <button
                className={"pay-tab" + (metodo === "pix" ? " active" : "")}
                onClick={() => setMetodo("pix")}
              >
                <Icons.Pin size={15}/> Pix
              </button>
              <button
                className={"pay-tab" + (metodo === "cartao" ? " active" : "")}
                onClick={() => setMetodo("cartao")}
              >
                <Icons.Card size={15}/> Cartão de crédito
              </button>
            </div>

            <hr className="modal-divider"/>

            {metodo === "pix" ? (
              <div className="modal-pay-cols">
                <div className="modal-pay-col">
                  <PixQRBox data={data} valor={valor} gift={gift} onToast={onToast}/>
                </div>

                <div className="modal-confirm modal-pay-col">
                  <div className="modal-confirm-title">Já pagou? Confirme aqui 👇</div>
                  <label className="admin-field">
                    <span>Seu nome</span>
                    <input
                      value={doador}
                      onChange={e => setDoador(e.target.value)}
                      placeholder="Como devemos te agradecer?"
                      maxLength={80}
                    />
                  </label>
                  <label className="admin-field">
                    <span>Mensagem aos noivos (opcional)</span>
                    <textarea
                      rows={2}
                      value={mensagem}
                      onChange={e => setMensagem(e.target.value)}
                      placeholder="Deixe um recadinho ✨"
                      maxLength={300}
                    />
                  </label>
                  <button className="btn-gift modal-paid-btn" onClick={jaPaguei} disabled={enviando}>
                    {enviando ? "Registrando…" : <><Icons.Check size={16}/> Já fiz o Pix</>}
                  </button>
                </div>
              </div>
            ) : (
              <div className="modal-pay-cols">
                <div className="modal-confirm modal-pay-col">
                  <div className="modal-confirm-title">Seus dados (opcional)</div>
                  <label className="admin-field">
                    <span>Seu nome</span>
                    <input
                      value={doador}
                      onChange={e => setDoador(e.target.value)}
                      placeholder="Como devemos te agradecer?"
                      maxLength={80}
                    />
                  </label>
                  <label className="admin-field">
                    <span>Mensagem aos noivos (opcional)</span>
                    <textarea
                      rows={2}
                      value={mensagem}
                      onChange={e => setMensagem(e.target.value)}
                      placeholder="Deixe um recadinho ✨"
                      maxLength={300}
                    />
                  </label>
                  <div className="cartao-parcela-card">
                    <div className="cartao-parcela-icone"><Icons.Card size={17}/></div>
                    <div className="cartao-parcela-texto">
                      Parcele em até <strong>{(window.MP_CONFIG && window.MP_CONFIG.maxParcelas) || 12}x</strong> no
                      cartão — as opções aparecem assim que os dados forem preenchidos.
                      <span className="cartao-parcela-bandeiras">
                        Parcelamento disponível para{" "}
                        <strong>
                          {((window.MP_CONFIG && window.MP_CONFIG.bandeirasParceladas) ||
                            ["Mastercard", "Elo", "American Express"]
                          ).join(", ")}
                        </strong>
                        . Demais bandeiras são aceitas normalmente, apenas à vista.
                      </span>
                    </div>
                  </div>
                </div>

                <div className="modal-pay-col">
                  <CartaoBrick
                    amount={valor}
                    descricao={"Presente: " + (gift.nome || "casamento")}
                    onApproved={cartaoAprovado}
                    onToast={onToast}
                  />
                </div>
              </div>
            )}
          </>
        )}
      </div>
    </div>
  );
}

// === Lista de presentes ===
function GiftList({ data, gifts, onDonate }) {
  // gifts === null -> ainda carregando (usa exemplos); array -> dados reais
  const lista = gifts == null ? data.presentes : gifts;
  const [expandido, setExpandido] = useState(false);
  const [isMobile, setIsMobile] = useState(() => window.matchMedia("(max-width: 639px)").matches);
  useEffect(() => {
    const mq = window.matchMedia("(max-width: 639px)");
    const onChange = e => setIsMobile(e.matches);
    mq.addEventListener("change", onChange);
    return () => mq.removeEventListener("change", onChange);
  }, []);
  const LIMITE = isMobile ? 5 : 6;
  const visiveis = expandido ? lista : lista.slice(0, LIMITE);
  return (
    <section id="presentes" className="section" data-screen-label="Presentes">
      <div className="section-inner">
        <div className="section-header">
          <div className="section-eyebrow">com carinho</div>
          <h2 className="section-title">Lista de Presentes</h2>
          <p className="section-sub">Escolha um item que queira nos presentear — sua presença já é o maior presente.</p>
        </div>

        {lista.length === 0 ? (
          <div className="empty-state">
            <p>A lista de presentes está sendo preparada com carinho. Volte em breve 💐</p>
          </div>
        ) : (
          <>
            <div className="gifts-grid">
              {visiveis.map(g => (
                <div className={"gift-card" + (g.reservado ? " is-reservado" : "")} key={g.id}>
                  <div className="gift-img">
                    <img src={g.img} alt={g.nome} onError={e => { e.target.style.display='none'; e.target.parentElement.innerHTML = '<div style="color:#999;font-size:11px;font-style:italic">imagem</div>'; }}/>
                  </div>
                  <div className="gift-info">
                    <div className="nome">{g.nome}</div>
                    <div className="desc">{renderRich(g.desc)}</div>
                    <div className="gift-footer">
                      <div className="preco">R$ {(Number(g.preco) || 0).toFixed(2).replace('.', ',')}</div>
                      {g.reservado ? (
                        <span className="gift-reservado-tag">
                          <Icons.Check size={14}/> Já presenteado
                        </span>
                      ) : (
                        <button className="btn-gift" onClick={() => onDonate(g)}>
                          <Icons.Gift size={14}/> Doar presente
                        </button>
                      )}
                    </div>
                  </div>
                </div>
              ))}
            </div>
            {lista.length > LIMITE && (
              <div className="gifts-toggle-wrap">
                <button className="btn-gifts-toggle" onClick={() => setExpandido(v => !v)}>
                  {expandido ? "Ver menos" : "Ver lista completa"}
                </button>
              </div>
            )}
          </>
        )}
      </div>
    </section>
  );
}

// === Pix ===
function PixSection({ data, onToast }) {
  const [copied, setCopied] = useState(false);

  async function copy() {
    try {
      await navigator.clipboard.writeText(data.pix.chave);
      setCopied(true);
      onToast?.("Chave Pix copiada!");
      setTimeout(() => setCopied(false), 2000);
    } catch {
      onToast?.("Não foi possível copiar");
    }
  }

  return (
    <section id="pix" className="section alt" data-screen-label="Pix">
      <div className="section-inner">
        <div className="section-header">
          <div className="section-eyebrow">presente em dinheiro</div>
          <h2 className="section-title">Pix dos Noivos</h2>
          <p className="section-sub">Se preferir, contribua diretamente — toda generosidade é recebida com gratidão.</p>
        </div>

        <div className="pix-card">
          <div className="pix-label">CHAVE PIX</div>
          <div className="pix-key">{data.pix.chave}</div>
          <div className="pix-meta">
            <span><b>Titular:</b> {data.pix.titular}</span>
            <span><b>Banco:</b> {data.pix.banco}</span>
          </div>
          <button className="btn ink" onClick={copy}>
            {copied ? <><Icons.Check size={16}/> Copiado!</> : <><Icons.Copy size={16}/> Copiar chave Pix</>}
          </button>
        </div>
      </div>
    </section>
  );
}

// === Topbar ===
function Topbar({ active, onNav, data, scrolled }) {
  const items = [
    { id: "inicio", label: "Início" },
    { id: "sobre", label: "Sobre" },
    { id: "detalhes", label: "Detalhes" },
    { id: "presentes", label: "Presentes" },
    { id: "pix", label: "Pix" },
    { id: "rsvp", label: "Presença" },
  ];
  return (
    <header className={`topbar${scrolled ? ' scrolled' : ''}`}>
      <div className="brand">
        {data.noivos.iniciais[0]} &amp; {data.noivos.iniciais[1]}
      </div>
      <nav>
        {items.map(it => (
          <a key={it.id} className={active === it.id ? 'active' : ''} onClick={() => onNav(it.id)}>{it.label}</a>
        ))}
      </nav>
      <div className="topbar-date">
        {data.dataExibicao.dia}.{String(data.dataExibicao.mesNum || 12).padStart(2,'0')}.{data.dataExibicao.ano}
      </div>
    </header>
  );
}

// === BottomNav (mobile) ===
function BottomNav({ active, onNav }) {
  const items = [
    { id: "inicio", label: "Início", Icon: Icons.Home },
    { id: "detalhes", label: "Detalhes", Icon: Icons.Calendar },
    { id: "presentes", label: "Presentes", Icon: Icons.Gift },
    { id: "pix", label: "Pix", Icon: Icons.Pin },
    { id: "rsvp", label: "Presença", Icon: Icons.Mail },
  ];
  return (
    <nav className="bottomnav">
      {items.map(({ id, label, Icon }) => (
        <button key={id} className={`bottomnav-item ${active === id ? 'active' : ''}`} onClick={() => onNav(id)}>
          <Icon size={20}/>
          <span>{label}</span>
        </button>
      ))}
    </nav>
  );
}

// === Footer ===
function Footer({ data }) {
  return (
    <footer className="footer">
      <div style={{fontFamily:"'Pinyon Script', cursive", fontSize:28, color:'var(--ink)'}}>
        {data.noivos.nome1} &amp; {data.noivos.nome2}
      </div>
      <div style={{fontSize:13, marginTop:6, opacity:0.85}}>
        {data.dataExibicao.dia}.{String(data.dataExibicao.mesNum || 12).padStart(2,'0')}.{data.dataExibicao.ano} · {data.local.cidade}
      </div>
    </footer>
  );
}

Object.assign(window, {
  Hero, About, EventDetails, GuestSearch, GiftList, PixSection,
  Topbar, BottomNav, Footer, Countdown, PagamentoModal,
});
