import { useState, useEffect } from "react";
import { trpc } from "../lib/trpc";
import { useAuth } from "../_core/hooks/useAuth";
import { PainelRepetidor } from "../components/admin/PainelRepetidor";

const CAPA_PLACEHOLDER = "/media/images/capas/capa-placeholder.svg";

const campoEstilo = { background: "rgba(255,255,255,0.06)", border: "var(--border-medium)", color: "var(--clr-branco)" };

interface LivroExistente {
  id: number;
  titulo: string;
  subtitulo: string | null;
  serie: string | null;
  volumeNumero: number | null;
  autor: string;
  resumo: string | null;
  capaUrl: string | null;
  epubUrl: string | null;
  docxOriginalUrl: string | null;
  status: "rascunho" | "publicado";
  destaque: boolean;
  formato: string;
}

const FORMATOS = [
  { valor: "texto", rotulo: "Texto (DOCX → EPUB)" },
  { valor: "ilustrado", rotulo: "Livro ilustrado (páginas de imagem)" },
  { valor: "manga", rotulo: "Mangá (páginas de imagem)" },
  { valor: "hq", rotulo: "HQ / Graphic novel (páginas de imagem)" },
  { valor: "revista", rotulo: "Revista (páginas de imagem)" },
  { valor: "apostila", rotulo: "Apostila (DOCX → EPUB)" },
];
const FORMATOS_IMAGEM = ["ilustrado", "manga", "hq", "revista"];

const PUBLICOS = [
  { valor: "", rotulo: "toda a família" },
  { valor: "primeiros_leitores", rotulo: "primeiros leitores (0–5)" },
  { valor: "infantil", rotulo: "infantil (6–9)" },
  { valor: "pre_adolescente", rotulo: "pré-adolescente (10–12)" },
  { valor: "adolescente", rotulo: "adolescente (13–17)" },
  { valor: "jovem", rotulo: "jovem (18–29)" },
  { valor: "adulto", rotulo: "adulto (30+)" },
];

function FormularioPublicacao({ livroExistente, aoTerminar }: { livroExistente: LivroExistente | null; aoTerminar: () => void }) {
  const utils = trpc.useUtils();
  const criar = trpc.biblioteca.admin.criar.useMutation({ onSuccess: () => utils.biblioteca.admin.listar.invalidate() });
  const atualizar = trpc.biblioteca.admin.atualizar.useMutation({ onSuccess: () => utils.biblioteca.admin.listar.invalidate() });
  const salvarPaginas = trpc.paginas.salvar.useMutation();

  // Quando está editando, busca o livro completo (com autores/temas já
  // ligados) pra pré-preencher — a listagem do admin não traz isso.
  const { data: livroCompleto } = trpc.biblioteca.getLivro.useQuery(
    { id: livroExistente?.id ?? 0 },
    { enabled: !!livroExistente },
  );

  const { data: todosAutores } = trpc.autores.listar.useQuery();
  const { data: todosTemas } = trpc.temas.listar.useQuery();
  const { data: todasColecoes } = trpc.colecoes.listar.useQuery();
  const criarAutor = trpc.autores.criar.useMutation({ onSuccess: () => utils.autores.listar.invalidate() });
  const criarTema = trpc.temas.criar.useMutation({ onSuccess: () => utils.temas.listar.invalidate() });

  const [titulo, setTitulo] = useState(livroExistente?.titulo ?? "");
  const [destaqueMarcado, setDestaqueMarcado] = useState(livroExistente?.destaque ?? false);
  const [linkCompraImpresso, setLinkCompraImpresso] = useState("");
  const [subtitulo, setSubtitulo] = useState(livroExistente?.subtitulo ?? "");
  const [serie, setSerie] = useState(livroExistente?.serie ?? "");
  const [volumeNumero, setVolumeNumero] = useState(livroExistente?.volumeNumero?.toString() ?? "");
  const [autor, setAutor] = useState(livroExistente?.autor ?? "");
  const [resumo, setResumo] = useState(livroExistente?.resumo ?? "");
  const [formato, setFormato] = useState(livroExistente?.formato ?? "texto");
  const [publicoAlvo, setPublicoAlvo] = useState("");
  const [colecaoId, setColecaoId] = useState("");
  const [autorIds, setAutorIds] = useState<number[]>([]);
  const [temaIds, setTemaIds] = useState<number[]>([]);
  const [novoAutorNome, setNovoAutorNome] = useState("");
  const [novoTemaNome, setNovoTemaNome] = useState("");
  const [arquivoDocx, setArquivoDocx] = useState<File | null>(null);
  const [arquivoCapa, setArquivoCapa] = useState<File | null>(null);
  const [arquivosPaginas, setArquivosPaginas] = useState<FileList | null>(null);
  const [enviando, setEnviando] = useState(false);
  const [progresso, setProgresso] = useState<string | null>(null);
  const [erro, setErro] = useState<string | null>(null);

  // Pré-preenche público/coleção/autores/temas assim que o livro completo chega.
  useEffect(() => {
    if (!livroCompleto) return;
    setPublicoAlvo(livroCompleto.publicoAlvo ?? "");
    setColecaoId(livroCompleto.colecaoId?.toString() ?? "");
    setAutorIds(livroCompleto.autores?.map((a) => a.id) ?? []);
    setTemaIds(livroCompleto.temas?.map((t) => t.id) ?? []);
    setLinkCompraImpresso(livroCompleto.linkCompraImpresso ?? "");
  }, [livroCompleto]);

  const editando = !!livroExistente;
  const formatoEhImagem = FORMATOS_IMAGEM.includes(formato);

  async function enviarArquivo(url: string, campo: string, arquivo: File, extras: Record<string, string> = {}) {
    const form = new FormData();
    form.append(campo, arquivo);
    for (const [chave, valor] of Object.entries(extras)) form.append(chave, valor);
    const resposta = await fetch(url, { method: "POST", body: form });
    if (!resposta.ok) {
      const corpo = await resposta.json().catch(() => ({}));
      throw new Error(corpo.erro || "Falha no upload.");
    }
    return resposta.json();
  }

  async function enviarPaginas(arquivos: FileList) {
    const form = new FormData();
    for (const arquivo of Array.from(arquivos)) form.append("paginas", arquivo);
    const resposta = await fetch("/api/admin/upload-paginas", { method: "POST", body: form });
    if (!resposta.ok) {
      const corpo = await resposta.json().catch(() => ({}));
      throw new Error(corpo.erro || "Falha no upload das páginas.");
    }
    return (await resposta.json()).urls as string[];
  }

  function limpar() {
    setTitulo("");
    setSubtitulo("");
    setSerie("");
    setVolumeNumero("");
    setAutor("");
    setResumo("");
    setFormato("texto");
    setPublicoAlvo("");
    setColecaoId("");
    setAutorIds([]);
    setTemaIds([]);
    setArquivoDocx(null);
    setArquivoCapa(null);
    setArquivosPaginas(null);
  }

  async function salvar() {
    if (!editando && formato === "texto" && !arquivoDocx) {
      setErro("Selecione o arquivo DOCX.");
      return;
    }
    if (!editando && formatoEhImagem && !arquivosPaginas) {
      setErro("Selecione as páginas (imagens).");
      return;
    }
    setErro(null);
    setEnviando(true);
    try {
      let docxOriginalUrl: string | undefined;
      let epubUrl: string | undefined;
      let capaUrl: string | undefined;

      if (arquivoDocx) {
        setProgresso("convertendo DOCX...");
        const resultado = await enviarArquivo("/api/admin/upload-docx", "arquivo", arquivoDocx, { titulo, autor });
        docxOriginalUrl = resultado.docxOriginalUrl;
        epubUrl = resultado.epubUrl;
        if (!resumo && resultado.resumoAutomatico) {
          setResumo(resultado.resumoAutomatico);
        }
      }
      if (arquivoCapa) {
        setProgresso("enviando capa...");
        const resultadoCapa = await enviarArquivo("/api/admin/upload-capa", "imagem", arquivoCapa);
        capaUrl = resultadoCapa.url;
      }

      const dadosComuns = {
        titulo,
        subtitulo: subtitulo || undefined,
        serie: serie || undefined,
        volumeNumero: volumeNumero ? Number(volumeNumero) : undefined,
        autor,
        resumo: resumo || undefined,
        destaque: destaqueMarcado,
        linkCompraImpresso: linkCompraImpresso || undefined,
        formato: formato as "texto" | "ilustrado" | "manga" | "hq" | "revista" | "apostila" | "audiolivro",
        publicoAlvo: publicoAlvo ? (publicoAlvo as "primeiros_leitores" | "infantil" | "pre_adolescente" | "adolescente" | "jovem" | "adulto") : undefined,
        colecaoId: colecaoId ? Number(colecaoId) : undefined,
        autorIds,
        temaIds,
        ...(capaUrl && { capaUrl }),
        ...(epubUrl && { epubUrl }),
        ...(docxOriginalUrl && { docxOriginalUrl }),
      };

      let livroId: number;
      if (editando) {
        await atualizar.mutateAsync({ id: livroExistente.id, ...dadosComuns });
        livroId = livroExistente.id;
      } else {
        const resultado = await criar.mutateAsync(dadosComuns);
        livroId = resultado.id;
      }

      if (formatoEhImagem && arquivosPaginas) {
        setProgresso(`enviando ${arquivosPaginas.length} páginas...`);
        const urls = await enviarPaginas(arquivosPaginas);
        await salvarPaginas.mutateAsync({ livroId, imagensUrl: urls });
      }

      if (!editando) limpar();
      aoTerminar();
    } catch (err) {
      setErro(err instanceof Error ? err.message : "Erro ao salvar.");
    } finally {
      setEnviando(false);
      setProgresso(null);
    }
  }

  function alternarSelecao(lista: number[], id: number, definir: (v: number[]) => void) {
    definir(lista.includes(id) ? lista.filter((x) => x !== id) : [...lista, id]);
  }

  return (
    <div className="space-y-3 rounded-lg p-4" style={{ background: "var(--color-bg-card-dark)", border: "var(--border-thin)" }}>
      <div className="flex items-center justify-between">
        <h2 className="font-medium" style={{ fontFamily: "var(--font-display)" }}>
          {editando ? `Editando: ${livroExistente!.titulo}` : "Novo livro"}
        </h2>
        {editando && (
          <button className="text-xs" style={{ color: "var(--color-text-on-dark-muted)" }} onClick={aoTerminar}>
            cancelar edição
          </button>
        )}
      </div>

      <input className="w-full rounded px-3 py-2" style={campoEstilo} placeholder="título" value={titulo} onChange={(e) => setTitulo(e.target.value)} />
      <input className="w-full rounded px-3 py-2" style={campoEstilo} placeholder="subtítulo (opcional)" value={subtitulo} onChange={(e) => setSubtitulo(e.target.value)} />
      <div className="flex gap-3">
        <input className="flex-1 rounded px-3 py-2" style={campoEstilo} placeholder="série (opcional)" value={serie} onChange={(e) => setSerie(e.target.value)} />
        <input className="w-28 rounded px-3 py-2" style={campoEstilo} placeholder="volume nº" value={volumeNumero} onChange={(e) => setVolumeNumero(e.target.value)} />
      </div>
      <input className="w-full rounded px-3 py-2" style={campoEstilo} placeholder="autor (texto de exibição)" value={autor} onChange={(e) => setAutor(e.target.value)} />
      <textarea className="w-full rounded px-3 py-2" style={campoEstilo} placeholder="resumo (opcional)" value={resumo} onChange={(e) => setResumo(e.target.value)} />

      <div className="grid grid-cols-2 gap-3">
        <label className="text-sm" style={{ color: "var(--color-text-on-dark-muted)" }}>
          formato
          <select className="w-full rounded px-3 py-2 mt-1" style={campoEstilo} value={formato} onChange={(e) => setFormato(e.target.value)}>
            {FORMATOS.map((f) => (
              <option key={f.valor} value={f.valor} style={{ color: "#000" }}>{f.rotulo}</option>
            ))}
          </select>
        </label>
        <label className="text-sm" style={{ color: "var(--color-text-on-dark-muted)" }}>
          público-alvo
          <select className="w-full rounded px-3 py-2 mt-1" style={campoEstilo} value={publicoAlvo} onChange={(e) => setPublicoAlvo(e.target.value)}>
            {PUBLICOS.map((p) => (
              <option key={p.valor} value={p.valor} style={{ color: "#000" }}>{p.rotulo}</option>
            ))}
          </select>
        </label>
      </div>

      <label className="block text-sm" style={{ color: "var(--color-text-on-dark-muted)" }}>
        coleção (opcional)
        <select className="w-full rounded px-3 py-2 mt-1" style={campoEstilo} value={colecaoId} onChange={(e) => setColecaoId(e.target.value)}>
          <option value="" style={{ color: "#000" }}>nenhuma</option>
          {todasColecoes?.map((c) => (
            <option key={c.id} value={c.id} style={{ color: "#000" }}>{c.nome}</option>
          ))}
        </select>
      </label>

      <div>
        <p className="text-sm mb-1" style={{ color: "var(--color-text-on-dark-muted)" }}>colaboradores (autor/ilustrador)</p>
        <div className="flex flex-wrap gap-2 mb-2">
          {todosAutores?.map((a) => (
            <button
              key={a.id}
              type="button"
              onClick={() => alternarSelecao(autorIds, a.id, setAutorIds)}
              className="text-xs px-3 py-1 rounded-full transition-colors"
              style={{
                border: "var(--border-medium)",
                background: autorIds.includes(a.id) ? "var(--clr-acento-alpha12)" : "transparent",
                color: autorIds.includes(a.id) ? "var(--clr-acento-400)" : "var(--color-text-on-dark-muted)",
              }}
            >
              {a.nome}
            </button>
          ))}
        </div>
        <div className="flex gap-2">
          <input
            className="flex-1 rounded px-3 py-1.5 text-sm" style={campoEstilo}
            placeholder="novo colaborador..." value={novoAutorNome} onChange={(e) => setNovoAutorNome(e.target.value)}
          />
          <button
            className="btn btn-ghost text-xs flex-shrink-0" style={{ padding: "0.4rem 0.8rem" }}
            onClick={async () => {
              if (!novoAutorNome) return;
              const r = await criarAutor.mutateAsync({ nome: novoAutorNome });
              setAutorIds((v) => [...v, r.id]);
              setNovoAutorNome("");
            }}
          >
            + adicionar
          </button>
        </div>
      </div>

      <div>
        <p className="text-sm mb-1" style={{ color: "var(--color-text-on-dark-muted)" }}>temas</p>
        <div className="flex flex-wrap gap-2 mb-2">
          {todosTemas?.map((t) => (
            <button
              key={t.id}
              type="button"
              onClick={() => alternarSelecao(temaIds, t.id, setTemaIds)}
              className="text-xs px-3 py-1 rounded-full transition-colors"
              style={{
                border: "var(--border-medium)",
                background: temaIds.includes(t.id) ? "var(--clr-acento-alpha12)" : "transparent",
                color: temaIds.includes(t.id) ? "var(--clr-acento-400)" : "var(--color-text-on-dark-muted)",
              }}
            >
              {t.nome}
            </button>
          ))}
        </div>
        <div className="flex gap-2">
          <input
            className="flex-1 rounded px-3 py-1.5 text-sm" style={campoEstilo}
            placeholder="novo tema..." value={novoTemaNome} onChange={(e) => setNovoTemaNome(e.target.value)}
          />
          <button
            className="btn btn-ghost text-xs flex-shrink-0" style={{ padding: "0.4rem 0.8rem" }}
            onClick={async () => {
              if (!novoTemaNome) return;
              const r = await criarTema.mutateAsync({ nome: novoTemaNome });
              setTemaIds((v) => [...v, r.id]);
              setNovoTemaNome("");
            }}
          >
            + adicionar
          </button>
        </div>
      </div>

      <label className="flex items-center gap-2 text-sm" style={{ color: "var(--color-text-on-dark-muted)" }}>
        <input type="checkbox" checked={destaqueMarcado} onChange={(e) => setDestaqueMarcado(e.target.checked)} />
        exibir no carrossel de destaque da Home
      </label>

      <label className="block text-sm" style={{ color: "var(--color-text-on-dark-muted)" }}>
        link pra comprar o livro impresso (opcional — loja externa)
        <input
          className="w-full rounded px-3 py-2 mt-1"
          style={campoEstilo}
          placeholder="https://..."
          value={linkCompraImpresso}
          onChange={(e) => setLinkCompraImpresso(e.target.value)}
        />
      </label>

      {formato === "texto" || formato === "apostila" ? (
        <>
          <label className="block text-sm" style={{ color: "var(--color-text-on-dark-muted)" }}>
            arquivo DOCX {editando && "(deixe em branco pra manter o atual)"}
          </label>
          <input type="file" accept=".docx" onChange={(e) => setArquivoDocx(e.target.files?.[0] ?? null)} />
        </>
      ) : (
        <>
          <label className="block text-sm" style={{ color: "var(--color-text-on-dark-muted)" }}>
            páginas (imagens, na ordem — selecione todas de uma vez) {editando && "(deixe em branco pra manter as atuais)"}
          </label>
          <input type="file" accept="image/*" multiple onChange={(e) => setArquivosPaginas(e.target.files)} />
        </>
      )}

      <label className="block text-sm" style={{ color: "var(--color-text-on-dark-muted)" }}>
        capa {editando && "(deixe em branco pra manter a atual)"}
      </label>
      <input type="file" accept="image/*" onChange={(e) => setArquivoCapa(e.target.files?.[0] ?? null)} />

      {progresso && <p className="text-sm" style={{ color: "var(--clr-acento-400)" }}>{progresso}</p>}
      {erro && <p className="text-sm" style={{ color: "#ff8080" }}>{erro}</p>}

      <button className="btn btn-primary" onClick={salvar} disabled={enviando || !titulo || !autor}>
        {enviando ? "processando..." : editando ? "salvar alterações" : "salvar como rascunho"}
      </button>
    </div>
  );
}

function ListaLivros({ aoEditar }: { aoEditar: (livro: LivroExistente) => void }) {
  const utils = trpc.useUtils();
  const { data: livros } = trpc.biblioteca.admin.listar.useQuery();
  const [filtro, setFiltro] = useState("");
  const atualizar = trpc.biblioteca.admin.atualizar.useMutation({ onSuccess: () => utils.biblioteca.admin.listar.invalidate() });
  const excluir = trpc.biblioteca.admin.excluir.useMutation({ onSuccess: () => utils.biblioteca.admin.listar.invalidate() });

  const filtrados = livros?.filter((l) => l.titulo.toLowerCase().includes(filtro.toLowerCase()) || l.autor.toLowerCase().includes(filtro.toLowerCase()));

  function confirmarExclusao(id: number, titulo: string) {
    if (window.confirm(`Excluir "${titulo}" permanentemente? Essa ação não pode ser desfeita.`)) {
      excluir.mutate({ id });
    }
  }

  return (
    <div className="mt-8 space-y-3">
      <div className="flex items-center justify-between gap-3">
        <h2 className="font-medium" style={{ fontFamily: "var(--font-display)" }}>
          Livros {livros ? `(${livros.length})` : ""}
        </h2>
        <input
          value={filtro}
          onChange={(e) => setFiltro(e.target.value)}
          placeholder="filtrar por título ou autor..."
          className="rounded px-3 py-1.5 text-sm"
          style={{ ...campoEstilo, maxWidth: 240 }}
        />
      </div>

      <div className="space-y-2">
        {filtrados?.map((livro) => (
          <div key={livro.id} className="flex items-center gap-3 rounded-md p-2" style={{ border: "var(--border-thin)" }}>
            <img
              src={livro.capaUrl || CAPA_PLACEHOLDER}
              alt=""
              className="w-10 aspect-[2/3] object-cover rounded flex-shrink-0"
            />
            <div className="flex-1 min-w-0">
              <p className="text-sm truncate">{livro.titulo}</p>
              <p className="text-xs flex items-center gap-2" style={{ color: "var(--color-text-on-dark-muted)" }}>
                <span
                  className="px-1.5 py-0.5 rounded"
                  style={{
                    background: livro.status === "publicado" ? "var(--clr-acento-alpha12)" : "rgba(255,255,255,0.06)",
                    color: livro.status === "publicado" ? "var(--clr-acento-400)" : "var(--color-text-on-dark-subtle)",
                  }}
                >
                  {livro.status}
                </span>
                {livro.epubUrl ? "epub ok" : "sem epub"}
                {livro.serie ? ` · ${livro.serie}` : ""}
              </p>
            </div>
            <div className="flex gap-1 flex-shrink-0">
              <button className="btn btn-ghost text-xs" style={{ padding: "0.35rem 0.7rem" }} onClick={() => aoEditar(livro)}>
                editar
              </button>
              <button
                className="btn btn-ghost text-xs"
                style={{ padding: "0.35rem 0.7rem" }}
                onClick={() => atualizar.mutate({ id: livro.id, status: livro.status === "publicado" ? "rascunho" : "publicado" })}
              >
                {livro.status === "publicado" ? "despublicar" : "publicar"}
              </button>
              <button
                className="btn btn-ghost text-xs"
                style={{ padding: "0.35rem 0.7rem", color: "#ff8080" }}
                onClick={() => confirmarExclusao(livro.id, livro.titulo)}
              >
                excluir
              </button>
            </div>
          </div>
        ))}
        {filtrados?.length === 0 && (
          <p className="text-sm" style={{ color: "var(--color-text-on-dark-subtle)" }}>nenhum livro encontrado.</p>
        )}
      </div>
    </div>
  );
}

function PainelConfiguracao() {
  const { data: config } = trpc.config.obter.useQuery();
  const utils = trpc.useUtils();
  const atualizar = trpc.config.atualizar.useMutation({ onSuccess: () => utils.config.obter.invalidate() });

  if (!config) return null;

  return (
    <div className="mt-8 space-y-3 rounded-lg p-4" style={{ background: "var(--color-bg-card-dark)", border: "var(--border-thin)" }}>
      <h2 className="font-medium" style={{ fontFamily: "var(--font-display)" }}>Configurações de exibição</h2>
      <p className="text-xs" style={{ color: "var(--color-text-on-dark-muted)" }}>
        Controla como os livros aparecem na Home. O celular sempre se ajusta sozinho — só desktop e tablet usam esse número fixo.
      </p>
      <div className="flex gap-4 items-center">
        <label className="text-sm flex-1" style={{ color: "var(--color-text-on-dark-muted)" }}>
          colunas no desktop
          <input
            type="number" min={1} max={6} defaultValue={config.colunasDesktop}
            className="w-full rounded px-3 py-2 mt-1" style={campoEstilo}
            onBlur={(e) => atualizar.mutate({ colunasDesktop: Number(e.target.value) })}
          />
        </label>
        <label className="text-sm flex-1" style={{ color: "var(--color-text-on-dark-muted)" }}>
          colunas no tablet
          <input
            type="number" min={1} max={6} defaultValue={config.colunasTablet}
            className="w-full rounded px-3 py-2 mt-1" style={campoEstilo}
            onBlur={(e) => atualizar.mutate({ colunasTablet: Number(e.target.value) })}
          />
        </label>
      </div>
      <label className="text-sm block" style={{ color: "var(--color-text-on-dark-muted)" }}>
        modo padrão pra quem visita pela primeira vez
        <select
          defaultValue={config.modoPadrao}
          className="w-full rounded px-3 py-2 mt-1" style={campoEstilo}
          onChange={(e) => atualizar.mutate({ modoPadrao: e.target.value as "grade" | "lista" })}
        >
          <option value="grade" style={{ color: "#000" }}>grade</option>
          <option value="lista" style={{ color: "#000" }}>lista</option>
        </select>
      </label>
      <label className="text-sm block" style={{ color: "var(--color-text-on-dark-muted)" }}>
        quantidade de slides no carrossel de destaque
        <input
          type="number" min={1} max={10} defaultValue={config.qtdSlidesHero}
          className="w-full rounded px-3 py-2 mt-1" style={campoEstilo}
          onBlur={(e) => atualizar.mutate({ qtdSlidesHero: Number(e.target.value) })}
        />
        <span className="block text-xs mt-1" style={{ color: "var(--color-text-on-dark-subtle)" }}>
          se faltar livro marcado como "destaque", completa com os mais recentes.
        </span>
      </label>
    </div>
  );
}

function PainelMenu() {
  const { data: itens } = trpc.menu.listar.useQuery();
  const utils = trpc.useUtils();
  const criar = trpc.menu.criar.useMutation({ onSuccess: () => utils.menu.listar.invalidate() });
  const atualizar = trpc.menu.atualizar.useMutation({ onSuccess: () => utils.menu.listar.invalidate() });
  const excluir = trpc.menu.excluir.useMutation({ onSuccess: () => utils.menu.listar.invalidate() });

  const [rotulo, setRotulo] = useState("");
  const [url, setUrl] = useState("");

  function adicionar() {
    if (!rotulo || !url) return;
    criar.mutate({ rotulo, url, ordem: (itens?.length ?? 0) + 1 });
    setRotulo("");
    setUrl("");
  }

  return (
    <div className="mt-8 space-y-3 rounded-lg p-4" style={{ background: "var(--color-bg-card-dark)", border: "var(--border-thin)" }}>
      <h2 className="font-medium" style={{ fontFamily: "var(--font-display)" }}>Menu de navegação</h2>
      <p className="text-xs" style={{ color: "var(--color-text-on-dark-muted)" }}>
        Aparece no topo e no rodapé do site. Deixe vazio pra não mostrar menu nenhum.
      </p>

      <div className="space-y-2">
        {itens?.map((item) => (
          <div key={item.id} className="flex items-center gap-2">
            <input
              defaultValue={item.rotulo}
              className="flex-1 rounded px-3 py-1.5 text-sm" style={campoEstilo}
              onBlur={(e) => atualizar.mutate({ id: item.id, rotulo: e.target.value })}
            />
            <input
              defaultValue={item.url}
              className="flex-1 rounded px-3 py-1.5 text-sm" style={campoEstilo}
              onBlur={(e) => atualizar.mutate({ id: item.id, url: e.target.value })}
            />
            <button
              className="text-xs flex-shrink-0"
              style={{ color: "#ff8080" }}
              onClick={() => excluir.mutate({ id: item.id })}
            >
              remover
            </button>
          </div>
        ))}
        {itens?.length === 0 && (
          <p className="text-xs" style={{ color: "var(--color-text-on-dark-subtle)" }}>nenhum item ainda.</p>
        )}
      </div>

      <div className="flex items-center gap-2 pt-2" style={{ borderTop: "var(--border-thin)" }}>
        <input
          placeholder="rótulo (ex: Sobre)"
          value={rotulo}
          onChange={(e) => setRotulo(e.target.value)}
          className="flex-1 rounded px-3 py-1.5 text-sm" style={campoEstilo}
        />
        <input
          placeholder="url (ex: /serie/Quatro Cavalos)"
          value={url}
          onChange={(e) => setUrl(e.target.value)}
          className="flex-1 rounded px-3 py-1.5 text-sm" style={campoEstilo}
        />
        <button className="btn btn-ghost text-xs flex-shrink-0" style={{ padding: "0.4rem 0.8rem" }} onClick={adicionar}>
          + adicionar
        </button>
      </div>
    </div>
  );
}

function PainelColecoes() {
  const { data: colecoes } = trpc.colecoes.listar.useQuery();
  const utils = trpc.useUtils();
  const criar = trpc.colecoes.criar.useMutation({ onSuccess: () => utils.colecoes.listar.invalidate() });
  const atualizar = trpc.colecoes.atualizar.useMutation({ onSuccess: () => utils.colecoes.listar.invalidate() });
  const excluir = trpc.colecoes.excluir.useMutation({ onSuccess: () => utils.colecoes.listar.invalidate() });

  const [nome, setNome] = useState("");
  const [descricao, setDescricao] = useState("");

  return (
    <div className="mt-8 space-y-3 rounded-lg p-4" style={{ background: "var(--color-bg-card-dark)", border: "var(--border-thin)" }}>
      <h2 className="font-medium" style={{ fontFamily: "var(--font-display)" }}>Coleções</h2>
      <p className="text-xs" style={{ color: "var(--color-text-on-dark-muted)" }}>
        Prateleiras temáticas (ex: "Heróis da Fé") que podem reunir várias séries ou obras avulsas — diferente de série, que é sequencial dentro de uma coleção.
      </p>

      <div className="space-y-2">
        {colecoes?.map((c) => (
          <div key={c.id} className="flex items-center gap-2">
            <input
              defaultValue={c.nome}
              className="flex-1 rounded px-3 py-1.5 text-sm" style={campoEstilo}
              onBlur={(e) => atualizar.mutate({ id: c.id, nome: e.target.value })}
            />
            <button className="text-xs flex-shrink-0" style={{ color: "#ff8080" }} onClick={() => excluir.mutate({ id: c.id })}>
              remover
            </button>
          </div>
        ))}
      </div>

      <div className="flex items-center gap-2 pt-2" style={{ borderTop: "var(--border-thin)" }}>
        <input
          placeholder="nova coleção (ex: Heróis da Fé)"
          value={nome} onChange={(e) => setNome(e.target.value)}
          className="flex-1 rounded px-3 py-1.5 text-sm" style={campoEstilo}
        />
        <input
          placeholder="descrição curta (opcional)"
          value={descricao} onChange={(e) => setDescricao(e.target.value)}
          className="flex-1 rounded px-3 py-1.5 text-sm" style={campoEstilo}
        />
        <button
          className="btn btn-ghost text-xs flex-shrink-0" style={{ padding: "0.4rem 0.8rem" }}
          onClick={() => {
            if (!nome) return;
            criar.mutate({ nome, descricao: descricao || undefined });
            setNome("");
            setDescricao("");
          }}
        >
          + adicionar
        </button>
      </div>
    </div>
  );
}

function PainelHomeConfig() {
  const { data: config } = trpc.homeCms.config.obter.useQuery();
  const utils = trpc.useUtils();
  const atualizar = trpc.homeCms.config.atualizar.useMutation({ onSuccess: () => utils.homeCms.config.obter.invalidate() });

  if (!config) return null;

  function campo(chave: keyof NonNullable<typeof config>, rotulo: string, tipo: "texto" | "textarea" = "texto") {
    const Elemento = tipo === "textarea" ? "textarea" : "input";
    return (
      <label className="block text-sm" style={{ color: "var(--color-text-on-dark-muted)" }}>
        {rotulo}
        <Elemento
          className="w-full rounded px-3 py-2 mt-1"
          style={campoEstilo}
          defaultValue={(config![chave] as string) ?? ""}
          onBlur={(e) => atualizar.mutate({ [chave]: e.target.value } as never)}
        />
      </label>
    );
  }

  return (
    <div className="mt-8 space-y-6">
      <div className="space-y-3 rounded-lg p-4" style={{ background: "var(--color-bg-card-dark)", border: "var(--border-thin)" }}>
        <h2 className="font-medium" style={{ fontFamily: "var(--font-display)" }}>Hero</h2>
        {campo("heroTitulo", "título (linha 1)")}
        {campo("heroTituloDestaque", "título em destaque (linha 2, dourada)")}
        {campo("heroSubtitulo", "subtítulo", "textarea")}
        {campo("heroFundoUrl", "URL da imagem de fundo")}
        <label className="block text-sm" style={{ color: "var(--color-text-on-dark-muted)" }}>
          intensidade do overlay escuro (0-100)
          <input type="number" min={0} max={100} className="w-full rounded px-3 py-2 mt-1" style={campoEstilo}
            defaultValue={config.heroOverlayIntensidade} onBlur={(e) => atualizar.mutate({ heroOverlayIntensidade: Number(e.target.value) })} />
        </label>
        <label className="flex items-center gap-2 text-sm" style={{ color: "var(--color-text-on-dark-muted)" }}>
          <input type="checkbox" defaultChecked={config.heroBuscaAtiva} onChange={(e) => atualizar.mutate({ heroBuscaAtiva: e.target.checked })} />
          mostrar busca no hero
        </label>
        {campo("heroBuscaPlaceholder", "texto de exemplo da busca")}
        <label className="block text-sm" style={{ color: "var(--color-text-on-dark-muted)" }}>
          critério dos destaques do hero
          <select className="w-full rounded px-3 py-2 mt-1" style={campoEstilo} defaultValue={config.destaquesCriterio}
            onChange={(e) => atualizar.mutate({ destaquesCriterio: e.target.value as "manual" | "recentes" | "aleatorio" })}>
            <option value="manual" style={{ color: "#000" }}>manual (livros marcados como destaque)</option>
            <option value="recentes" style={{ color: "#000" }}>sempre os mais recentes</option>
            <option value="aleatorio" style={{ color: "#000" }}>aleatório</option>
          </select>
        </label>
      </div>

      <div className="space-y-3 rounded-lg p-4" style={{ background: "var(--color-bg-card-dark)", border: "var(--border-thin)" }}>
        <h2 className="font-medium" style={{ fontFamily: "var(--font-display)" }}>Todos os livros</h2>
        <label className="block text-sm" style={{ color: "var(--color-text-on-dark-muted)" }}>
          ordenação
          <select className="w-full rounded px-3 py-2 mt-1" style={campoEstilo} defaultValue={config.todosLivrosOrdenacao}
            onChange={(e) => atualizar.mutate({ todosLivrosOrdenacao: e.target.value as "recentes" | "aleatorio" | "titulo" })}>
            <option value="recentes" style={{ color: "#000" }}>mais recentes primeiro</option>
            <option value="aleatorio" style={{ color: "#000" }}>aleatório</option>
            <option value="titulo" style={{ color: "#000" }}>ordem alfabética</option>
          </select>
        </label>
      </div>

      <div className="space-y-3 rounded-lg p-4" style={{ background: "var(--color-bg-card-dark)", border: "var(--border-thin)" }}>
        <h2 className="font-medium" style={{ fontFamily: "var(--font-display)" }}>Rodapé</h2>
        {campo("footerDescricao", "descrição", "textarea")}
        {campo("footerCopyright", "linha de copyright (deixe em branco pro padrão)")}
      </div>

      <div className="space-y-3 rounded-lg p-4" style={{ background: "var(--color-bg-card-dark)", border: "var(--border-thin)" }}>
        <h2 className="font-medium" style={{ fontFamily: "var(--font-display)" }}>SEO</h2>
        {campo("seoTitulo", "título da página")}
        {campo("seoDescricao", "meta descrição", "textarea")}
        {campo("seoOgImagemUrl", "imagem de compartilhamento (og:image)")}
        {campo("seoKeywords", "palavras-chave")}
        {campo("seoCanonical", "URL canônica")}
      </div>

      <div className="space-y-3 rounded-lg p-4" style={{ background: "var(--color-bg-card-dark)", border: "var(--border-thin)" }}>
        <h2 className="font-medium" style={{ fontFamily: "var(--font-display)" }}>Aparência</h2>
        <p className="text-xs" style={{ color: "var(--color-text-on-dark-muted)" }}>
          conjunto curado de cores — não é cor-por-elemento, de propósito, pra manter consistência visual.
        </p>
        <div className="flex gap-3">
          <label className="text-sm flex-1" style={{ color: "var(--color-text-on-dark-muted)" }}>
            cor primária (dourado)
            <input type="color" className="w-full h-10 rounded mt-1" defaultValue={config.corPrimaria} onBlur={(e) => atualizar.mutate({ corPrimaria: e.target.value })} />
          </label>
          <label className="text-sm flex-1" style={{ color: "var(--color-text-on-dark-muted)" }}>
            cor de fundo
            <input type="color" className="w-full h-10 rounded mt-1" defaultValue={config.corFundo} onBlur={(e) => atualizar.mutate({ corFundo: e.target.value })} />
          </label>
        </div>
      </div>
    </div>
  );
}

function PainelHeroCards() {
  const { data: cards } = trpc.homeCms.heroCards.listarTodos.useQuery();
  const utils = trpc.useUtils();
  const criar = trpc.homeCms.heroCards.criar.useMutation({ onSuccess: () => utils.homeCms.heroCards.listarTodos.invalidate() });
  const atualizar = trpc.homeCms.heroCards.atualizar.useMutation({ onSuccess: () => utils.homeCms.heroCards.listarTodos.invalidate() });
  const excluir = trpc.homeCms.heroCards.excluir.useMutation({ onSuccess: () => utils.homeCms.heroCards.listarTodos.invalidate() });

  const [titulo, setTitulo] = useState("");
  const [imagemUrl, setImagemUrl] = useState("");
  const [linkUrl, setLinkUrl] = useState("");

  return (
    <div className="mt-8 space-y-3 rounded-lg p-4" style={{ background: "var(--color-bg-card-dark)", border: "var(--border-thin)" }}>
      <h2 className="font-medium" style={{ fontFamily: "var(--font-display)" }}>Cards do Hero</h2>
      <p className="text-xs" style={{ color: "var(--color-text-on-dark-muted)" }}>
        Se nenhum card estiver cadastrado aqui, o hero mostra os destaques automáticos. Cadastrando aqui, estes têm prioridade.
      </p>
      <div className="space-y-2">
        {cards?.map((c) => (
          <div key={c.id} className="flex items-center gap-2">
            <input defaultValue={c.titulo} className="flex-1 rounded px-2 py-1.5 text-sm" style={campoEstilo} onBlur={(e) => atualizar.mutate({ id: c.id, titulo: e.target.value })} />
            <input defaultValue={c.imagemUrl ?? ""} placeholder="imagem" className="flex-1 rounded px-2 py-1.5 text-sm" style={campoEstilo} onBlur={(e) => atualizar.mutate({ id: c.id, imagemUrl: e.target.value })} />
            <input defaultValue={c.linkUrl ?? ""} placeholder="link" className="flex-1 rounded px-2 py-1.5 text-sm" style={campoEstilo} onBlur={(e) => atualizar.mutate({ id: c.id, linkUrl: e.target.value })} />
            <label className="flex items-center gap-1 text-xs flex-shrink-0" style={{ color: "var(--color-text-on-dark-muted)" }}>
              <input type="checkbox" defaultChecked={c.ativo} onChange={(e) => atualizar.mutate({ id: c.id, ativo: e.target.checked })} /> ativo
            </label>
            <button className="text-xs flex-shrink-0" style={{ color: "#ff8080" }} onClick={() => excluir.mutate({ id: c.id })}>remover</button>
          </div>
        ))}
      </div>
      <div className="flex items-center gap-2 pt-2" style={{ borderTop: "var(--border-thin)" }}>
        <input placeholder="título" value={titulo} onChange={(e) => setTitulo(e.target.value)} className="flex-1 rounded px-2 py-1.5 text-sm" style={campoEstilo} />
        <input placeholder="imagem (opcional)" value={imagemUrl} onChange={(e) => setImagemUrl(e.target.value)} className="flex-1 rounded px-2 py-1.5 text-sm" style={campoEstilo} />
        <input placeholder="link" value={linkUrl} onChange={(e) => setLinkUrl(e.target.value)} className="flex-1 rounded px-2 py-1.5 text-sm" style={campoEstilo} />
        <button className="btn btn-ghost text-xs flex-shrink-0" style={{ padding: "0.4rem 0.8rem" }}
          onClick={() => { if (!titulo) return; criar.mutate({ titulo, imagemUrl: imagemUrl || undefined, linkUrl: linkUrl || undefined }); setTitulo(""); setImagemUrl(""); setLinkUrl(""); }}>
          + adicionar
        </button>
      </div>
    </div>
  );
}

function PainelBanners() {
  const { data: banners } = trpc.homeCms.banners.listarTodos.useQuery();
  const utils = trpc.useUtils();
  const criar = trpc.homeCms.banners.criar.useMutation({ onSuccess: () => utils.homeCms.banners.listarTodos.invalidate() });
  const atualizar = trpc.homeCms.banners.atualizar.useMutation({ onSuccess: () => utils.homeCms.banners.listarTodos.invalidate() });
  const excluir = trpc.homeCms.banners.excluir.useMutation({ onSuccess: () => utils.homeCms.banners.listarTodos.invalidate() });

  const [titulo, setTitulo] = useState("");
  const [linkUrl, setLinkUrl] = useState("");

  return (
    <div className="mt-8 space-y-3 rounded-lg p-4" style={{ background: "var(--color-bg-card-dark)", border: "var(--border-thin)" }}>
      <h2 className="font-medium" style={{ fontFamily: "var(--font-display)" }}>Banners (cross-divulgação do ecossistema)</h2>
      <p className="text-xs" style={{ color: "var(--color-text-on-dark-muted)" }}>
        Independente do hero — pode ter período de exibição (ex: só durante um congresso). Deixe as datas em branco pra sempre visível.
      </p>
      <div className="space-y-2">
        {banners?.map((b) => (
          <div key={b.id} className="rounded p-3 space-y-2" style={{ border: "var(--border-thin)" }}>
            <div className="flex gap-2">
              <input defaultValue={b.titulo} className="flex-1 rounded px-2 py-1.5 text-sm" style={campoEstilo} onBlur={(e) => atualizar.mutate({ id: b.id, titulo: e.target.value })} />
              <input defaultValue={b.linkUrl} placeholder="link" className="flex-1 rounded px-2 py-1.5 text-sm" style={campoEstilo} onBlur={(e) => atualizar.mutate({ id: b.id, linkUrl: e.target.value })} />
            </div>
            <div className="flex gap-2 items-center">
              <label className="text-xs flex-1" style={{ color: "var(--color-text-on-dark-muted)" }}>
                início
                <input type="date" defaultValue={b.dataInicio?.toString().slice(0, 10) ?? ""} className="w-full rounded px-2 py-1 text-sm mt-0.5" style={campoEstilo}
                  onChange={(e) => atualizar.mutate({ id: b.id, dataInicio: e.target.value })} />
              </label>
              <label className="text-xs flex-1" style={{ color: "var(--color-text-on-dark-muted)" }}>
                fim
                <input type="date" defaultValue={b.dataFim?.toString().slice(0, 10) ?? ""} className="w-full rounded px-2 py-1 text-sm mt-0.5" style={campoEstilo}
                  onChange={(e) => atualizar.mutate({ id: b.id, dataFim: e.target.value })} />
              </label>
              <label className="flex items-center gap-1 text-xs flex-shrink-0 mt-3" style={{ color: "var(--color-text-on-dark-muted)" }}>
                <input type="checkbox" defaultChecked={b.ativo} onChange={(e) => atualizar.mutate({ id: b.id, ativo: e.target.checked })} /> ativo
              </label>
              <button className="text-xs flex-shrink-0 mt-3" style={{ color: "#ff8080" }} onClick={() => excluir.mutate({ id: b.id })}>remover</button>
            </div>
          </div>
        ))}
      </div>
      <div className="flex items-center gap-2 pt-2" style={{ borderTop: "var(--border-thin)" }}>
        <input placeholder="título (ex: Ouça no SpotOnFide)" value={titulo} onChange={(e) => setTitulo(e.target.value)} className="flex-1 rounded px-2 py-1.5 text-sm" style={campoEstilo} />
        <input placeholder="link (ex: https://spot.onfide.com.br)" value={linkUrl} onChange={(e) => setLinkUrl(e.target.value)} className="flex-1 rounded px-2 py-1.5 text-sm" style={campoEstilo} />
        <button className="btn btn-ghost text-xs flex-shrink-0" style={{ padding: "0.4rem 0.8rem" }}
          onClick={() => { if (!titulo || !linkUrl) return; criar.mutate({ titulo, linkUrl }); setTitulo(""); setLinkUrl(""); }}>
          + adicionar
        </button>
      </div>
    </div>
  );
}

function PainelSecoesListas() {
  const utils = trpc.useUtils();

  const { data: comoFunciona } = trpc.homeCms.comoFunciona.listar.useQuery();
  const criarCF = trpc.homeCms.comoFunciona.criar.useMutation({ onSuccess: () => utils.homeCms.comoFunciona.listar.invalidate() });
  const atualizarCF = trpc.homeCms.comoFunciona.atualizar.useMutation({ onSuccess: () => utils.homeCms.comoFunciona.listar.invalidate() });
  const excluirCF = trpc.homeCms.comoFunciona.excluir.useMutation({ onSuccess: () => utils.homeCms.comoFunciona.listar.invalidate() });

  const { data: acervo } = trpc.homeCms.acervoItens.listarTodos.useQuery();
  const criarAc = trpc.homeCms.acervoItens.criar.useMutation({ onSuccess: () => utils.homeCms.acervoItens.listarTodos.invalidate() });
  const atualizarAc = trpc.homeCms.acervoItens.atualizar.useMutation({ onSuccess: () => utils.homeCms.acervoItens.listarTodos.invalidate() });
  const excluirAc = trpc.homeCms.acervoItens.excluir.useMutation({ onSuccess: () => utils.homeCms.acervoItens.listarTodos.invalidate() });

  const { data: publico } = trpc.homeCms.publicoItens.listarTodos.useQuery();
  const criarPub = trpc.homeCms.publicoItens.criar.useMutation({ onSuccess: () => utils.homeCms.publicoItens.listarTodos.invalidate() });
  const atualizarPub = trpc.homeCms.publicoItens.atualizar.useMutation({ onSuccess: () => utils.homeCms.publicoItens.listarTodos.invalidate() });
  const excluirPub = trpc.homeCms.publicoItens.excluir.useMutation({ onSuccess: () => utils.homeCms.publicoItens.listarTodos.invalidate() });

  const { data: beneficios } = trpc.homeCms.beneficios.listarTodos.useQuery();
  const criarBen = trpc.homeCms.beneficios.criar.useMutation({ onSuccess: () => utils.homeCms.beneficios.listarTodos.invalidate() });
  const atualizarBen = trpc.homeCms.beneficios.atualizar.useMutation({ onSuccess: () => utils.homeCms.beneficios.listarTodos.invalidate() });
  const excluirBen = trpc.homeCms.beneficios.excluir.useMutation({ onSuccess: () => utils.homeCms.beneficios.listarTodos.invalidate() });

  const { data: faq } = trpc.homeCms.faqItens.listarTodos.useQuery();
  const criarFaq = trpc.homeCms.faqItens.criar.useMutation({ onSuccess: () => utils.homeCms.faqItens.listarTodos.invalidate() });
  const atualizarFaq = trpc.homeCms.faqItens.atualizar.useMutation({ onSuccess: () => utils.homeCms.faqItens.listarTodos.invalidate() });
  const excluirFaq = trpc.homeCms.faqItens.excluir.useMutation({ onSuccess: () => utils.homeCms.faqItens.listarTodos.invalidate() });

  return (
    <>
      <PainelRepetidor
        titulo="Como Funciona"
        descricao="ícone = nome de um ícone do lucide-react (ex: Search, BookOpen, Bookmark)"
        temAtivo={false}
        campos={[
          { chave: "icone", rotulo: "ícone" },
          { chave: "numero", rotulo: "número" },
          { chave: "titulo", rotulo: "título" },
          { chave: "descricao", rotulo: "descrição", tipo: "textarea" },
        ]}
        itens={comoFunciona}
        aoCriar={(d) => criarCF.mutate(d as { icone: string; numero: string; titulo: string; descricao?: string })}
        aoAtualizar={(id, d) => atualizarCF.mutate({ id, ...d })}
        aoExcluir={(id) => excluirCF.mutate({ id })}
      />

      <PainelRepetidor
        titulo="O Acervo (formatos)"
        campos={[
          { chave: "icone", rotulo: "ícone" },
          { chave: "nome", rotulo: "nome" },
          { chave: "descricao", rotulo: "descrição", tipo: "textarea" },
          { chave: "linkUrl", rotulo: "link" },
        ]}
        itens={acervo}
        aoCriar={(d) => criarAc.mutate(d as { icone: string; nome: string; descricao?: string; linkUrl: string })}
        aoAtualizar={(id, d) => atualizarAc.mutate({ id, ...d })}
        aoExcluir={(id) => excluirAc.mutate({ id })}
      />

      <PainelRepetidor
        titulo="Leitura pra Toda a Família (público)"
        campos={[
          { chave: "icone", rotulo: "ícone" },
          { chave: "nome", rotulo: "nome" },
          { chave: "faixaEtaria", rotulo: "faixa etária" },
          { chave: "linkUrl", rotulo: "link" },
        ]}
        itens={publico}
        aoCriar={(d) => criarPub.mutate(d as { icone: string; nome: string; faixaEtaria: string; linkUrl: string })}
        aoAtualizar={(id, d) => atualizarPub.mutate({ id, ...d })}
        aoExcluir={(id) => excluirPub.mutate({ id })}
      />

      <PainelRepetidor
        titulo="Por Que Ler (experiência)"
        campos={[
          { chave: "icone", rotulo: "ícone" },
          { chave: "texto", rotulo: "texto" },
        ]}
        itens={beneficios}
        aoCriar={(d) => criarBen.mutate(d as { icone: string; texto: string })}
        aoAtualizar={(id, d) => atualizarBen.mutate({ id, ...d })}
        aoExcluir={(id) => excluirBen.mutate({ id })}
      />

      <PainelRepetidor
        titulo="Perguntas Frequentes"
        campos={[
          { chave: "pergunta", rotulo: "pergunta" },
          { chave: "resposta", rotulo: "resposta", tipo: "textarea" },
        ]}
        itens={faq}
        aoCriar={(d) => criarFaq.mutate(d as { pergunta: string; resposta: string })}
        aoAtualizar={(id, d) => atualizarFaq.mutate({ id, ...d })}
        aoExcluir={(id) => excluirFaq.mutate({ id })}
      />
    </>
  );
}

export function Admin() {
  const { usuario, isLoading, podePublicar, logout } = useAuth();
  const [livroEmEdicao, setLivroEmEdicao] = useState<LivroExistente | null>(null);

  if (isLoading) return null;
  if (!usuario) {
    window.location.href = "/entrar";
    return null;
  }
  if (!podePublicar)
    return (
      <div className="min-h-dvh p-6" style={{ background: "var(--gradient-hero)", color: "var(--color-text-on-dark)" }}>
        Sua conta não tem permissão de editor.
      </div>
    );

  return (
    <div className="min-h-dvh" style={{ background: "var(--gradient-hero)", color: "var(--color-text-on-dark)" }}>
      <div className="max-w-2xl mx-auto p-6">
        <div className="flex justify-between items-center mb-6">
          <img src="/media/images/logo-biblioteca-onfide.svg" alt="Biblioteca OnFide" className="h-7" />
          <button style={{ color: "var(--color-text-on-dark-muted)" }} className="text-sm" onClick={() => logout.mutate()}>sair</button>
        </div>
        <FormularioPublicacao
          key={livroEmEdicao?.id ?? "novo"}
          livroExistente={livroEmEdicao}
          aoTerminar={() => setLivroEmEdicao(null)}
        />
        <ListaLivros aoEditar={setLivroEmEdicao} />
        <PainelConfiguracao />
        <PainelColecoes />
        <PainelMenu />
        <h2 className="mt-10 mb-2 text-lg" style={{ fontFamily: "var(--font-display)" }}>CMS da Home</h2>
        <PainelHomeConfig />
        <PainelHeroCards />
        <PainelBanners />
        <PainelSecoesListas />
      </div>
    </div>
  );
}
