import cookieParser from "cookie-parser";
import cors from "cors";
import express from "express";
import rateLimit from "express-rate-limit";
import helmet from "helmet";
import morgan from "morgan";
import { corsOrigins } from "./config/env.js";
import { isMailConfigured, verifyMailTransport } from "./lib/mail.js";
import { errorHandler } from "./middleware/error-handler.js";
import { appVersionRouter } from "./modules/app-version/app-version.routes.js";
import { adminRouter } from "./modules/admin/admin.routes.js";
import { authRouter } from "./modules/auth/auth.routes.js";
import { internalRouter } from "./modules/internal/internal.routes.js";
import { pushRouter } from "./modules/push/push.routes.js";
import { rssRouter } from "./modules/rss/rss.routes.js";
import { signalsRouter } from "./modules/signals/signals.routes.js";
import { usersRouter } from "./modules/users/users.routes.js";

export const app = express();

if (isMailConfigured()) {
  void verifyMailTransport()
    .then(() => {
      console.info("SMTP transport verified");
    })
    .catch((error) => {
      console.error("SMTP transport verification failed", error instanceof Error ? error.message : String(error));
    });
} else {
  console.warn("SMTP is not fully configured. Password reset emails are disabled.");
}

app.set("trust proxy", 1);
app.use(helmet());
app.use(
  cors({
    origin(origin, callback) {
      if (!origin || corsOrigins.includes(origin)) {
        callback(null, true);
        return;
      }

      callback(new Error(`CORS blocked for origin: ${origin}`));
    },
    credentials: true
  })
);
const apiLimiter = rateLimit({
  windowMs: 15 * 60 * 1000,
  max: 300,
  standardHeaders: true,
  legacyHeaders: false
});
const authLimiter = rateLimit({
  windowMs: 15 * 60 * 1000,
  max: 10,
  standardHeaders: true,
  legacyHeaders: false,
  message: { message: "Too many authentication requests. Try again later." }
});
const publicWriteLimiter = rateLimit({
  windowMs: 15 * 60 * 1000,
  max: 60,
  standardHeaders: true,
  legacyHeaders: false,
  message: { message: "Too many requests. Try again later." }
});
const internalLimiter = rateLimit({
  windowMs: 60 * 1000,
  max: 30,
  standardHeaders: true,
  legacyHeaders: false,
  message: { message: "Too many internal requests. Try again later." }
});

app.use(apiLimiter);
app.use(express.json({ limit: "1mb" }));
app.use(cookieParser());
app.use(morgan("dev"));
app.use("/auth/login", authLimiter);
app.use("/auth/register", authLimiter);
app.use("/auth/forgot-password", authLimiter);
app.use("/auth/reset-password", authLimiter);
app.use("/public", publicWriteLimiter);
app.use("/internal", internalLimiter);

app.get("/health", (_req, res) => {
  res.json({ ok: true });
});

app.use("/", appVersionRouter);
app.use("/auth", authRouter);
app.use("/signals", signalsRouter);
app.use("/", rssRouter);
app.use("/", pushRouter);
app.use("/", usersRouter);
app.use("/internal", internalRouter);
app.use("/admin", adminRouter);
app.use(errorHandler);
