// ============================================================
//  Área administrativa (painel dos noivos)
//  Acesse adicionando #admin ao endereço do site.
// ============================================================
const { useState: useSt, useEffect: useEf, useRef: useRf } = React;

const SITE_URL = window.location.pathname || "./";

function fmtBRL(n) {
  return "R$ " + (Number(n) || 0).toFixed(2).replace(".", ",");
}

// Formata um timestamp do Firestore (ou Date/ISO) para data e hora pt-BR.
function fmtData(ts) {
  try {
    const d = ts && ts.toDate ? ts.toDate() : ts ? new Date(ts) : null;
    if (!d || isNaN(d.getTime())) return "";
    return (
      d.toLocaleDateString("pt-BR") +
      " às " +
      d.toLocaleTimeString("pt-BR", { hour: "2-digit", minute: "2-digit" })
    );
  } catch (e) {
    return "";
  }
}

function traduzErroAuth(e) {
  const c = (e && e.code) || "";
  if (
    c.indexOf("invalid-credential") >= 0 ||
    c.indexOf("wrong-password") >= 0 ||
    c.indexOf("user-not-found") >= 0
  )
    return "E-mail ou senha incorretos.";
  if (c.indexOf("invalid-email") >= 0) return "E-mail inválido.";
  if (c.indexOf("too-many-requests") >= 0)
    return "Muitas tentativas. Aguarde um momento e tente novamente.";
  if (c.indexOf("network") >= 0)
    return "Sem conexão. Verifique a internet.";
  return (e && e.message) || "Não foi possível entrar.";
}

// --- Campo de texto com botão de negrito ---
// Envolve os "**" do markdown simples em volta do trecho selecionado
// (ou remove, se o trecho já estiver em negrito). O site (sections.jsx)
// interpreta "**texto**" e exibe em <strong>. Funciona tanto em <textarea>
// quanto em <input> de linha única (ambos suportam selectionStart/End).
function aplicarNegritoNoElemento(el, value, onChange) {
  if (!el) return;
  const start = el.selectionStart;
  const end = el.selectionEnd;
  if (start == null || end == null || start === end) return; // nada selecionado

  const antes = value.slice(0, start);
  const selecionado = value.slice(start, end);
  const depois = value.slice(end);
  const jaNegrito =
    selecionado.length >= 4 &&
    selecionado.startsWith("**") &&
    selecionado.endsWith("**");

  let novoValor, novoStart, novoEnd;
  if (jaNegrito) {
    const miolo = selecionado.slice(2, -2);
    novoValor = antes + miolo + depois;
    novoStart = start;
    novoEnd = start + miolo.length;
  } else {
    novoValor = antes + "**" + selecionado + "**" + depois;
    novoStart = start;
    novoEnd = end + 4;
  }

  onChange(novoValor);
  requestAnimationFrame(function () {
    el.focus();
    el.setSelectionRange(novoStart, novoEnd);
  });
}

function BoldButton({ onClick }) {
  return (
    <div className="admin-richfield-toolbar">
      <button
        type="button"
        className="admin-bold-btn"
        onClick={onClick}
        title="Selecione um trecho do texto e clique para deixar em negrito"
        aria-label="Aplicar negrito ao texto selecionado"
      >
        <b>B</b>
      </button>
    </div>
  );
}

function BoldField({ value, onChange, rows, maxLength, placeholder }) {
  const taRef = useRf(null);
  return (
    <div className="admin-richfield">
      <BoldButton onClick={() => aplicarNegritoNoElemento(taRef.current, value, onChange)} />
      <textarea
        ref={taRef}
        value={value}
        onChange={(e) => onChange(e.target.value)}
        rows={rows}
        maxLength={maxLength}
        placeholder={placeholder}
      />
    </div>
  );
}

function BoldInput({ value, onChange, maxLength, placeholder }) {
  const inRef = useRf(null);
  return (
    <div className="admin-richfield">
      <BoldButton onClick={() => aplicarNegritoNoElemento(inRef.current, value, onChange)} />
      <input
        ref={inRef}
        value={value}
        onChange={(e) => onChange(e.target.value)}
        maxLength={maxLength}
        placeholder={placeholder}
      />
    </div>
  );
}

// --- Configuração ainda pendente ---
function AdminSetup() {
  return (
    <div className="adm-auth">
      <div className="adm-auth-card adm-setup">
        <div className="adm-auth-logo">G&amp;M</div>
        <h1 className="adm-auth-title">Configuração necessária</h1>
        <p>Para ativar o painel, cole as credenciais do Firebase no arquivo:</p>
        <code>src/firebase-config.js</code>
        <p>
          O passo a passo completo está no arquivo <b>LEIA-ME-ADMIN.md</b>,
          na pasta do site.
        </p>
        <a className="adm-btn-primary" href={SITE_URL}>← Voltar ao site</a>
      </div>
    </div>
  );
}

// --- Tela de login ---
function AdminLogin() {
  const [email, setEmail] = useSt("");
  const [senha, setSenha] = useSt("");
  const [erro, setErro] = useSt("");
  const [busy, setBusy] = useSt(false);

  function submit(e) {
    e.preventDefault();
    setErro("");
    setBusy(true);
    Store.login(email.trim(), senha).catch(function (er) {
      setErro(traduzErroAuth(er));
      setBusy(false);
    });
  }

  return (
    <div className="adm-auth">
      <form className="adm-auth-card" onSubmit={submit}>
        <div className="adm-auth-logo">G&amp;M</div>
        <h1 className="adm-auth-title">Painel dos Noivos</h1>
        <p className="adm-auth-sub">
          Acesso restrito · entre para gerenciar presentes e convidados.
        </p>

        <label className="adm-field">
          <span>E-mail</span>
          <input
            type="email"
            value={email}
            onChange={(e) => setEmail(e.target.value)}
            autoComplete="username"
            placeholder="seu@email.com"
            required
          />
        </label>
        <label className="adm-field">
          <span>Senha</span>
          <input
            type="password"
            value={senha}
            onChange={(e) => setSenha(e.target.value)}
            autoComplete="current-password"
            placeholder="••••••••"
            required
          />
        </label>

        {erro && <div className="adm-error">{erro}</div>}

        <button className="adm-btn-primary block" type="submit" disabled={busy}>
          {busy ? "Entrando…" : "Entrar no painel"}
        </button>
        <a className="adm-auth-back" href={SITE_URL}>← Voltar ao site</a>
      </form>
    </div>
  );
}

// --- Formulário de presente (adicionar / editar) ---
function GiftForm({ inicial, onSalvar, onCancelar }) {
  const [nome, setNome] = useSt((inicial && inicial.nome) || "");
  const [desc, setDesc] = useSt((inicial && inicial.desc) || "");
  const [preco, setPreco] = useSt(
    inicial && inicial.preco != null ? String(inicial.preco).replace(".", ",") : ""
  );
  const [img, setImg] = useSt((inicial && inicial.img) || "");
  const [erro, setErro] = useSt("");
  const [busy, setBusy] = useSt(false);
  const [carregandoImg, setCarregandoImg] = useSt(false);
  const fileRef = useRf(null);

  function escolherArquivo(file) {
    if (!file) return;
    setCarregandoImg(true);
    setErro("");
    Store.resizeImage(file)
      .then(function (dataUrl) {
        setImg(dataUrl);
      })
      .catch(function () {
        setErro("Não foi possível processar a imagem. Tente outra foto.");
      })
      .then(function () {
        setCarregandoImg(false);
      });
  }

  function submit(e) {
    e.preventDefault();
    const precoNum = parseFloat(
      String(preco).replace(/\./g, "").replace(",", ".")
    );
    if (!nome.trim()) return setErro("Informe o título do presente.");
    if (isNaN(precoNum) || precoNum < 0)
      return setErro("Informe um valor válido (ex.: 129,90).");

    setBusy(true);
    setErro("");
    Promise.resolve(
      onSalvar({
        nome: nome.trim(),
        desc: desc.trim(),
        preco: precoNum,
        img: img,
      })
    ).catch(function () {
      setErro("Erro ao salvar. Verifique a conexão e tente novamente.");
      setBusy(false);
    });
  }

  return (
    <form className="admin-card gift-form" onSubmit={submit}>
      <h2>{inicial ? "Editar presente" : "Adicionar presente"}</h2>

      <div className="gift-form-grid">
        <div className="gift-form-img">
          <div
            className={"img-drop" + (img ? " has-img" : "")}
            onClick={() => fileRef.current && fileRef.current.click()}
            onDragOver={(e) => e.preventDefault()}
            onDrop={(e) => {
              e.preventDefault();
              escolherArquivo(e.dataTransfer.files[0]);
            }}
          >
            {carregandoImg ? (
              <span>Processando…</span>
            ) : img ? (
              <img src={img} alt="Prévia do presente" />
            ) : (
              <span>
                📁
                <br />
                Clique ou arraste
                <br />a foto aqui
              </span>
            )}
          </div>
          {img && (
            <button
              type="button"
              className="link-remove"
              onClick={() => setImg("")}
            >
              Remover imagem
            </button>
          )}
          <input
            ref={fileRef}
            type="file"
            accept="image/*"
            hidden
            onChange={(e) => escolherArquivo(e.target.files[0])}
          />
        </div>

        <div className="gift-form-fields">
          <label className="admin-field">
            <span>Título</span>
            <input
              value={nome}
              onChange={(e) => setNome(e.target.value)}
              placeholder="Ex.: Jogo de panelas Tramontina"
              maxLength={80}
            />
          </label>
          <label className="admin-field">
            <span>Descrição</span>
            <BoldField
              value={desc}
              onChange={setDesc}
              placeholder="Uma breve descrição do presente"
              rows={3}
              maxLength={240}
            />
          </label>
          <label className="admin-field">
            <span>Valor (R$)</span>
            <input
              value={preco}
              onChange={(e) => setPreco(e.target.value)}
              placeholder="0,00"
              inputMode="decimal"
            />
          </label>
        </div>
      </div>

      {erro && <div className="admin-error">{erro}</div>}

      <div className="gift-form-actions">
        {onCancelar && (
          <button
            type="button"
            className="btn ghost small"
            onClick={onCancelar}
          >
            Cancelar
          </button>
        )}
        <button className="btn" type="submit" disabled={busy || carregandoImg}>
          {busy
            ? "Salvando…"
            : inicial
            ? "Salvar alterações"
            : "Adicionar presente"}
        </button>
      </div>
    </form>
  );
}

// --- Gerenciador de presentes ---
function GiftsManager() {
  const [gifts, setGifts] = useSt(null);
  const [editando, setEditando] = useSt(null);
  const [mostrarForm, setMostrarForm] = useSt(false);

  useEf(function () {
    return Store.subscribeGifts(setGifts);
  }, []);

  function adicionar(dados) {
    return Store.addGift(dados).then(function () {
      setMostrarForm(false);
    });
  }
  function salvarEdicao(dados) {
    return Store.updateGift(editando.id, dados).then(function () {
      setEditando(null);
    });
  }
  function remover(g) {
    if (!window.confirm('Remover "' + g.nome + '" da lista de presentes?'))
      return;
    Store.deleteGift(g.id).catch(function () {
      window.alert("Não foi possível remover. Tente novamente.");
    });
  }
  function desbloquear(g) {
    if (!window.confirm('Marcar "' + g.nome + '" como disponível novamente?'))
      return;
    Store.unlockGift(g.id).catch(function () {
      window.alert("Não foi possível desbloquear. Tente novamente.");
    });
  }
  function marcarRecebido(g) {
    const nome = window.prompt(
      'Presente "' +
        g.nome +
        '": nome de quem presenteou (deixe em branco se não souber, ex.: Pix sem identificação)?',
      ""
    );
    if (nome === null) return; // cancelado
    Store.reserveGift(g.id, "manual")
      .then(function () {
        return Store.addDoacao({
          presenteId: g.id,
          presenteNome: g.nome,
          valor: g.preco,
          doador: nome.trim() || "Não identificado",
          mensagem: "Marcado manualmente pelos noivos.",
          metodo: "pix-manual",
          status: "registrado",
        });
      })
      .catch(function () {
        window.alert("Não foi possível marcar como recebido. Tente novamente.");
      });
  }
  function mover(index, direcao) {
    const alvo = index + direcao;
    if (!gifts || alvo < 0 || alvo >= gifts.length) return;
    Store.swapGiftOrder(gifts[index], gifts[alvo]).catch(function () {
      window.alert("Não foi possível reordenar. Tente novamente.");
    });
  }

  const totalGifts = gifts ? gifts.length : 0;
  const valorTotal = (gifts || []).reduce(function (s, g) {
    return s + (Number(g.preco) || 0);
  }, 0);

  return (
    <>
      <div className="adm-stats">
        <div className="adm-stat">
          <div className="adm-stat-icon"><Icons.Gift size={18} /></div>
          <div>
            <div className="adm-stat-num">{totalGifts}</div>
            <div className="adm-stat-label">Presentes cadastrados</div>
          </div>
        </div>
        <div className="adm-stat">
          <div className="adm-stat-icon"><Icons.Star size={18} /></div>
          <div>
            <div className="adm-stat-num">{fmtBRL(valorTotal)}</div>
            <div className="adm-stat-label">Valor total da lista</div>
          </div>
        </div>
      </div>

      <div className="adm-toolbar">
        <h2 className="adm-section-title">Lista de presentes</h2>
        {!editando && !mostrarForm && (
          <button className="adm-btn-primary" onClick={() => setMostrarForm(true)}>
            <Icons.Gift size={16} /> Adicionar presente
          </button>
        )}
      </div>

      {editando ? (
        <GiftForm
          inicial={editando}
          onSalvar={salvarEdicao}
          onCancelar={() => setEditando(null)}
        />
      ) : mostrarForm ? (
        <GiftForm onSalvar={adicionar} onCancelar={() => setMostrarForm(false)} />
      ) : null}

      <div className="admin-list">
        {gifts == null && <div className="admin-muted">Carregando…</div>}
        {gifts && gifts.length === 0 && (
          <div className="admin-muted">
            Nenhum presente cadastrado ainda. Clique em “Adicionar presente”.
          </div>
        )}
        {gifts &&
          gifts.map(function (g, idx) {
            return (
              <div className="admin-gift-row" key={g.id}>
                <div className="admin-gift-reorder">
                  <button
                    className="admin-gift-reorder-btn"
                    onClick={() => mover(idx, -1)}
                    disabled={idx === 0}
                    aria-label="Mover para cima"
                  >
                    <Icons.ArrowUp size={16} />
                  </button>
                  <button
                    className="admin-gift-reorder-btn"
                    onClick={() => mover(idx, 1)}
                    disabled={idx === gifts.length - 1}
                    aria-label="Mover para baixo"
                  >
                    <Icons.ArrowDown size={16} />
                  </button>
                </div>
                <div className="admin-gift-thumb">
                  {g.img ? (
                    <img src={g.img} alt={g.nome} />
                  ) : (
                    <span>sem foto</span>
                  )}
                </div>
                <div className="admin-gift-info">
                  <div className="nome">
                    {g.nome}
                    {g.reservado && (
                      <span className="admin-gift-reservado-badge">Já presenteado</span>
                    )}
                  </div>
                  <div className="desc">{g.desc}</div>
                  <div className="preco">{fmtBRL(g.preco)}</div>
                </div>
                <div className="admin-gift-actions">
                  {g.reservado ? (
                    <button className="btn ghost small" onClick={() => desbloquear(g)}>
                      Desbloquear
                    </button>
                  ) : (
                    <button className="btn ghost small" onClick={() => marcarRecebido(g)}>
                      Marcar como recebido
                    </button>
                  )}
                  <button
                    className="btn ghost small"
                    onClick={() => {
                      setEditando(g);
                      setMostrarForm(false);
                    }}
                  >
                    Editar
                  </button>
                  <button className="btn-danger" onClick={() => remover(g)}>
                    Excluir
                  </button>
                </div>
              </div>
            );
          })}
      </div>
    </>
  );
}

// --- Formulário de grupo de convidados ---
function GuestGroupForm({ inicial, onSalvar, onCancelar }) {
  const [rotulo, setRotulo] = useSt((inicial && inicial.rotulo) || "");
  const [mesa, setMesa] = useSt(
    inicial && inicial.mesa != null ? String(inicial.mesa) : ""
  );
  const [membros, setMembros] = useSt(
    inicial && inicial.membros && inicial.membros.length
      ? inicial.membros.slice()
      : [""]
  );
  const [erro, setErro] = useSt("");
  const [busy, setBusy] = useSt(false);

  function setMembro(i, val) {
    setMembros(function (arr) {
      const c = arr.slice();
      c[i] = val;
      return c;
    });
  }
  function addMembro() {
    setMembros(function (arr) {
      return arr.concat([""]);
    });
  }
  function removeMembro(i) {
    setMembros(function (arr) {
      return arr.length <= 1 ? arr : arr.filter(function (_, idx) { return idx !== i; });
    });
  }

  function submit(e) {
    e.preventDefault();
    const nomes = membros
      .map(function (n) { return n.trim(); })
      .filter(Boolean);
    if (!nomes.length) return setErro("Adicione pelo menos uma pessoa ao grupo.");
    let mesaNum = null;
    if (String(mesa).trim() !== "") {
      mesaNum = parseInt(mesa, 10);
      if (isNaN(mesaNum)) return setErro("Número da mesa inválido.");
    }
    setBusy(true);
    setErro("");
    Promise.resolve(
      onSalvar({ rotulo: rotulo.trim(), mesa: mesaNum, membros: nomes })
    ).catch(function () {
      setErro("Erro ao salvar. Verifique a conexão e tente novamente.");
      setBusy(false);
    });
  }

  return (
    <form className="admin-card guest-form" onSubmit={submit}>
      <h2>{inicial ? "Editar grupo" : "Adicionar grupo"}</h2>

      <div className="guest-form-top">
        <label className="admin-field" style={{ flex: 2 }}>
          <span>Rótulo do grupo (opcional)</span>
          <input
            value={rotulo}
            onChange={(e) => setRotulo(e.target.value)}
            placeholder="Ex.: Família Pimenta"
            maxLength={60}
          />
        </label>
        <label className="admin-field" style={{ flex: 1 }}>
          <span>Mesa (opcional)</span>
          <input
            value={mesa}
            onChange={(e) => setMesa(e.target.value)}
            placeholder="Ex.: 4"
            inputMode="numeric"
          />
        </label>
      </div>

      <div className="admin-field">
        <span>Pessoas do grupo</span>
        <div className="membros-list">
          {membros.map(function (n, i) {
            return (
              <div className="membro-row" key={i}>
                <input
                  value={n}
                  onChange={(e) => setMembro(i, e.target.value)}
                  placeholder={"Nome da pessoa " + (i + 1)}
                  maxLength={60}
                />
                <button
                  type="button"
                  className="membro-remove"
                  onClick={() => removeMembro(i)}
                  disabled={membros.length <= 1}
                  aria-label="Remover pessoa"
                >
                  ✕
                </button>
              </div>
            );
          })}
        </div>
        <button
          type="button"
          className="btn ghost small membro-add"
          onClick={addMembro}
        >
          + Adicionar pessoa
        </button>
      </div>

      {erro && <div className="admin-error">{erro}</div>}

      <div className="gift-form-actions">
        {onCancelar && (
          <button type="button" className="btn ghost small" onClick={onCancelar}>
            Cancelar
          </button>
        )}
        <button className="btn" type="submit" disabled={busy}>
          {busy ? "Salvando…" : inicial ? "Salvar alterações" : "Adicionar grupo"}
        </button>
      </div>
    </form>
  );
}

// --- Gerenciador de convidados ---
function GuestsManager() {
  const [groups, setGroups] = useSt(null);
  const [confs, setConfs] = useSt({});
  const [editando, setEditando] = useSt(null);
  const [mostrarForm, setMostrarForm] = useSt(false);

  useEf(function () {
    return Store.subscribeGuests(setGroups);
  }, []);
  useEf(function () {
    return Store.subscribeConfirmations(setConfs);
  }, []);

  function adicionar(dados) {
    return Store.addGuestGroup(dados).then(function () {
      setMostrarForm(false);
    });
  }
  function salvarEdicao(dados) {
    return Store.updateGuestGroup(editando.id, dados).then(function () {
      setEditando(null);
    });
  }
  function remover(g) {
    const nome = g.rotulo || (g.membros || []).join(", ");
    if (!window.confirm('Remover o grupo "' + nome + '"?')) return;
    Store.deleteGuestGroup(g.id).catch(function () {
      window.alert("Não foi possível remover. Tente novamente.");
    });
  }

  function statusMembro(g, n) {
    const conf = confs[g.id];
    if (!conf || !conf.respostas || !(n in conf.respostas)) return "pendente";
    return conf.respostas[n] ? "vai" : "nao";
  }

  let totalPessoas = 0;
  let totalVai = 0;
  (groups || []).forEach(function (g) {
    (g.membros || []).forEach(function (n) {
      totalPessoas++;
      if (statusMembro(g, n) === "vai") totalVai++;
    });
  });

  const totalGrupos = groups ? groups.length : 0;

  return (
    <>
      <div className="adm-stats">
        <div className="adm-stat">
          <div className="adm-stat-icon"><Icons.Mail size={18} /></div>
          <div>
            <div className="adm-stat-num">{totalGrupos}</div>
            <div className="adm-stat-label">Grupos / convites</div>
          </div>
        </div>
        <div className="adm-stat">
          <div className="adm-stat-icon"><Icons.Heart size={18} /></div>
          <div>
            <div className="adm-stat-num">{totalPessoas}</div>
            <div className="adm-stat-label">Pessoas convidadas</div>
          </div>
        </div>
        <div className="adm-stat accent">
          <div className="adm-stat-icon"><Icons.Check size={18} /></div>
          <div>
            <div className="adm-stat-num">{totalVai}</div>
            <div className="adm-stat-label">Presenças confirmadas</div>
          </div>
        </div>
      </div>

      <div className="adm-toolbar">
        <h2 className="adm-section-title">Grupos de convidados</h2>
        {!editando && !mostrarForm && (
          <button className="adm-btn-primary" onClick={() => setMostrarForm(true)}>
            <Icons.Mail size={16} /> Adicionar grupo
          </button>
        )}
      </div>

      {editando ? (
        <GuestGroupForm
          inicial={editando}
          onSalvar={salvarEdicao}
          onCancelar={() => setEditando(null)}
        />
      ) : mostrarForm ? (
        <GuestGroupForm
          onSalvar={adicionar}
          onCancelar={() => setMostrarForm(false)}
        />
      ) : null}

      <div className="admin-list">
        {groups == null && <div className="admin-muted">Carregando…</div>}
        {groups && groups.length === 0 && (
          <div className="admin-muted">
            Nenhum grupo cadastrado ainda. Clique em “Adicionar grupo”.
          </div>
        )}
        {groups &&
          groups.map(function (g) {
            return (
              <div className="admin-guest-row" key={g.id}>
                <div className="admin-guest-info">
                  <div className="guest-head">
                    <span className="guest-rotulo">
                      {g.rotulo || "Grupo sem rótulo"}
                    </span>
                    {g.mesa != null && (
                      <span className="guest-mesa">Mesa {g.mesa}</span>
                    )}
                  </div>
                  <div className="guest-membros">
                    {(g.membros || []).map(function (n) {
                      const st = statusMembro(g, n);
                      return (
                        <span className={"guest-membro st-" + st} key={n}>
                          {st === "vai" ? "✓" : st === "nao" ? "✕" : "•"} {n}
                        </span>
                      );
                    })}
                  </div>
                </div>
                <div className="admin-gift-actions">
                  <button
                    className="btn ghost small"
                    onClick={() => {
                      setEditando(g);
                      setMostrarForm(false);
                    }}
                  >
                    Editar
                  </button>
                  <button className="btn-danger" onClick={() => remover(g)}>
                    Excluir
                  </button>
                </div>
              </div>
            );
          })}
      </div>
    </>
  );
}

// --- Gerenciador dos detalhes do evento ---
function DetalhesManager() {
  const [det, setDet] = useSt(null);
  const [dataISO, setDataISO] = useSt("");
  const [hora, setHora] = useSt("");
  const [local, setLocal] = useSt({ nome: "", endereco: "", cidade: "", cep: "", mapaQuery: "" });
  const [dress, setDress] = useSt({ titulo: "", descricao: "" });
  const [cores, setCores] = useSt([]);
  const [sobre, setSobre] = useSt({ paragrafo1: "", paragrafo2: "", paragrafo3: "" });
  const [cerimoniaTemplate, setCerimoniaTemplate] = useSt("");
  const [verMapaTexto, setVerMapaTexto] = useSt("");
  const [coresProibidasTitulo, setCoresProibidasTitulo] = useSt("");
  const [erro, setErro] = useSt("");
  const [ok, setOk] = useSt(false);
  const [busy, setBusy] = useSt(false);
  const carregado = useRf(false);
  const carregadoTextos = useRf(false);

  useEf(function () {
    return Store.subscribeDetalhes(function (d) {
      setDet(d);
      if (!carregado.current) {
        const dx = d.dataExibicao;
        setDataISO(
          dx.anoNum +
            "-" +
            String(dx.mesNum).padStart(2, "0") +
            "-" +
            String(dx.dia).padStart(2, "0")
        );
        setHora(dx.hora || "");
        setLocal({
          nome: d.local.nome || "",
          endereco: d.local.endereco || "",
          cidade: d.local.cidade || "",
          cep: d.local.cep || "",
          mapaQuery: d.local.mapaQuery || "",
        });
        setDress({
          titulo: d.dressCode.titulo || "",
          descricao: d.dressCode.descricao || "",
        });
        setCores(
          (d.dressCode.coresProibidas || []).map(function (c) {
            return { hex: c.hex, nome: c.nome };
          })
        );
        carregado.current = true;
      }
    });
  }, []);

  useEf(function () {
    return Store.subscribeTextos(function (t) {
      if (!carregadoTextos.current) {
        setSobre(t.sobre);
        setCerimoniaTemplate(t.detalhes.cerimoniaTemplate || "");
        setVerMapaTexto(t.detalhes.verMapaTexto || "");
        setCoresProibidasTitulo(t.detalhes.coresProibidasTitulo || "");
        carregadoTextos.current = true;
      }
    });
  }, []);

  function setLocalCampo(k, v) {
    setLocal(function (o) {
      return Object.assign({}, o, { [k]: v });
    });
  }
  function setDressCampo(k, v) {
    setDress(function (o) {
      return Object.assign({}, o, { [k]: v });
    });
  }
  function setCor(i, k, v) {
    setCores(function (arr) {
      const c = arr.slice();
      c[i] = Object.assign({}, c[i], { [k]: v });
      return c;
    });
  }
  function setSobreCampo(k, v) {
    setSobre(function (o) {
      return Object.assign({}, o, { [k]: v });
    });
  }

  function submit(e) {
    e.preventDefault();
    if (!dataISO) return setErro("Informe a data do casamento.");
    if (!hora) return setErro("Informe o horário da cerimônia.");
    if (!local.mapaQuery.trim()) return setErro("Informe o endereço do mapa.");
    setBusy(true);
    setErro("");
    setOk(false);
    Promise.all([
      Store.saveDetalhes({
        dataISO: dataISO,
        hora: hora,
        local: {
          nome: local.nome.trim(),
          endereco: local.endereco.trim(),
          cidade: local.cidade.trim(),
          cep: local.cep.trim(),
          mapaQuery: local.mapaQuery.trim(),
        },
        dressCode: {
          titulo: dress.titulo.trim(),
          descricao: dress.descricao.trim(),
          coresProibidas: cores.map(function (c) {
            return { hex: c.hex, nome: (c.nome || "").trim() };
          }),
        },
      }),
      Store.saveTextos({
        sobre: sobre,
        detalhes: {
          cerimoniaTemplate: cerimoniaTemplate.trim(),
          verMapaTexto: verMapaTexto.trim(),
          coresProibidasTitulo: coresProibidasTitulo.trim(),
        },
      }),
    ])
      .then(function () {
        setOk(true);
        setBusy(false);
        setTimeout(function () {
          setOk(false);
        }, 3000);
      })
      .catch(function () {
        setErro("Não foi possível salvar. Verifique a conexão e tente novamente.");
        setBusy(false);
      });
  }

  if (!det) return <div className="admin-muted">Carregando…</div>;

  return (
    <>
      <div className="adm-stats">
        <div className="adm-stat">
          <div className="adm-stat-icon"><Icons.Calendar size={18} /></div>
          <div>
            <div className="adm-stat-num adm-stat-num-sm">
              {det.dataExibicao.dia}/{String(det.dataExibicao.mesNum).padStart(2, "0")}/
              {det.dataExibicao.ano} · {det.dataExibicao.hora}
            </div>
            <div className="adm-stat-label">Data e horário</div>
          </div>
        </div>
        <div className="adm-stat">
          <div className="adm-stat-icon"><Icons.Pin size={18} /></div>
          <div>
            <div className="adm-stat-num adm-stat-num-sm">{det.local.nome}</div>
            <div className="adm-stat-label">Local da cerimônia</div>
          </div>
        </div>
        <div className="adm-stat">
          <div className="adm-stat-icon"><Icons.Shirt size={18} /></div>
          <div>
            <div className="adm-stat-num adm-stat-num-sm">{det.dressCode.titulo}</div>
            <div className="adm-stat-label">Dress code</div>
          </div>
        </div>
      </div>

      <form onSubmit={submit}>
        <div className="admin-card">
          <h2>Nosso Dia Especial</h2>
          <label className="admin-field">
            <span>Parágrafo 1</span>
            <BoldField
              rows={3}
              value={sobre.paragrafo1}
              onChange={(v) => setSobreCampo("paragrafo1", v)}
            />
          </label>
          <label className="admin-field">
            <span>Parágrafo 2</span>
            <BoldField
              rows={3}
              value={sobre.paragrafo2}
              onChange={(v) => setSobreCampo("paragrafo2", v)}
            />
          </label>
          <label className="admin-field">
            <span>Parágrafo 3</span>
            <BoldField
              rows={2}
              value={sobre.paragrafo3}
              onChange={(v) => setSobreCampo("paragrafo3", v)}
            />
          </label>
        </div>

        <div className="admin-card">
          <h2>Data &amp; Horário</h2>
          <div className="adm-form-row">
            <label className="admin-field">
              <span>Data do casamento</span>
              <input
                type="date"
                value={dataISO}
                onChange={(e) => setDataISO(e.target.value)}
              />
            </label>
            <label className="admin-field">
              <span>Horário da cerimônia</span>
              <input
                type="time"
                value={hora}
                onChange={(e) => setHora(e.target.value)}
              />
            </label>
          </div>
          <label className="admin-field">
            <span>Texto da cerimônia (exibido no card)</span>
            <BoldInput
              value={cerimoniaTemplate}
              onChange={setCerimoniaTemplate}
              placeholder="Ex.: Cerimônia às {hora} — chegue 30 min antes"
            />
          </label>
          <p className="adm-hint">
            O calendário, a contagem regressiva e as datas do site se ajustam
            sozinhos à data escolhida. O desenho do calendário não muda. Use{" "}
            <code>{"{hora}"}</code> no texto da cerimônia — ele é substituído
            automaticamente pelo horário definido acima.
          </p>
        </div>

        <div className="admin-card">
          <h2>Local &amp; Mapa</h2>
          <label className="admin-field">
            <span>Nome do local</span>
            <input
              value={local.nome}
              onChange={(e) => setLocalCampo("nome", e.target.value)}
              placeholder="Ex.: Casa Samanta Fonseca"
            />
          </label>
          <label className="admin-field">
            <span>Endereço (exibido no site)</span>
            <input
              value={local.endereco}
              onChange={(e) => setLocalCampo("endereco", e.target.value)}
              placeholder="Ex.: Av. Japão, 11000 — Parque São Martinho"
            />
          </label>
          <div className="adm-form-row">
            <label className="admin-field">
              <span>Cidade / Estado</span>
              <input
                value={local.cidade}
                onChange={(e) => setLocalCampo("cidade", e.target.value)}
                placeholder="Ex.: Mogi das Cruzes, SP"
              />
            </label>
            <label className="admin-field">
              <span>CEP</span>
              <input
                value={local.cep}
                onChange={(e) => setLocalCampo("cep", e.target.value)}
                placeholder="Ex.: 08700-000"
              />
            </label>
          </div>
          <label className="admin-field">
            <span>Endereço do mapa (Google Maps)</span>
            <input
              value={local.mapaQuery}
              onChange={(e) => setLocalCampo("mapaQuery", e.target.value)}
              placeholder="Ex.: Av. Japão 11000 Mogi das Cruzes SP"
            />
          </label>
          <label className="admin-field">
            <span>Texto do link do mapa</span>
            <input
              value={verMapaTexto}
              onChange={(e) => setVerMapaTexto(e.target.value)}
              placeholder="Ex.: Ver no mapa"
            />
          </label>
          <p className="adm-hint">
            O mapa continua aparecendo no site — você só muda o endereço para
            onde ele aponta. Digite o endereço como você buscaria no Google Maps.
          </p>
        </div>

        <div className="admin-card">
          <h2>Dress Code</h2>
          <label className="admin-field">
            <span>Título</span>
            <input
              value={dress.titulo}
              onChange={(e) => setDressCampo("titulo", e.target.value)}
              placeholder="Ex.: Esporte Fino"
            />
          </label>
          <label className="admin-field">
            <span>Descrição</span>
            <BoldField
              rows={2}
              value={dress.descricao}
              onChange={(v) => setDressCampo("descricao", v)}
              placeholder="Ex.: Tons claros, terrosos e pastéis. Evite branco."
            />
          </label>

          <label className="admin-field">
            <span>Título das cores reservadas</span>
            <input
              value={coresProibidasTitulo}
              onChange={(e) => setCoresProibidasTitulo(e.target.value)}
              placeholder="Ex.: Cores reservadas aos noivos — por favor, não usar:"
            />
          </label>

          <div className="admin-field" style={{ marginBottom: 8 }}>
            <span>Cores reservadas aos noivos (não permitidas)</span>
          </div>
          <div className="adm-cores">
            {cores.map(function (c, i) {
              return (
                <div className="adm-cor-item" key={i}>
                  <input
                    type="color"
                    className="adm-cor-pick"
                    value={c.hex}
                    onChange={(e) => setCor(i, "hex", e.target.value)}
                    aria-label={"Cor " + (i + 1)}
                  />
                  <input
                    className="adm-cor-nome"
                    value={c.nome}
                    onChange={(e) => setCor(i, "nome", e.target.value)}
                    placeholder="Nome da cor"
                    maxLength={40}
                  />
                </div>
              );
            })}
          </div>
          <p className="adm-hint">
            As bolinhas continuam as mesmas no site — você só ajusta a cor e o
            nome de cada uma.
          </p>
        </div>

        {erro && <div className="admin-error">{erro}</div>}
        {ok && (
          <div className="adm-success">
            <Icons.Check size={16} /> Detalhes atualizados! Já aparecem no site.
          </div>
        )}

        <div className="gift-form-actions">
          <button className="adm-btn-primary" type="submit" disabled={busy}>
            {busy ? "Salvando…" : "Salvar detalhes"}
          </button>
        </div>
      </form>
    </>
  );
}

// --- Gerenciador da chave Pix ---
function PixManager() {
  const [pix, setPix] = useSt(null);
  const [chave, setChave] = useSt("");
  const [titular, setTitular] = useSt("");
  const [banco, setBanco] = useSt("");
  const [erro, setErro] = useSt("");
  const [ok, setOk] = useSt(false);
  const [busy, setBusy] = useSt(false);
  const carregado = useRf(false);

  useEf(function () {
    return Store.subscribePix(function (p) {
      setPix(p);
      // Preenche os campos só na primeira carga, para não atropelar a digitação.
      if (!carregado.current) {
        setChave((p && p.chave) || "");
        setTitular((p && p.titular) || "");
        setBanco((p && p.banco) || "");
        carregado.current = true;
      }
    });
  }, []);

  function submit(e) {
    e.preventDefault();
    if (!chave.trim()) return setErro("Informe a chave Pix.");
    setBusy(true);
    setErro("");
    setOk(false);
    Store.savePix({
      chave: chave.trim(),
      titular: titular.trim(),
      banco: banco.trim(),
    })
      .then(function () {
        setOk(true);
        setBusy(false);
        setTimeout(function () {
          setOk(false);
        }, 3000);
      })
      .catch(function () {
        setErro("Não foi possível salvar. Verifique a conexão e tente novamente.");
        setBusy(false);
      });
  }

  return (
    <>
      <div className="adm-stats">
        <div className="adm-stat accent">
          <div className="adm-stat-icon"><Icons.Card size={18} /></div>
          <div>
            <div className="adm-stat-num adm-stat-num-sm">
              {pix && pix.chave ? pix.chave : "—"}
            </div>
            <div className="adm-stat-label">Chave Pix exibida no site</div>
          </div>
        </div>
      </div>

      <div className="adm-toolbar">
        <h2 className="adm-section-title">Dados do Pix</h2>
      </div>

      <form className="admin-card" onSubmit={submit}>
        <h2>Editar chave Pix</h2>
        <label className="admin-field">
          <span>Chave Pix</span>
          <input
            value={chave}
            onChange={(e) => setChave(e.target.value)}
            placeholder="e-mail, CPF, telefone ou chave aleatória"
            maxLength={120}
          />
        </label>
        <label className="admin-field">
          <span>Titular da conta</span>
          <input
            value={titular}
            onChange={(e) => setTitular(e.target.value)}
            placeholder="Ex.: Giovanna R. Pimenta"
            maxLength={80}
          />
        </label>
        <label className="admin-field">
          <span>Banco</span>
          <input
            value={banco}
            onChange={(e) => setBanco(e.target.value)}
            placeholder="Ex.: Nubank"
            maxLength={60}
          />
        </label>

        {erro && <div className="admin-error">{erro}</div>}
        {ok && (
          <div className="adm-success">
            <Icons.Check size={16} /> Chave Pix atualizada! Já aparece para os convidados.
          </div>
        )}

        <div className="gift-form-actions">
          <button className="adm-btn-primary" type="submit" disabled={busy}>
            {busy ? "Salvando…" : "Salvar alterações"}
          </button>
        </div>
      </form>
    </>
  );
}

// --- Gerenciador de doações (presentes recebidos pelo Pix) ---
function DoacoesManager() {
  const [lista, setLista] = useSt(null);
  const [busy, setBusy] = useSt("");

  useEf(function () {
    return Store.subscribeDoacoes(setLista);
  }, []);

  function excluir(id) {
    if (!window.confirm("Remover este registro? Isso não cancela o Pix, só apaga a anotação."))
      return;
    setBusy(id);
    Store.deleteDoacao(id)
      .then(function () { setBusy(""); })
      .catch(function () { setBusy(""); });
  }

  if (lista == null) return <div className="admin-muted">Carregando…</div>;

  const total = lista.reduce(function (s, d) {
    return s + (Number(d.valor) || 0);
  }, 0);

  return (
    <>
      <div className="adm-stats">
        <div className="adm-stat accent">
          <div className="adm-stat-icon"><Icons.Heart size={18} /></div>
          <div>
            <div className="adm-stat-num">{lista.length}</div>
            <div className="adm-stat-label">Presentes registrados</div>
          </div>
        </div>
        <div className="adm-stat">
          <div className="adm-stat-icon"><Icons.Card size={18} /></div>
          <div>
            <div className="adm-stat-num adm-stat-num-sm">{fmtBRL(total)}</div>
            <div className="adm-stat-label">Total informado pelos convidados</div>
          </div>
        </div>
      </div>

      <div className="adm-toolbar">
        <h2 className="adm-section-title">Quem já presenteou</h2>
      </div>

      {lista.length === 0 ? (
        <div className="admin-card">
          <p className="adm-hint" style={{ margin: 0 }}>
            Ainda não há presentes registrados. Quando um convidado pagar pelo
            cartão ou clicar em “Já fiz o Pix”, o registro aparece aqui automaticamente.
          </p>
        </div>
      ) : (
        <div className="adm-doacoes">
          {lista.map(function (d) {
            return (
              <div className="adm-doacao" key={d.id}>
                <div className="adm-doacao-main">
                  <div className="adm-doacao-top">
                    <span className="adm-doacao-nome">{d.doador || "Anônimo"}</span>
                    <span className="adm-doacao-valor">{fmtBRL(d.valor)}</span>
                  </div>
                  <div className="adm-doacao-presente">
                    <Icons.Gift size={13} /> {d.presenteNome || "—"}
                    {d.metodo === "cartao" ? (
                      <span className="adm-doacao-tag cartao">
                        <Icons.Card size={11} /> Cartão
                        {Number(d.parcelas) > 1 ? " " + d.parcelas + "x" : ""}
                      </span>
                    ) : d.metodo === "pix-manual" ? (
                      <span className="adm-doacao-tag pix">Pix (marcado manualmente)</span>
                    ) : (
                      <span className="adm-doacao-tag pix">Pix</span>
                    )}
                  </div>
                  {d.mensagem ? (
                    <div className="adm-doacao-msg">“{d.mensagem}”</div>
                  ) : null}
                  {fmtData(d.createdAt) ? (
                    <div className="adm-doacao-data">{fmtData(d.createdAt)}</div>
                  ) : null}
                </div>
                <button
                  className="btn btn-danger"
                  onClick={() => excluir(d.id)}
                  disabled={busy === d.id}
                >
                  {busy === d.id ? "…" : "Excluir"}
                </button>
              </div>
            );
          })}
        </div>
      )}
    </>
  );
}

// --- Painel principal (layout de gestão: sidebar + conteúdo) ---
function AdminPanel({ user }) {
  const [aba, setAba] = useSt("presentes");
  const [menuAberto, setMenuAberto] = useSt(false);

  const paginas = {
    presentes: { titulo: "Presentes", sub: "Gerencie a lista de presentes do casal" },
    convidados: { titulo: "Convidados", sub: "Grupos, mesas e confirmações de presença" },
    detalhes: { titulo: "Detalhes do Evento", sub: "Data, local, mapa, dress code e textos da 'Nosso Dia Especial'" },
    pix: { titulo: "Pix / Pagamento", sub: "Altere a chave Pix exibida no site" },
    doacoes: { titulo: "Presentes recebidos", sub: "Quem já presenteou os noivos pelo Pix" },
  };
  const pag = paginas[aba];

  // Trava o scroll do fundo enquanto o menu lateral (mobile) está aberto.
  useEf(function () {
    document.body.style.overflow = menuAberto ? "hidden" : "";
    return function () {
      document.body.style.overflow = "";
    };
  }, [menuAberto]);

  function irPara(id) {
    setAba(id);
    setMenuAberto(false);
  }

  function sair() {
    Store.logout();
  }

  return (
    <div className="adm">
      <div
        className={"adm-drawer-overlay" + (menuAberto ? " show" : "")}
        onClick={() => setMenuAberto(false)}
      />

      <aside className={"adm-sidebar" + (menuAberto ? " open" : "")}>
        <div className="adm-brand">
          <span className="adm-brand-mark">G&amp;M</span>
          <span className="adm-brand-text">
            <span className="adm-brand-title">Painel dos Noivos</span>
            <span className="adm-brand-sub">Gestão do casamento</span>
          </span>
          <button
            className="adm-drawer-close"
            onClick={() => setMenuAberto(false)}
            aria-label="Fechar menu"
          >
            <Icons.Close size={20} />
          </button>
        </div>

        <nav className="adm-nav">
          <div className="adm-nav-group">Menu</div>
          <button
            className={"adm-nav-item" + (aba === "presentes" ? " active" : "")}
            onClick={() => irPara("presentes")}
          >
            <Icons.Gift size={18} /> Presentes
          </button>
          <button
            className={"adm-nav-item" + (aba === "convidados" ? " active" : "")}
            onClick={() => irPara("convidados")}
          >
            <Icons.Mail size={18} /> Convidados
          </button>
          <button
            className={"adm-nav-item" + (aba === "detalhes" ? " active" : "")}
            onClick={() => irPara("detalhes")}
          >
            <Icons.Calendar size={18} /> Detalhes
          </button>
          <button
            className={"adm-nav-item" + (aba === "pix" ? " active" : "")}
            onClick={() => irPara("pix")}
          >
            <Icons.Card size={18} /> Pix
          </button>
          <button
            className={"adm-nav-item" + (aba === "doacoes" ? " active" : "")}
            onClick={() => irPara("doacoes")}
          >
            <Icons.Heart size={18} /> Presentes recebidos
          </button>

          <div className="adm-nav-group">Geral</div>
          <a
            className="adm-nav-item"
            href={SITE_URL}
            target="_blank"
            rel="noopener"
          >
            <Icons.Home size={18} /> Ver site
          </a>
        </nav>

        <div className="adm-sidebar-foot">
          <div className="adm-user">
            <div className="adm-user-avatar">
              {(user.email || "?").charAt(0).toUpperCase()}
            </div>
            <div className="adm-user-meta">
              <span className="adm-user-name">{user.email}</span>
              <span className="adm-user-role">Administrador</span>
            </div>
          </div>
          <button className="adm-logout" onClick={sair}>
            <Icons.Logout size={16} /> Sair
          </button>
        </div>
      </aside>

      <main className="adm-main">
        <header className="adm-topbar">
          <button
            className="adm-hamburger"
            onClick={() => setMenuAberto(true)}
            aria-label="Abrir menu"
          >
            <Icons.Menu size={22} />
          </button>
          <span className="adm-topbar-title">{pag.titulo}</span>
          <div className="adm-topbar-right">
            <span className="adm-topbar-user">{user.email}</span>
            <button className="adm-logout adm-logout-top" onClick={sair}>
              <Icons.Logout size={16} /> Sair
            </button>
          </div>
        </header>

        <div className="adm-content">
          <div className="adm-page-head">
            <h1 className="adm-page-title">{pag.titulo}</h1>
            <p className="adm-page-sub">{pag.sub}</p>
          </div>

          {aba === "presentes" ? (
            <GiftsManager />
          ) : aba === "convidados" ? (
            <GuestsManager />
          ) : aba === "detalhes" ? (
            <DetalhesManager />
          ) : aba === "doacoes" ? (
            <DoacoesManager />
          ) : (
            <PixManager />
          )}
        </div>
      </main>
    </div>
  );
}

// --- Raiz do admin: decide tela conforme configuração/login ---
function Admin() {
  const [user, setUser] = useSt(undefined); // undefined = ainda carregando

  useEf(function () {
    return Store.onAuth(setUser);
  }, []);

  if (!Store.isConfigured()) return <AdminSetup />;
  if (user === undefined)
    return (
      <div className="adm-auth">
        <div className="adm-loading">Carregando…</div>
      </div>
    );
  if (!user) return <AdminLogin />;
  return <AdminPanel user={user} />;
}

Object.assign(window, { Admin });
