import express from "express";
import multer from "multer";
import fs from "node:fs";
import path from "node:path";
import crypto from "node:crypto";
import mammoth from "mammoth";
import { EPub } from "epub-gen-memory";
import { exigirEditor } from "./require-auth-rest.js";
const UPLOADS_DIR = path.resolve("uploads");
const DOCX_DIR = path.join(UPLOADS_DIR, "docx");
const EPUB_DIR = path.join(UPLOADS_DIR, "epub");
const CAPAS_DIR = path.join(UPLOADS_DIR, "capas");
const PAGINAS_DIR = path.join(UPLOADS_DIR, "paginas");
// Sinopse automática (decisão do Marsan: extração simples, sem IA,
// sem custo) — pega o começo do texto real do livro, sem tags HTML,
// cortado num limite de palavra (nunca no meio de uma palavra) com
// reticências. Só serve de ponto de partida — o editor pode reescrever.
function extrairResumoAutomatico(html, limite = 320) {
    const textoLimpo = html
        .replace(/<h1[^>]*>.*?<\/h1>/gi, "") // não repete o título do capítulo/livro
        .replace(/<[^>]+>/g, " ")
        .replace(/\s+/g, " ")
        .trim();
    if (textoLimpo.length <= limite)
        return textoLimpo;
    const cortado = textoLimpo.slice(0, limite);
    const ultimoEspaco = cortado.lastIndexOf(" ");
    return `${cortado.slice(0, ultimoEspaco > 0 ? ultimoEspaco : limite)}…`;
}
export function garantirPastasDeUpload() {
    for (const dir of [DOCX_DIR, EPUB_DIR, CAPAS_DIR, PAGINAS_DIR]) {
        fs.mkdirSync(dir, { recursive: true });
    }
}
// Divide o HTML do mammoth em capítulos reais (um <h1> = um capítulo =
// um arquivo próprio no EPUB). Isso resolve dois problemas de uma vez:
// (1) o Sumário do leitor passa a ter entradas de verdade por capítulo,
// não só uma entrada com o título do livro inteiro; (2) cada capítulo
// começa num arquivo/página nova — sem isso, tudo virava um único blob
// contínuo e um capítulo podia começar no meio/fim de uma página.
// Fallback: se o Word não usou estilo de título nenhum, mantém como
// um capítulo só (comportamento antigo) em vez de quebrar a geração.
function dividirEmCapitulos(html, tituloLivro) {
    const partes = html.split(/(?=<h1[^>]*>)/i).filter((p) => p.trim().length > 0);
    if (partes.length <= 1) {
        return [{ title: tituloLivro, content: html }];
    }
    return partes.map((parte, indice) => {
        const match = parte.match(/<h1[^>]*>(.*?)<\/h1>/i);
        const titulo = match ? match[1].replace(/<[^>]+>/g, "").trim() : `Capítulo ${indice + 1}`;
        // epub-gen-memory já insere um <h1>{title}</h1> automaticamente a
        // partir do campo abaixo — removemos o <h1> original do conteúdo
        // pra não sair duplicado ("Reino de Sacerdotes" duas vezes seguidas).
        const conteudoSemH1 = parte.replace(/<h1[^>]*>.*?<\/h1>/i, "");
        return { title: titulo || `Capítulo ${indice + 1}`, content: conteudoSemH1 };
    });
}
const armazenamentoDocx = multer.diskStorage({
    destination: DOCX_DIR,
    filename: (_req, file, cb) => cb(null, `${crypto.randomUUID()}.docx`),
});
const armazenamentoCapa = multer.diskStorage({
    destination: CAPAS_DIR,
    filename: (_req, file, cb) => {
        const ext = path.extname(file.originalname) || ".jpg";
        cb(null, `${crypto.randomUUID()}${ext}`);
    },
});
const uploadDocx = multer({
    storage: armazenamentoDocx,
    limits: { fileSize: 20 * 1024 * 1024 }, // 20MB
    fileFilter: (_req, file, cb) => {
        const mimeCorreto = file.mimetype === "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
        const extensaoCorreta = path.extname(file.originalname).toLowerCase() === ".docx";
        if (mimeCorreto || extensaoCorreta)
            cb(null, true);
        else
            cb(new Error("Envie um arquivo .docx válido."));
    },
});
const uploadCapa = multer({
    storage: armazenamentoCapa,
    limits: { fileSize: 5 * 1024 * 1024 }, // 5MB
    fileFilter: (_req, file, cb) => {
        const valido = file.mimetype.startsWith("image/");
        if (valido)
            cb(null, true);
        else
            cb(new Error("Envie uma imagem válida."));
    },
});
const armazenamentoPaginas = multer.diskStorage({
    destination: PAGINAS_DIR,
    filename: (_req, file, cb) => {
        const ext = path.extname(file.originalname) || ".jpg";
        cb(null, `${crypto.randomUUID()}${ext}`);
    },
});
const uploadPaginas = multer({
    storage: armazenamentoPaginas,
    limits: { fileSize: 8 * 1024 * 1024, files: 300 }, // 8MB por página, até 300 páginas
    fileFilter: (_req, file, cb) => {
        const valido = file.mimetype.startsWith("image/");
        if (valido)
            cb(null, true);
        else
            cb(new Error("Envie apenas imagens."));
    },
});
export function registrarRotasDeUpload(app) {
    garantirPastasDeUpload();
    // DOCX -> converte pra EPUB na hora (mammoth + epub-gen-memory, sem binário externo)
    app.post("/api/admin/upload-docx", exigirEditor, uploadDocx.single("arquivo"), async (req, res) => {
        if (!req.file) {
            res.status(400).json({ erro: "Nenhum arquivo enviado." });
            return;
        }
        try {
            const titulo = req.body.titulo || "Sem título";
            const autor = req.body.autor || "Desconhecido";
            // Pasta temporária só pra esta conversão — o epub-gen-memory só
            // sabe "baixar" imagem via URL http(s) ou file://, nunca aceita
            // data: URI direto (é o padrão do mammoth sozinho, e quebra a
            // geração inteira com "Only HTTP(S) protocols are supported").
            // Por isso salvamos cada imagem num arquivo real primeiro.
            const dirImagensTemp = path.join(EPUB_DIR, `_tmp-imagens-${crypto.randomUUID()}`);
            fs.mkdirSync(dirImagensTemp, { recursive: true });
            const conversorImagem = mammoth.images.imgElement(async (imagem) => {
                const extensao = imagem.contentType.split("/")[1] || "png";
                const nomeArquivo = `${crypto.randomUUID()}.${extensao}`;
                const caminhoCompleto = path.join(dirImagensTemp, nomeArquivo);
                fs.writeFileSync(caminhoCompleto, await imagem.read());
                return { src: `file://${caminhoCompleto}` };
            });
            const { value: html } = await mammoth.convertToHtml({ path: req.file.path }, { convertImage: conversorImagem });
            const capitulos = dividirEmCapitulos(html, titulo);
            const resumoAutomatico = extrairResumoAutomatico(html);
            const epubBuffer = await new EPub({
                title: titulo,
                author: autor,
                lang: "pt-BR",
                // Cada capítulo sempre começa em página nova, e o título
                // nunca fica separado do texto que vem logo depois dele —
                // resolve o "capítulo começando no fim da página".
                css: `
              h1 { page-break-before: always; break-before: page; page-break-after: avoid; break-after: avoid; }
              table { border-collapse: collapse; width: 100%; }
              td, th { border: 1px solid #999; padding: 4px 8px; }
              img { max-width: 100%; height: auto; }
            `,
            }, capitulos).genEpub();
            // Limpa a pasta temporária de imagens — já foram lidas e
            // empacotadas de verdade dentro do .epub, não precisam mais existir soltas.
            fs.rmSync(dirImagensTemp, { recursive: true, force: true });
            const nomeEpub = `${crypto.randomUUID()}.epub`;
            fs.writeFileSync(path.join(EPUB_DIR, nomeEpub), epubBuffer);
            res.json({
                docxOriginalUrl: `/uploads/docx/${path.basename(req.file.path)}`,
                epubUrl: `/uploads/epub/${nomeEpub}`,
                resumoAutomatico,
            });
        }
        catch (err) {
            console.error("Erro na conversão DOCX->EPUB:", err);
            res.status(500).json({ erro: "Falha ao converter o DOCX para EPUB." });
        }
    });
    app.post("/api/admin/upload-capa", exigirEditor, uploadCapa.single("imagem"), (req, res) => {
        if (!req.file) {
            res.status(400).json({ erro: "Nenhuma imagem enviada." });
            return;
        }
        res.json({ url: `/uploads/capas/${path.basename(req.file.path)}` });
    });
    // Mangá/HQ/ilustrado — sobe várias páginas de uma vez, preservando a
    // ordem em que os arquivos chegaram (o navegador respeita a ordem de
    // seleção do input múltiplo).
    app.post("/api/admin/upload-paginas", exigirEditor, uploadPaginas.array("paginas", 300), (req, res) => {
        const arquivos = req.files;
        if (!arquivos || arquivos.length === 0) {
            res.status(400).json({ erro: "Nenhuma página enviada." });
            return;
        }
        const urls = arquivos.map((arquivo) => `/uploads/paginas/${path.basename(arquivo.path)}`);
        res.json({ urls });
    });
    app.use("/uploads", express.static(UPLOADS_DIR));
}
