import { createServer } from "http";
import path from "path";
import cookieParser from "cookie-parser";
import cors from "cors";
import express from "express";
import helmet from "helmet";
import { startDueDateReminderJob } from "./lib/dueDateReminders";
import { env } from "./lib/env";
import { startMailSyncJob } from "./lib/mailSync";
import { uploadRoot } from "./lib/upload";
import { errorHandler } from "./middleware/errorHandler";
import { activityRouter } from "./routes/activity.routes";
import { attachmentsRouter } from "./routes/attachments.routes";
import { authRouter } from "./routes/auth.routes";
import { automationsRouter } from "./routes/automations.routes";
import { boardsRouter } from "./routes/boards.routes";
import { cardsRouter } from "./routes/cards.routes";
import { checklistItemsRouter } from "./routes/checklistItems.routes";
import { checklistsRouter } from "./routes/checklists.routes";
import { commentsRouter } from "./routes/comments.routes";
import { driveRouter } from "./routes/drive.routes";
import { healthRouter } from "./routes/health.routes";
import { integrationsRouter } from "./routes/integrations.routes";
import { invitationsRouter } from "./routes/invitations.routes";
import { labelsRouter } from "./routes/labels.routes";
import { listsRouter } from "./routes/lists.routes";
import { mailRouter } from "./routes/mail.routes";
import { notificationsRouter } from "./routes/notifications.routes";
import { organizationsRouter } from "./routes/organizations.routes";
import { portalRouter } from "./routes/portal.routes";
import { searchRouter } from "./routes/search.routes";
import { usersRouter } from "./routes/users.routes";
import { workspacesRouter } from "./routes/workspaces.routes";
import { createSocketServer } from "./sockets/index";

const app = express();

// Production runs behind a single reverse proxy (Apache -> this Node process on
// 127.0.0.1) — trust its X-Forwarded-For/Proto so req.ip and express-rate-limit's
// IP-based limiting see the real client IP instead of throwing on an
// unrecognized forwarded header. "1" = trust exactly one hop, not "true" (which
// would trust the whole chain and defeat the point of the check).
if (env.NODE_ENV === "production") {
  app.set("trust proxy", 1);
}

app.use(
  helmet({
    // This is a JSON API + static file server, not an HTML-rendering app, so the
    // default CSP (meant for pages with scripts/styles) doesn't apply here.
    contentSecurityPolicy: false,
    // Frontend and backend run on different origins/ports — without this, helmet's
    // default same-origin resource policy blocks the frontend from loading images
    // and attachments served from /uploads.
    crossOriginResourcePolicy: { policy: "cross-origin" },
  })
);
app.use(cors({ origin: env.CLIENT_URL, credentials: true }));
app.use(express.json());
app.use(cookieParser());
app.use(
  "/uploads",
  express.static(uploadRoot, {
    // Defense in depth alongside the upload fileFilter allow/deny-lists: never let
    // the browser execute an uploaded file as HTML/script based on sniffed content,
    // even for file types the filters didn't anticipate.
    setHeaders: (res) => res.setHeader("X-Content-Type-Options", "nosniff"),
  })
);

app.use("/api/health", healthRouter);
app.use("/api/auth", authRouter);
app.use("/api/users", usersRouter);
app.use("/api/organizations", organizationsRouter);
app.use("/api/workspaces", workspacesRouter);
app.use("/api/boards", boardsRouter);
app.use("/api/lists", listsRouter);
app.use("/api/cards", cardsRouter);
app.use("/api/labels", labelsRouter);
app.use("/api/checklists", checklistsRouter);
app.use("/api/checklist-items", checklistItemsRouter);
app.use("/api/comments", commentsRouter);
app.use("/api/attachments", attachmentsRouter);
app.use("/api/search", searchRouter);
app.use("/api/notifications", notificationsRouter);
app.use("/api/automations", automationsRouter);
app.use("/api/invitations", invitationsRouter);
app.use("/api/activity", activityRouter);
app.use("/api/drive", driveRouter);
app.use("/api/portal", portalRouter);
app.use("/api/integrations", integrationsRouter);
app.use("/api/mail", mailRouter);

// Any /api/* request that fell through every router above is a genuine 404 —
// answer with JSON, not the SPA fallback below.
app.use("/api", (_req, res) => res.status(404).json({ error: "Not found" }));

// In production the backend also serves the built frontend (single Node app,
// single origin — no separate static host or reverse proxy needed). In dev,
// Vite's own server handles the frontend, so this is skipped entirely.
if (env.NODE_ENV === "production") {
  const frontendDist = path.resolve(__dirname, "../../frontend/dist");
  app.use(express.static(frontendDist));
  app.get("*", (_req, res) => res.sendFile(path.join(frontendDist, "index.html")));
}

app.use(errorHandler);

const httpServer = createServer(app);
createSocketServer(httpServer);

httpServer.listen(env.PORT, () => {
  console.log(`API listening on http://localhost:${env.PORT}`);
  startDueDateReminderJob();
  startMailSyncJob();
});
