import express, { type Request, Response, NextFunction } from "express";
import { registerRoutes } from "./routes";
import { setupVite, serveStatic, log } from "./vite";
import { startRTMPServer as startRTMP } from "./rtmp-server";
import cors from "cors";

const app = express();

app.use(
  cors({
    origin: "*", // Allow all origins
    credentials: true,
    methods: ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"],
    allowedHeaders: [
      "Content-Type",
      "Authorization",
      "X-Requested-With",
      "Accept",
      "Origin",
      "Access-Control-Allow-Origin",
      "Access-Control-Allow-Headers",
      "Access-Control-Allow-Methods",
      "Access-Control-Allow-Credentials",
      "x-flutter-mode",
      "flutter-platform",
      "user-agent",
    ],
    exposedHeaders: ["Set-Cookie"],
  }),
);

// Additional headers middleware
app.use((req, res, next) => {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Credentials", "true");
  res.header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
  res.header(
    "Access-Control-Allow-Headers",
    "Origin, X-Requested-With, Content-Type, Accept, Authorization",
  );

  if (req.method === "OPTIONS") {
    return res.status(200).json({});
  }

  next();
});

// Body parser configuration with increased limits
app.use(express.json({ limit: "50mb" }));
app.use(express.urlencoded({ extended: true, limit: "50mb" }));

// Request logging middleware
app.use((req, res, next) => {
  const start = Date.now();
  const path = req.path;
  let capturedJsonResponse: Record<string, any> | undefined = undefined;

  const originalResJson = res.json;
  res.json = function (bodyJson, ...args) {
    capturedJsonResponse = bodyJson;
    return originalResJson.apply(res, [bodyJson, ...args]);
  };

  res.on("finish", () => {
    const duration = Date.now() - start;
    if (path.startsWith("/api")) {
      let logLine = `${req.method} ${path} ${res.statusCode} in ${duration}ms`;
      if (capturedJsonResponse) {
        logLine += ` :: ${JSON.stringify(capturedJsonResponse)}`;
      }

      if (logLine.length > 80) {
        logLine = logLine.slice(0, 79) + "…";
      }

      log(logLine);
    }
  });

  next();
});

// Startup sequence
(async () => {
  try {
    log("Starting server initialization...");
    const isProduction = process.env.NODE_ENV === "production";
    const port = 5000;

    log(`Environment: ${isProduction ? "production" : "development"}`);
    log(`Configured port: ${port}`);

    const server = await registerRoutes(app);
    log("✅ Routes registered successfully");

    // Error handling middleware
    app.use((err: any, _req: Request, res: Response, _next: NextFunction) => {
      console.error("Server error:", err);
      const status = err.status || err.statusCode || 500;
      const message = err.message || "Internal Server Error";
      res.status(status).json({ message });
    });

    if (isProduction) {
      log("Production mode detected, serving static files...");
      serveStatic(app);
      log("✅ Static files setup completed");
    } else {
      log("Setting up Vite development server...");
      await setupVite(app, server);
      log("✅ Vite setup completed");
    }

    log(`Attempting to start server on port ${port}...`);

    await new Promise<void>((resolve, reject) => {
      server
        .listen(
          {
            port,
            host: "0.0.0.0",
          },
          () => {
            log(`✅ Server running at http://0.0.0.0:${port}`);
            resolve();
          },
        )
        .on("error", (error) => {
          console.error("❌ Server failed to start:", error);
          reject(error);
        });
    });

    if (!isProduction || process.env.ENABLE_RTMP === "true") {
      const rtmpStarted = startRTMP();
      if (rtmpStarted) {
        log("✅ RTMP Server started successfully");
      } else {
        log("❌ Failed to start RTMP server");
      }
    }
  } catch (error) {
    console.error("❌ Failed to start server:", error);
    process.exit(1);
  }
})().catch((error) => {
  console.error("❌ Unhandled startup error:", error);
  process.exit(1);
});
