import { COOKIE_NAME } from "@shared/const";
import { parse as parseCookieHeader } from "cookie";
import express, {
  type NextFunction,
  type Request,
  type Response,
  type Router,
} from "express";
import fs from "fs";
import multer from "multer";
import { nanoid } from "nanoid";
import path from "path";
import { verifySessionToken } from "./auth";
import * as db from "../db";

const UPLOADS_DIR = path.resolve(process.cwd(), "uploads");
const AUDIO_DIR = path.join(UPLOADS_DIR, "audio");
const IMAGES_DIR = path.join(UPLOADS_DIR, "images");

for (const dir of [AUDIO_DIR, IMAGES_DIR]) {
  fs.mkdirSync(dir, { recursive: true });
}

function sanitizeFilename(name: string): string {
  const base = path.basename(name).replace(/[^a-zA-Z0-9._-]/g, "_");
  return base.length > 0 ? base.slice(-120) : "arquivo";
}

const audioStorage = multer.diskStorage({
  destination: (_req, _file, cb) => cb(null, AUDIO_DIR),
  filename: (_req, file, cb) =>
    cb(null, `${nanoid(10)}-${sanitizeFilename(file.originalname)}`),
});

const imageStorage = multer.diskStorage({
  destination: (_req, _file, cb) => cb(null, IMAGES_DIR),
  filename: (_req, file, cb) =>
    cb(null, `${nanoid(10)}-${sanitizeFilename(file.originalname)}`),
});

const audioUpload = multer({
  storage: audioStorage,
  limits: { fileSize: 300 * 1024 * 1024 }, // 300MB — sermões/podcasts longos
  fileFilter: (_req, file, cb) => {
    const okMime = /^audio\//.test(file.mimetype);
    const okExt = /\.(mp3|wav|m4a|ogg|aac|flac)$/i.test(file.originalname);
    if (okMime || okExt) return cb(null, true);
    cb(new Error("Tipo de arquivo de áudio inválido"));
  },
});

const imageUpload = multer({
  storage: imageStorage,
  limits: { fileSize: 10 * 1024 * 1024 }, // 10MB
  fileFilter: (_req, file, cb) => {
    if (/^image\//.test(file.mimetype)) return cb(null, true);
    cb(new Error("Tipo de arquivo de imagem inválido"));
  },
});

async function requireAdmin(req: Request, res: Response, next: NextFunction) {
  try {
    const cookies = parseCookieHeader(req.headers.cookie ?? "");
    const session = await verifySessionToken(cookies[COOKIE_NAME]);
    if (!session) {
      res.status(401).json({ error: "Não autenticado" });
      return;
    }

    const user = await db.getUserById(session.uid);
    if (!user || user.role !== "admin") {
      res.status(403).json({ error: "Acesso restrito a administradores" });
      return;
    }

    next();
  } catch {
    res.status(401).json({ error: "Não autenticado" });
  }
}

/**
 * Registers local file upload endpoints (admin-only) and serves the
 * uploaded files statically from /uploads. Files are stored on disk under
 * <project root>/uploads — this directory is independent of `dist/`, so it
 * survives rebuilds/redeploys as long as the folder itself is preserved.
 */
export function registerUploadRoutes(app: Router) {
  app.use("/uploads", express.static(UPLOADS_DIR));

  app.post(
    "/api/upload/audio",
    requireAdmin,
    audioUpload.single("file"),
    (req, res) => {
      if (!req.file) {
        res.status(400).json({ error: "Nenhum arquivo enviado" });
        return;
      }
      res.json({ url: `/uploads/audio/${req.file.filename}` });
    }
  );

  app.post(
    "/api/upload/image",
    requireAdmin,
    imageUpload.single("file"),
    (req, res) => {
      if (!req.file) {
        res.status(400).json({ error: "Nenhum arquivo enviado" });
        return;
      }
      res.json({ url: `/uploads/images/${req.file.filename}` });
    }
  );

  // Multer / fileFilter errors land here instead of crashing the request.
  app.use(
    "/api/upload",
    (err: unknown, _req: Request, res: Response, next: NextFunction) => {
      if (!err) return next();
      const message = err instanceof Error ? err.message : "Erro no upload";
      res.status(400).json({ error: message });
    }
  );
}
