/* global React, window */
const { useState, useRef, useEffect } = React;

// Step 12: Final confirmation, agrupa por segmento (Literatura · Didáticos · Papelaria · Outros)
// Sem preços, isso fica pro Passo 1 (Previsão de preço).
function Step11_Confirm() {
  const { data, setData } = useApp();
  // Séries de verdade da escola (Passo 1), não a lista fixa de 12.
  const activeSeries = resolveSeriesList(data);
  const hasEN = data.scolexEN !== "none";
  const qtyPT = data.qtyPerYearPT ?? (data.qtyPerYear ?? 3);
  const qtyEN = hasEN ? (data.qtyPerYearEN ?? 2) : 0;
  const qty = qtyPT + qtyEN;
  const pinned = data.pinned || {};
  const didaticosAdopted = data.didaticosAdopted || {};
  const papelariaCart = data.papelaria || {};
  const customMaterials = data.customMaterials || [];
  const optionalBooks = data.optionalBooks || {};
  const [editMode, setEditMode] = useState(false);
  const [removingIds, setRemovingIds] = useState(() => new Set());

  const runtimeSelectionTop = data.runtimeSelection || {};
  const runtimeSchoolId = runtimeSelectionTop.schoolId || "";
  const runtimePeriod = runtimeSelectionTop.period || String(new Date().getFullYear());
  const runtimeGradesTop = Array.isArray(runtimeSelectionTop.availableGrades) ? runtimeSelectionTop.availableGrades : [];

  // ===== Removers (modo editar) =====
  // Esse passo (Confirmação final) tinha sua PRÓPRIA função de remover
  // livro, separada da que existe no passo Recomendações/Revisão — e essa
  // aqui nunca chamou o backend nenhuma vez, só mexia em pinned local.
  // Resultado: o livro sumia da tela, mas continuava salvo no Scolist, e
  // voltava assim que qualquer outra tela revisitasse a série (bug
  // reportado pelo Alex, 27/08/2026: "comportamento de não deletar na 13
  // continua também"). Reescrito pra chamar unpinBookFromGrade de verdade,
  // pessimista igual o fix de steps-curation.jsx — só some da tela depois
  // que o backend confirmar, removendo também todo item duplicado com o
  // mesmo ISBN (mesmo motivo do fix de duplicata, ver TAREFAS).
  const removeLitBook = async (seriesIdx, bookId) => {
    const book = CATALOG.find(b => b.id === bookId);
    const grade = findGradeForSeriesIndex(runtimeGradesTop, seriesIdx, activeSeries);
    const rawItems = (grade && runtimeSelectionTop.recommendedByGradeId
      && runtimeSelectionTop.recommendedByGradeId[grade.id]
      && runtimeSelectionTop.recommendedByGradeId[grade.id].items) || [];
    const byIsbn = book && book.isbn ? rawItems.filter((raw) => raw && raw.isbn === book.isbn) : [];
    const idsToRemove = byIsbn.length > 0
      ? Array.from(new Set(byIsbn.map((raw) => raw.id).filter(Boolean)))
      : [book && (book.gradeBookId || book.bookId)].filter(Boolean);

    let ok = true;
    if (window.ScolistAPI && typeof window.ScolistAPI.unpinBookFromGrade === "function" && idsToRemove.length > 0 && runtimeSchoolId && grade && grade.id) {
      setRemovingIds(prev => new Set(prev).add(bookId));
      try {
        for (const itemId of idsToRemove) {
          // eslint-disable-next-line no-await-in-loop
          await window.ScolistAPI.unpinBookFromGrade(runtimeSchoolId, runtimePeriod, grade.id, itemId);
        }
        if (book) book.gradeBookId = null;
        // purgeFromRuntimeItemsCache definida em steps-curation.jsx
        // (script global carregado antes deste) — mesmo motivo do fix
        // "delete funciona mas refresh traz de volta", ver comentário lá.
        purgeFromRuntimeItemsCache(setData, grade.id, idsToRemove);
      } catch (error) {
        console.error("Falha ao remover livro da lista:", error);
        ok = false;
      } finally {
        setRemovingIds(prev => { const next = new Set(prev); next.delete(bookId); return next; });
      }
    }
    if (!ok) return;

    setData(d => {
      const next = { ...(d.pinned || {}) };
      next[seriesIdx] = (next[seriesIdx] || []).filter(id => id !== bookId);
      return { ...d, pinned: next };
    });
  };
  // Para livros "auto" (sugestões), adiciona à blocklist para que o auto-fill os pule
  const blockAutoBook = (seriesIdx, bookId) => {
    setData(d => {
      const blocked = { ...(d.blockedAutoBooks || {}) };
      blocked[seriesIdx] = [...new Set([...(blocked[seriesIdx] || []), bookId])];
      return { ...d, blockedAutoBooks: blocked };
    });
  };
  // Marca/desmarca um livro como opcional (a família não é obrigada a
  // comprar) — só afeta o rótulo mostrado na lista (aqui, no Excel
  // exportado e na página da família), não remove o livro nem mexe no
  // Scolist.
  const toggleOptionalBook = (seriesIdx, bookId) => {
    setData(d => {
      const cur = (d.optionalBooks || {})[seriesIdx] || [];
      const next = cur.includes(bookId) ? cur.filter(id => id !== bookId) : [...cur, bookId];
      return { ...d, optionalBooks: { ...(d.optionalBooks || {}), [seriesIdx]: next } };
    });
  };
  const removeDidatico = (seriesIdx, itemId) => {
    setData(d => {
      const next = { ...(d.didaticosAdopted || {}) };
      next[seriesIdx] = (next[seriesIdx] || []).filter(a => a.itemId !== itemId);
      return { ...d, didaticosAdopted: next };
    });
  };
  const removePap = (seriesIdx, cartIdx) => {
    setData(d => {
      const next = { ...(d.papelaria || {}) };
      next[seriesIdx] = (next[seriesIdx] || []).filter((_, j) => j !== cartIdx);
      return { ...d, papelaria: next };
    });
  };
  const removeCustomFromSeries = (materialId, seriesIdx) => {
    setData(d => {
      const list = (d.customMaterials || []).map(m => {
        if (m.id !== materialId) return m;
        const seriesApplied = (m.seriesApplied || []).filter(j => j !== seriesIdx);
        return { ...m, seriesApplied };
      }).filter(m => (m.seriesApplied || []).length > 0);
      return { ...d, customMaterials: list };
    });
  };
  const PAPELARIA_CAT = window.PAPELARIA_CATALOG || [];
  const PAPELARIA_PARTNERS_LOCAL = window.PAPELARIA_PARTNERS || {};

  // ===== Contagens por segmento =====
  const litCount = Object.values(pinned).reduce((a, b) => a + b.length, 0);
  const didCount = Object.values(didaticosAdopted).reduce((a, b) => a + b.length, 0);
  const papCount = Object.values(papelariaCart).reduce((a, b) => a + b.length, 0);
  const customCount = customMaterials.reduce((s, m) => s + (m.seriesApplied?.length || 1), 0);
  const totalItems = litCount + didCount + papCount + customCount;

  return (
    <div>
      <Heading
        eyebrow="Fechamento · Passo 1, Confirmação"
        title="Sua lista está quase pronta"
        subtitle="Revise série por série, literatura, didáticos, papelaria e outros materiais juntos. Você pode adicionar materiais próprios da escola antes de gerar o link final. A previsão de preço aparece no próximo passo." />
      <LexBubble pose="cheer">
        Antes de finalizar, dá uma última olhada com calma 👀 Eu já confirmei pra você: temas pedagógicos alinhados, níveis <Scolex/> aplicados, disponibilidade conferida e curadoria revisada por série. Se algum desses pontos te deixar em dúvida, é só voltar, senão, segue pro próximo passo.
      </LexBubble>

      {/* ===== Banner modo editar ===== */}
      {editMode ? (
        <div style={{
          marginTop: 18, padding: "12px 18px",
          background: "linear-gradient(180deg, #fff5e6 0%, #ffeacc 100%)",
          border: "1.5px solid #d97757",
          borderRadius: 12,
          display: "flex", alignItems: "center", gap: 14, flexWrap: "wrap",
          boxShadow: "0 2px 8px rgba(217, 119, 87, 0.15)",
        }}>
          <div style={{
            width: 32, height: 32, borderRadius: "50%",
            background: "#d97757", color: "#fff",
            display: "flex", alignItems: "center", justifyContent: "center",
            fontSize: 16, flexShrink: 0,
          }}>✏️</div>
          <div style={{ flex: 1, minWidth: 200 }}>
            <div style={{ fontSize: 13.5, fontWeight: 700, color: "var(--text)" }}>
              Modo edição ativo
            </div>
            <div style={{ fontSize: 11.5, color: "var(--text-mute)", marginTop: 2 }}>
              Clique no <strong style={{ color: "#b53a3a" }}>✕</strong> ao lado de cada item pra remover. Livros marcados <em>auto</em> são sugestões automáticas — pra removê-los, volte na curadoria.
            </div>
          </div>
          <button
            onClick={() => setEditMode(false)}
            style={{
              padding: "10px 18px", fontSize: 13, fontWeight: 800,
              background: "#d97757", color: "#fff",
              border: "none", borderRadius: 8, cursor: "pointer", fontFamily: "inherit",
              boxShadow: "0 2px 6px rgba(217, 119, 87, 0.35)",
              flexShrink: 0,
            }}
          >
            ✓ Concluir edição
          </button>
        </div>
      ) : (
        <div style={{ marginTop: 18, display: "flex", justifyContent: "flex-end" }}>
          <button
            onClick={() => setEditMode(true)}
            style={{
              padding: "8px 14px", fontSize: 12.5, fontWeight: 700,
              background: "#fff", color: "var(--text)",
              border: "1.5px solid var(--border)",
              borderRadius: 8, cursor: "pointer", fontFamily: "inherit",
              display: "inline-flex", alignItems: "center", gap: 6,
            }}
          >
            ✏️ Editar lista
          </button>
        </div>
      )}

      <div style={{ marginTop: 24, display: "flex", flexDirection: "column", gap: 14 }}>

          {activeSeries.map((s, i) => {
            // === Literatura desta série ===
            // Antes completava a lista com sugestões "auto" (não pinadas de
            // verdade) até bater a cota da calibragem — e o filtro dessas
            // sugestões pegava livro de série vizinha também
            // (Math.abs(...) <= 1), então um livro pensado pro 2º ano podia
            // aparecer "de graça" na lista do 1º. A etiqueta "auto" que
            // distinguia isso é pequena/discreta, fácil de não perceber com
            // vários livros na tela — dava a impressão de duas listas
            // diferentes entre Recomendações e Confirmação final. A pedido
            // do Alex (27/08/2026, "a lista deve ser uma só"), agora mostra
            // só o que está pinado de verdade — idêntico ao que aparece em
            // Recomendações.
            const ids = pinned[i] || [];
            const pinnedBooks = ids.map(id => CATALOG.find(b => b.id === id)).filter(Boolean);
            const pinnedPT = pinnedBooks.filter(b => b.lang === "pt");
            const pinnedEN = pinnedBooks.filter(b => b.lang === "en");
            const litShown = [...pinnedPT, ...pinnedEN];

            // === Didáticos desta série ===
            const adoptedHere = didaticosAdopted[i] || [];
            // resolveDidatico (definida em steps-didaticos.jsx, script global
            // carregado antes deste) olha primeiro em DIDATICOS_RUNTIME — os
            // itens achados por busca ao vivo no passo 10, com capa real —
            // antes de cair no catálogo estático. Usar direto window.DIDATICOS
            // aqui perdia esses itens vindos de busca (ou, na melhor das
            // hipóteses, achava a versão sem capa).
            const didItems = adoptedHere.map(a => resolveDidatico(a.itemId)).filter(Boolean);

            // === Papelaria desta série ===
            const papHere = (papelariaCart[i] || []).map(c => {
              const it = PAPELARIA_CAT.find(x => x.id === c.itemId);
              const br = it?.brands?.[c.brandIdx];
              const partner = br ? PAPELARIA_PARTNERS_LOCAL[br.partnerId] : null;
              return it && br ? { name: it.genericName, brand: partner?.name, qty: c.qty } : null;
            }).filter(Boolean);

            // === Outros desta série ===
            const customHere = customMaterials.filter(m => m.seriesApplied?.includes(i));

            const seriesItemsCount = litShown.length + didItems.length + papHere.length + customHere.length;

            return (
              <SeriesCard key={s} label={s} itemsCount={seriesItemsCount}>
                <SegmentInline icon="📚" label="Literatura" color="var(--teal)" count={litShown.length}>
                  <div style={{ display: "flex", gap: 8, flexWrap: "wrap" }}>
                    {litShown.length === 0 ? <Empty>nenhum livro</Empty> : litShown.map((b, j) => {
                      const isPinned = !b.auto;
                      const showX = editMode;
                      const isOptional = (optionalBooks[i] || []).includes(b.id);
                      return (
                        <div key={j} style={{ display: "flex", flexDirection: "column", gap: 4, alignItems: "flex-start" }}>
                          <div style={{ position: "relative" }}>
                            <BookChip b={b} langLabel={b.lang === "en" ? "EN" : "PT"} langColor={b.lang === "en" ? "#2c4ffc" : "var(--teal)"} optional={isOptional} />
                            {showX && (
                              <button onClick={() => isPinned ? removeLitBook(i, b.id) : blockAutoBook(i, b.id)}
                                disabled={removingIds.has(b.id)}
                                title={removingIds.has(b.id) ? "Removendo…" : (isPinned ? "Remover livro" : "Remover sugestão automática")}
                                style={{ ...removeBtnStyle, cursor: removingIds.has(b.id) ? "wait" : "pointer", opacity: removingIds.has(b.id) ? 0.5 : 1 }}>
                                {removingIds.has(b.id) ? "…" : "✕"}
                              </button>
                            )}
                          </div>
                          {isPinned && (
                            <button onClick={() => toggleOptionalBook(i, b.id)}
                              title={isOptional ? "Clique para tornar obrigatório de novo" : "Marcar como opcional — a família não é obrigada a comprar"}
                              style={{
                                padding: "3px 8px", borderRadius: 999, fontSize: 10, fontWeight: 700, fontFamily: "inherit",
                                border: isOptional ? "1px solid #d99a3a" : "1px dashed var(--border)",
                                background: isOptional ? "#fff3e0" : "transparent",
                                color: isOptional ? "#9a6416" : "var(--text-mute)",
                                cursor: "pointer",
                              }}>
                              {isOptional ? "★ Opcional" : "☆ Marcar opcional"}
                            </button>
                          )}
                        </div>
                      );
                    })}
                  </div>
                </SegmentInline>

                <SegmentInline icon="📘" label="Didáticos" color="#3aaaa3" count={didItems.length}>
                  {didItems.length === 0 ? <Empty>nenhum adotado</Empty> : (
                    <div style={{ display: "flex", flexDirection: "column", gap: 4 }}>
                      {didItems.map((it, j) => {
                        const langColor = ({ pt: "var(--teal-dark)", en: "#2c4ffc", ib: "#8b5cf6", es: "#e8a23a", fr: "#5b8de8", al: "#c8536a" })[it.lang] || "var(--teal)";
                        const langShort = ({ pt: "PT", en: "EN", ib: "IB", es: "ES", fr: "FR", al: "AL" })[it.lang] || it.lang.toUpperCase();
                        return (
                          <div key={j} style={{ display: "flex", gap: 8, alignItems: "center", fontSize: 12 }}>
                            <DidaticoCover item={it} w={20} h={28} />
                            <span style={{ padding: "2px 6px", borderRadius: 3, fontSize: 9, fontWeight: 800, background: langColor, color: "#fff", letterSpacing: 0.4 }}>{langShort}</span>
                            <span style={{ fontWeight: 600, color: "var(--text)", flex: 1, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{it.title}</span>
                            <span style={{ fontSize: 10.5, color: "var(--text-mute)" }}>{it.publisher}</span>
                            {editMode && (
                              <button onClick={() => removeDidatico(i, it.id)}
                                title="Remover didático"
                                style={removeBtnInlineStyle}>✕</button>
                            )}
                          </div>
                        );
                      })}
                    </div>
                  )}
                </SegmentInline>

                <SegmentInline icon="✏️" label="Papelaria" color="#e0798e" count={papHere.length}>
                  {papHere.length === 0 ? <Empty>{data.papelariaMode === "skip" ? "papelaria não inclusa" : "nenhum item"}</Empty> : (
                    <div style={{ display: "flex", flexWrap: "wrap", gap: 6 }}>
                      {papHere.map((p, j) => (
                        <div key={j} style={{ position: "relative", display: "inline-flex", alignItems: "center", gap: 6, padding: "4px 9px", background: "var(--bg-light)", border: "1px solid var(--border)", borderRadius: 8, fontSize: 11.5 }}>
                          <span style={{ fontWeight: 600, color: "var(--text)" }}>{p.name}</span>
                          <span style={{ color: "var(--text-mute)", fontSize: 10.5 }}>×{p.qty}</span>
                          {p.brand && <span style={{ fontSize: 9.5, color: "var(--text-mute)", padding: "1px 5px", borderRadius: 3, background: "#fff", border: "1px solid var(--border)" }}>{p.brand}*</span>}
                          {editMode && (
                            <button onClick={() => removePap(i, j)}
                              title="Remover item"
                              style={removeBtnStyle}>✕</button>
                          )}
                        </div>
                      ))}
                    </div>
                  )}
                </SegmentInline>

                <SegmentInline icon="🎒" label="Outros" color="#c44d6a" count={customHere.length}>
                  {customHere.length === 0 ? <Empty>nenhum material extra</Empty> : (
                    <div style={{ display: "flex", flexDirection: "column", gap: 4 }}>
                      {customHere.map(m => (
                        <div key={m.id} style={{ display: "flex", gap: 8, alignItems: "center", fontSize: 12 }}>
                          <span style={{ fontWeight: 600, color: "var(--text)", flex: 1 }}>{m.name}</span>
                          {m.desc && <span style={{ fontSize: 10.5, color: "var(--text-mute)" }}>{m.desc}</span>}
                          {editMode && (
                            <button onClick={() => removeCustomFromSeries(m.id, i)}
                              title="Remover desta série"
                              style={removeBtnInlineStyle}>✕</button>
                          )}
                        </div>
                      ))}
                    </div>
                  )}
                </SegmentInline>
              </SeriesCard>
            );
          })}

          {/* ===== Outros materiais (gestão global) ===== */}
          <CustomMaterialsCard
            items={customMaterials}
            onAdd={(m) => setData(d => ({ ...d, customMaterials: [...(d.customMaterials || []), m] }))}
            onRemove={(id) => setData(d => ({ ...d, customMaterials: (d.customMaterials || []).filter(x => x.id !== id) }))}
          />

      </div>

      {/* ===== Finalização: marca da escola, download ===== */}
      <LandingBrandingCard/>
      <div style={{ marginTop: 24, display: "flex", gap: 10, flexWrap: "wrap" }}>
        <a href="#familia" target="_blank" rel="noopener" style={{
          padding: "12px 18px", borderRadius: 10,
          background: "#fff", border: "1.5px solid var(--teal)",
          color: "var(--teal-dark)", fontWeight: 600, fontSize: 14, textDecoration: "none",
          display: "inline-flex", alignItems: "center", gap: 8,
        }}>
          👁 Preview da lista da família <span style={{ fontSize: 11, opacity: 0.85 }}>↗</span>
        </a>
        <button onClick={() => window.exportListaPorTurma && window.exportListaPorTurma(data)} style={{
          padding: "12px 18px", borderRadius: 10,
          background: "var(--teal)", color: "#fff", border: "none",
          fontWeight: 700, fontSize: 14, cursor: "pointer",
          display: "inline-flex", alignItems: "center", gap: 8,
        }}>
          ⬇ Baixar lista (Excel, uma aba por turma)
        </button>
      </div>
    </div>
  );
}

// Marca da escola (logo + cor de destaque) pra página da família — movido do
// passo 15 (Link da lista) pra cá, a pedido da Joana: passo 15 virou só
// download, essa configuração faz mais sentido junto da revisão final.
// Upload de logo escondido por enquanto (Alex, 27/08/2026) — ainda não
// temos esse recurso pronto. Fica só a cor de destaque, que já funciona.
// Reativar trocando essa constante pra true.
const LOGO_UPLOAD_ENABLED = false;

function LandingBrandingCard() {
  const { data, setData, account, setAccount } = useApp();
  const [dragOver, setDragOver] = useState(false);
  const [uploading, setUploading] = useState(false);
  const [uploadError, setUploadError] = useState(null);
  const fileRef = useRef(null);

  // Logo + accent vivem em `account.school` (persistidos em
  // schools/{id}.logo/.accent no Scolist, ver README-INTEGRACAO-SCOLIST.md
  // §5). Mantemos fallback pra `data.*` por compatibilidade com snapshots
  // antigos salvos só no localStorage.
  const logoUrl = (account && account.school && account.school.logoUrl) || data.schoolLogoUrl;
  const accent  = (account && account.school && account.school.accent)  || data.schoolAccent || "var(--teal)";
  const logoName = data.schoolLogoName || (logoUrl ? "logo.png" : null);

  // Upload via API (PUT /school/:schoolId, campo `logo`). Atualiza account
  // global pra refletir na sidebar imediatamente.
  const handleFile = async (f) => {
    if (!f) return;
    setUploadError(null);
    setUploading(true);
    try {
      const { logoUrl: url, fileName } = await window.ScolistAPI.uploadSchoolLogo(f);
      setAccount(acc => acc ? ({ ...acc, school: { ...acc.school, logoUrl: url } }) : acc);
      setData(d => ({ ...d, schoolLogoUrl: url, schoolLogoName: fileName }));
    } catch (e) {
      setUploadError(e.message || "Falha no upload");
    } finally {
      setUploading(false);
    }
  };

  const handleRemoveLogo = async (e) => {
    e?.stopPropagation?.();
    try {
      await window.ScolistAPI.removeSchoolLogo();
      setAccount(acc => acc ? ({ ...acc, school: { ...acc.school, logoUrl: null } }) : acc);
      setData(d => ({ ...d, schoolLogoUrl: null, schoolLogoName: null }));
    } catch (err) {
      setUploadError(err.message || "Falha ao remover");
    }
  };

  // Cor de destaque — persiste via PATCH /api/school (TODO(backend)).
  const setAccent = async (val) => {
    setData(d => ({ ...d, schoolAccent: val })); // optimistic local
    setAccount(acc => acc ? ({ ...acc, school: { ...acc.school, accent: val } }) : acc);
    try { await window.ScolistAPI.updateSchoolBranding({ accent: val }); } catch {}
  };

  return (
    <div style={{
      marginTop: 24, background: "#fff", border: "1px solid var(--border)",
      borderRadius: 20, padding: 20, boxShadow: "var(--shadow-sm)",
    }}>
      <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 14 }}>
        <div>
          <div style={{ fontSize: 13, fontWeight: 700, color: "var(--teal-dark)", textTransform: "uppercase", letterSpacing: 1 }}>Personalização da landing</div>
          <div style={{ fontSize: 13, color: "var(--text-mute)", marginTop: 4 }}>
            {LOGO_UPLOAD_ENABLED
              ? "Suba a logo da escola, vai aparecer no cabeçalho da página que as famílias recebem."
              : "Escolha a cor de destaque da página que as famílias recebem."}
          </div>
        </div>
      </div>

      <div style={{ display: "grid", gridTemplateColumns: LOGO_UPLOAD_ENABLED ? "1fr 1fr" : "1fr", gap: 16 }}>
        {LOGO_UPLOAD_ENABLED && (
          <div
            onDragOver={(e) => { e.preventDefault(); setDragOver(true); }}
            onDragLeave={() => setDragOver(false)}
            onDrop={(e) => { e.preventDefault(); setDragOver(false); handleFile(e.dataTransfer.files?.[0]); }}
            onClick={() => !uploading && fileRef.current?.click()}
            style={{
              border: `2px dashed ${dragOver ? "var(--teal)" : "var(--border)"}`,
              background: dragOver ? "rgba(60,170,163,0.06)" : "var(--bg-soft)",
              borderRadius: 14, padding: 20, cursor: uploading ? "wait" : "pointer",
              display: "flex", gap: 14, alignItems: "center",
              transition: "all 0.15s",
              opacity: uploading ? 0.7 : 1,
            }}
          >
            <input ref={fileRef} type="file" accept="image/*" style={{ display: "none" }}
              onChange={(e) => handleFile(e.target.files?.[0])} />
            {logoUrl ? (
              <>
                <div style={{
                  width: 72, height: 72, borderRadius: 12, background: "#fff",
                  border: "1px solid var(--border)", display: "flex", alignItems: "center", justifyContent: "center", overflow: "hidden", flexShrink: 0,
                }}>
                  <img src={logoUrl} alt="logo" style={{ maxWidth: "85%", maxHeight: "85%", objectFit: "contain" }} />
                </div>
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ fontSize: 14, fontWeight: 700, color: "var(--text)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{logoName || "logo.png"}</div>
                  <div style={{ fontSize: 12, color: "var(--text-mute)", marginTop: 2 }}>Aparece no preview e no menu lateral</div>
                  <button
                    onClick={handleRemoveLogo}
                    style={{ marginTop: 8, background: "transparent", border: "none", color: "var(--coral)", fontSize: 12, fontWeight: 600, cursor: "pointer", padding: 0 }}
                  >Remover</button>
                </div>
              </>
            ) : (
              <>
                <div style={{
                  width: 56, height: 56, borderRadius: 12, background: "#fff",
                  border: "1px solid var(--border)", display: "flex", alignItems: "center", justifyContent: "center", fontSize: 24, flexShrink: 0,
                }}>🖼️</div>
                <div style={{ flex: 1 }}>
                  <div style={{ fontSize: 14, fontWeight: 700, color: "var(--text)" }}>Subir logo da escola</div>
                  <div style={{ fontSize: 12, color: "var(--text-mute)", marginTop: 2, lineHeight: 1.5 }}>
                    {uploading ? "Enviando…" : "Arraste ou clique. PNG, SVG ou JPG, fundo transparente fica melhor."}
                  </div>
                  {uploadError ? (
                    <div style={{ fontSize: 12, color: "var(--coral)", marginTop: 6, fontWeight: 600 }}>{uploadError}</div>
                  ) : null}
                </div>
              </>
            )}
          </div>
        )}

        {/* Cor de destaque */}
        <div style={{ background: "var(--bg-soft)", borderRadius: 14, padding: 20 }}>
          <div style={{ fontSize: 13, fontWeight: 700, color: "var(--text)", marginBottom: 10 }}>Cor de destaque da página</div>
          <div style={{ display: "flex", gap: 10, flexWrap: "wrap" }}>
            {[
              { name: "Scolist", val: "var(--teal)" },
              { name: "Azul",   val: "#2c4ffc" },
              { name: "Coral",  val: "#e0798e" },
              { name: "Verde",  val: "#6fc48a" },
              { name: "Violeta",val: "#8b5cf6" },
              { name: "Âmbar",  val: "#f5b942" },
            ].map(c => (
              <button key={c.name} onClick={() => setAccent(c.val)} title={c.name}
                style={{
                  width: 36, height: 36, borderRadius: "50%", background: c.val,
                  border: accent === c.val ? "3px solid var(--text)" : "2px solid #fff",
                  boxShadow: "0 0 0 1px var(--border)",
                  cursor: "pointer",
                }} />
            ))}
          </div>
          {LOGO_UPLOAD_ENABLED && (
            <div style={{ fontSize: 11, color: "var(--text-mute)", marginTop: 10, lineHeight: 1.5 }}>Se preferir, posso extrair a cor principal da sua logo automaticamente.</div>
          )}
        </div>
      </div>
    </div>
  );
}

// ===== Helpers Step11 =====
const removeBtnStyle = {
  position: "absolute", top: -7, right: -7,
  width: 20, height: 20, borderRadius: "50%",
  background: "#fff", border: "1px solid var(--border)",
  fontSize: 10.5, fontWeight: 700, color: "#b53a3a",
  cursor: "pointer",
  boxShadow: "0 2px 6px rgba(0,0,0,0.15)",
  display: "flex", alignItems: "center", justifyContent: "center",
  padding: 0, lineHeight: 1,
};
const removeBtnInlineStyle = {
  width: 18, height: 18, borderRadius: "50%",
  background: "#fff5f5", border: "1px solid #f0cdcd",
  fontSize: 10, fontWeight: 700, color: "#b53a3a",
  cursor: "pointer", marginLeft: 4,
  display: "inline-flex", alignItems: "center", justifyContent: "center",
  padding: 0, lineHeight: 1, flexShrink: 0,
};
function Row({ k, v }) {
  return (
    <div style={{ display: "flex", justifyContent: "space-between", fontSize: 13, padding: "4px 0" }}>
      <span style={{ opacity: 0.85 }}>{k}</span>
      <span style={{ fontWeight: 700, fontVariantNumeric: "tabular-nums" }}>{v}</span>
    </div>
  );
}

function SeriesCard({ label, itemsCount, children }) {
  return (
    <div style={{ background: "#fff", border: "1px solid var(--border)", borderRadius: 16, padding: 18, boxShadow: "var(--shadow-sm)" }}>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", marginBottom: 14, paddingBottom: 12, borderBottom: "1px solid var(--border)" }}>
        <div style={{ fontSize: 17, fontWeight: 800, color: "var(--text)", letterSpacing: -0.4 }}>{label}</div>
        <div style={{ display: "flex", alignItems: "baseline", gap: 8 }}>
          <span style={{ fontSize: 10.5, fontWeight: 700, color: "var(--text-mute)", textTransform: "uppercase", letterSpacing: 0.8 }}>Itens</span>
          <span style={{ fontSize: 17, fontWeight: 800, color: "var(--teal-dark)", fontVariantNumeric: "tabular-nums" }}>{itemsCount}</span>
        </div>
      </div>
      <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
        {children}
      </div>
    </div>
  );
}

function SegmentInline({ icon, label, color, count, children }) {
  return (
    <div style={{ display: "grid", gridTemplateColumns: "120px 1fr", gap: 14, alignItems: "flex-start", padding: "8px 0" }}>
      <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
        <div style={{ width: 24, height: 24, borderRadius: 6, background: color + "22", color, display: "flex", alignItems: "center", justifyContent: "center", fontSize: 12, flexShrink: 0 }}>{icon}</div>
        <div>
          <div style={{ fontSize: 12, fontWeight: 700, color: "var(--text)" }}>{label}</div>
          <div style={{ fontSize: 10.5, color: "var(--text-mute)" }}>{count} {count === 1 ? "item" : "itens"}</div>
        </div>
      </div>
      <div style={{ minWidth: 0 }}>{children}</div>
    </div>
  );
}

function Empty({ children }) {
  return <span style={{ fontSize: 12, color: "var(--text-mute)", fontStyle: "italic" }}>{children}</span>;
}

function BookChip({ b, langLabel, langColor, optional }) {
  return (
    <div title={b.title} style={{ display: "flex", gap: 8, alignItems: "center", padding: "6px 10px 6px 6px", background: b.auto ? "var(--bg-soft)" : "var(--bg-light)", border: optional ? "1px solid #d99a3a" : "1px solid var(--border)", borderRadius: 10 }}>
      <div style={{ flexShrink: 0, position: "relative" }}>
        <BookCover book={b} size={26} />
        <div style={{ position: "absolute", bottom: -2, right: -4, fontSize: 8, fontWeight: 800, background: langColor, color: "#fff", padding: "1px 3px", borderRadius: 3, lineHeight: 1 }}>{langLabel}</div>
      </div>
      <div style={{ fontSize: 12.5, fontWeight: 600, color: "var(--text)", maxWidth: 160, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{b.title}</div>
      {b.auto && <span style={{ fontSize: 10, color: "var(--text-mute)", fontStyle: "italic" }}>auto</span>}
    </div>
  );
}

function CustomMaterialsCard({ items, onAdd, onRemove }) {
  const { data } = useApp();
  // Séries de verdade da escola (Passo 1), não a lista fixa de 12.
  const activeSeries = resolveSeriesList(data);
  const [adding, setAdding] = useState(false);
  const [draft, setDraft] = useState({ name: "", desc: "", price: "", scope: "all", seriesIdx: [] });

  const toggleSeries = (i) => setDraft(d => ({
    ...d,
    seriesIdx: d.seriesIdx.includes(i) ? d.seriesIdx.filter(x => x !== i) : [...d.seriesIdx, i],
  }));

  // Segmento de cada série pelo nome canônico embutido nela (window.canonicalIndexOf,
  // shared.jsx) — não pela posição, que muda conforme a escola cadastra Educação
  // Infantil, renomeia ou reordena séries no Passo 1.
  const indicesInSegment = (fromCanon, toCanon) => activeSeries
    .map((name, i) => ({ i, canon: window.canonicalIndexOf(name) }))
    .filter(({ canon }) => canon >= fromCanon && canon <= toCanon)
    .map(({ i }) => i);

  const save = () => {
    if (!draft.name.trim()) return;
    const seriesApplied = draft.scope === "all"
      ? activeSeries.map((_, i) => i)
      : draft.scope === "fund1" ? indicesInSegment(0, 4)
      : draft.scope === "fund2" ? indicesInSegment(5, 8)
      : draft.scope === "em" ? indicesInSegment(9, 11)
      : draft.scope === "preescola" ? indicesInSegment(0, 1) // proxy
      : draft.seriesIdx;
    onAdd({
      id: "cm_" + Date.now(),
      name: draft.name.trim(),
      desc: draft.desc.trim(),
      price: parseFloat(draft.price) || 0,
      scope: draft.scope,
      seriesApplied,
    });
    setDraft({ name: "", desc: "", price: "", scope: "all", seriesIdx: [] });
    setAdding(false);
  };

  const SCOPE_LABEL = {
    all: "Todas as séries", fund1: "Fundamental I", fund2: "Fundamental II",
    em: "Ensino Médio", preescola: "Pré-escola (1º,2º ano)", custom: "Séries específicas",
  };

  return (
    <div style={{ background: "#fff", border: "1px solid var(--border)", borderRadius: 20, padding: 24, boxShadow: "var(--shadow-sm)" }}>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 14, paddingBottom: 14, borderBottom: "1px solid var(--border)" }}>
        <div style={{ display: "flex", alignItems: "center", gap: 12 }}>
          <div style={{ width: 36, height: 36, borderRadius: 10, background: "#e0798e22", color: "#c44d6a", display: "flex", alignItems: "center", justifyContent: "center", fontSize: 18 }}>🎒</div>
          <div>
            <div style={{ fontSize: 15, fontWeight: 800, color: "var(--text)", letterSpacing: -0.2 }}>Outros materiais</div>
            <div style={{ fontSize: 12, color: "var(--text-mute)", marginTop: 2 }}>
              {items.length === 0 ? "Material próprio da escola, kits, apostilas, cadernos específicos..." : `${items.length} ${items.length === 1 ? "item" : "itens"}`}
            </div>
          </div>
        </div>
      </div>

      {items.length > 0 && (
        <div style={{ display: "flex", flexDirection: "column", gap: 8, marginBottom: 14 }}>
          {items.map(m => (
            <div key={m.id} style={{ display: "flex", gap: 12, alignItems: "center", padding: "10px 12px", background: "var(--bg-soft)", border: "1px solid var(--border)", borderRadius: 10 }}>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ fontSize: 13.5, fontWeight: 700, color: "var(--text)" }}>{m.name}</div>
                <div style={{ fontSize: 11.5, color: "var(--text-mute)", marginTop: 2 }}>
                  {SCOPE_LABEL[m.scope] || `${m.seriesApplied.length} séries`}
                  {m.desc && ` · ${m.desc}`}
                </div>
              </div>
              <span style={{ fontSize: 11, color: "var(--text-mute)" }}>×{m.seriesApplied.length} séries</span>
              <button onClick={() => onRemove(m.id)} style={{ background: "transparent", border: "none", color: "var(--text-mute)", fontSize: 16, cursor: "pointer", padding: 4 }} title="Remover">×</button>
            </div>
          ))}
        </div>
      )}

      {!adding ? (
        <button onClick={() => setAdding(true)} style={{
          width: "100%", padding: "14px 18px",
          background: "var(--bg-soft)", border: "1.5px dashed var(--border)",
          borderRadius: 12, cursor: "pointer", fontSize: 13.5, fontWeight: 600, color: "var(--teal-dark)",
          display: "flex", alignItems: "center", justifyContent: "center", gap: 10,
        }}>
          <span style={{ fontSize: 16 }}>+</span> Adicionar outros materiais
          <span style={{ fontSize: 11.5, fontWeight: 500, color: "var(--text-mute)" }}>(material próprio, kit higiene, apostila…)</span>
        </button>
      ) : (
        <div style={{ padding: 18, background: "var(--bg-soft)", border: "1.5px solid var(--teal)", borderRadius: 14 }}>
          <div style={{ fontSize: 13, fontWeight: 700, color: "var(--text)", marginBottom: 14 }}>Novo material</div>
          <div style={{ display: "grid", gridTemplateColumns: "1fr 120px", gap: 10, marginBottom: 10 }}>
            <input value={draft.name} onChange={e => setDraft(d => ({ ...d, name: e.target.value }))}
              placeholder="Nome (ex: Kit higiene Pré-escola)" autoFocus
              style={{ padding: "10px 12px", border: "1px solid var(--border)", borderRadius: 8, fontSize: 13.5, fontFamily: "inherit", background: "#fff" }}/>
            <input value={draft.price} onChange={e => setDraft(d => ({ ...d, price: e.target.value }))}
              placeholder="Preço (R$)" type="number"
              style={{ padding: "10px 12px", border: "1px solid var(--border)", borderRadius: 8, fontSize: 13.5, fontFamily: "inherit", background: "#fff" }}/>
          </div>
          <input value={draft.desc} onChange={e => setDraft(d => ({ ...d, desc: e.target.value }))}
            placeholder="Descrição (opcional, ex: produzido pela escola, retirar na secretaria)"
            style={{ width: "100%", padding: "10px 12px", border: "1px solid var(--border)", borderRadius: 8, fontSize: 13, fontFamily: "inherit", background: "#fff", marginBottom: 12 }}/>

          <div style={{ fontSize: 11, fontWeight: 700, color: "var(--text-mute)", textTransform: "uppercase", letterSpacing: 0.6, marginBottom: 8 }}>Em quais séries aplicar?</div>
          <div style={{ display: "flex", gap: 6, flexWrap: "wrap", marginBottom: draft.scope === "custom" ? 10 : 14 }}>
            {[
              ["all", "Todas as séries"],
              ["fund1", "Fundamental I"],
              ["fund2", "Fundamental II"],
              ["em", "Ensino Médio"],
              ["custom", "Escolher séries"],
            ].map(([id, lbl]) => (
              <button key={id} onClick={() => setDraft(d => ({ ...d, scope: id }))} style={{
                padding: "6px 12px", borderRadius: 6, fontSize: 12, fontWeight: 700,
                border: draft.scope === id ? "1.5px solid var(--teal-dark)" : "1px solid var(--border)",
                background: draft.scope === id ? "#e7f4f5" : "#fff",
                color: draft.scope === id ? "var(--teal-dark)" : "var(--text)",
                cursor: "pointer",
              }}>{lbl}</button>
            ))}
          </div>

          {draft.scope === "custom" && (
            <div style={{ display: "flex", gap: 4, flexWrap: "wrap", marginBottom: 14, padding: 10, background: "#fff", borderRadius: 8, border: "1px solid var(--border)" }}>
              {activeSeries.map((s, i) => {
                const on = draft.seriesIdx.includes(i);
                return (
                  <button key={i} onClick={() => toggleSeries(i)} style={{
                    padding: "5px 9px", borderRadius: 5, fontSize: 11, fontWeight: 700,
                    border: on ? "1.5px solid var(--teal-dark)" : "1px solid var(--border)",
                    background: on ? "var(--teal-dark)" : "#fff", color: on ? "#fff" : "var(--text)",
                    cursor: "pointer",
                  }}>{s}</button>
                );
              })}
            </div>
          )}

          <div style={{ display: "flex", gap: 10, justifyContent: "flex-end" }}>
            <button onClick={() => { setAdding(false); setDraft({ name: "", desc: "", price: "", scope: "all", seriesIdx: [] }); }} style={{
              padding: "10px 16px", background: "transparent", color: "var(--text-mute)",
              border: "1px solid var(--border)", borderRadius: 8, fontSize: 13, fontWeight: 600, cursor: "pointer",
            }}>Cancelar</button>
            <button onClick={save} disabled={!draft.name.trim()} style={{
              padding: "10px 18px", background: draft.name.trim() ? "var(--teal-dark)" : "var(--border)",
              color: "#fff", border: "none", borderRadius: 8, fontSize: 13, fontWeight: 700,
              cursor: draft.name.trim() ? "pointer" : "not-allowed",
            }}>Adicionar</button>
          </div>
        </div>
      )}
    </div>
  );
}

// Step 14: Final link
function Step13_Link() {
  const { data } = useApp();

  // Ao chegar nesta tela, envia a lista de cada série já tocada pro backend
  // com status "aguardando aprovação" — front-onboard nunca auto-aprova
  // (isso é ação do time no console, ver README-INTEGRACAO-SCOLIST.md §6).
  // Sem link público ativo aqui: o snapshot compartilhável só existe depois
  // que alguém do Scolist aprovar a lista.
  const runtimeSelection = data.runtimeSelection || {};
  const submitSchoolId = runtimeSelection.schoolId || "";
  const submitPeriod = runtimeSelection.period || "";
  const submitGrades = Array.isArray(runtimeSelection.availableGrades) ? runtimeSelection.availableGrades : [];
  const [submitState, setSubmitState] = useState("idle"); // idle | submitting | done | error

  useEffect(() => {
    if (submitState !== "idle") return;
    if (!window.ScolistAPI || typeof window.ScolistAPI.submitSeriesList !== "function") return;
    if (!submitSchoolId || !submitPeriod || submitGrades.length === 0) return;

    let cancelled = false;
    setSubmitState("submitting");

    Promise.all(submitGrades.map((grade) =>
      window.ScolistAPI.submitSeriesList(submitSchoolId, submitPeriod, grade.id)
    ))
      .then(() => { if (!cancelled) setSubmitState("done"); })
      .catch((error) => {
        console.error("Falha ao enviar lista para aprovação:", error);
        if (!cancelled) setSubmitState("error");
      });

    return () => { cancelled = true; };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [submitSchoolId, submitPeriod, JSON.stringify(submitGrades.map((g) => g.id))]);

  return (
    <div>
      <Heading
        eyebrow="Fechamento · Passo 15"
        title="Baixe sua lista"
        subtitle="Excel com uma aba por turma — série, categoria, ISBN, título e preço de cada item." />
      <LexBubble pose="cheer">
        Prontinho, sua lista está finalizada 🌱 {submitState === "done"
          ? "Já mandei ela pra equipe Scolist aprovar."
          : submitState === "error"
            ? "Não consegui enviar pra aprovação agora, mas você já pode baixar sua lista — tento de novo em seguida."
            : "Estou enviando ela agora pra equipe Scolist aprovar."}
      </LexBubble>

      <div style={{
        marginTop: 32, background: "#fff", border: "1px solid var(--border)",
        borderRadius: 20, padding: 40, boxShadow: "var(--shadow-sm)",
        display: "flex", flexDirection: "column", alignItems: "center", gap: 16, textAlign: "center",
      }}>
        <div style={{ fontSize: 40 }}>⬇️</div>
        <div>
          <div style={{ fontSize: 18, fontWeight: 800, color: "var(--text)" }}>Lista completa em Excel</div>
          <div style={{ fontSize: 13.5, color: "var(--text-mute)", marginTop: 4 }}>Uma aba por turma · série, categoria, ISBN, título e preço</div>
        </div>
        <button onClick={() => window.exportListaPorTurma && window.exportListaPorTurma(data)} style={{
          padding: "14px 28px", borderRadius: 30,
          background: "var(--teal)", color: "#fff", border: "none",
          fontWeight: 700, fontSize: 15, cursor: "pointer",
        }}>
          ⬇ Baixar lista (Excel)
        </button>
      </div>
    </div>
  );
}

Object.assign(window, { Step11_Confirm, Step13_Link });
