import compression from "compression";
import express from "express";
import type { Express, Request, Response, NextFunction } from "express";
import morgan from "morgan";
import { createServer } from "http";
import type { ViteDevServer } from "vite";
import path from "path";
import { fileURLToPath } from "url";
import { drizzle } from "drizzle-orm/postgres-js";
import { migrate } from "drizzle-orm/postgres-js/migrator";
import postgres from "postgres";
import { logger } from "./server/logger";

// ESM module resolution helpers
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

// Configuration
// Resolve paths relative to project root (one level up from dist/ in production, or current dir in dev)
const PROJECT_ROOT = path.resolve(__dirname, "..");
const BUILD_PATH = path.join(PROJECT_ROOT, "build/server/index.js");
const CLIENT_BUILD_PATH = path.join(PROJECT_ROOT, "build/client");
const CLIENT_ASSETS_PATH = path.join(PROJECT_ROOT, "build/client/assets");
const DEVELOPMENT = process.env.NODE_ENV === "development";
const PORT = Number.parseInt(process.env.PORT || "3000", 10);

async function runMigrations(): Promise<void> {
  if (!process.env.DATABASE_URL) {
    throw new Error("DATABASE_URL is required");
  }
  const client = postgres(process.env.DATABASE_URL);
  try {
    const db = drizzle(client);
    await migrate(db, { migrationsFolder: path.join(PROJECT_ROOT, "drizzle") });
    logger.log("Migrations complete");
  } finally {
    await client.end();
  }
}

async function createAppServer(): Promise<void> {
  const app: Express = express();
  
  app.use(compression());
  app.disable("x-powered-by");

  if (DEVELOPMENT) {
    logger.log("Starting development server");
    
    // Dynamic import Vite only in development
    const { createServer: createViteServer } = await import("vite");
    
    const viteDevServer: ViteDevServer = await createViteServer({
      server: { middlewareMode: true },
    });
    
    app.use(viteDevServer.middlewares);
    
    app.use(async (req: Request, res: Response, next: NextFunction) => {
      try {
        const source = await viteDevServer.ssrLoadModule("./server/app.ts");
        return await source.app(req, res, next);
      } catch (error) {
        if (error instanceof Error) {
          viteDevServer.ssrFixStacktrace(error);
        }
        next(error);
      }
    });
  } else {
    logger.log("Starting production server");
    
    app.use(
      "/assets",
      express.static(CLIENT_ASSETS_PATH, { 
        immutable: true, 
        maxAge: "1y" 
      })
    );
    
    app.use(morgan("tiny"));
    app.use(express.static(CLIENT_BUILD_PATH, { maxAge: "1h" }));
    
    // Import the built React Router app
    const { app: productionApp } = await import(BUILD_PATH);
    app.use(productionApp);
  }

  // Create HTTP server
  const httpServer = createServer(app);

  // Initialize Socket.IO
  const { initializeSocketIO } = await import("./server/socket");
  initializeSocketIO(httpServer);

  // Start server
  httpServer.listen(PORT, () => {
    logger.log(`Server is running on http://localhost:${PORT}`);
  });
}

// Start the server with error handling
(DEVELOPMENT ? Promise.resolve() : runMigrations())
  .then(createAppServer)
  .catch((error) => {
    logger.error("Failed to start server:", error);
    process.exit(1);
  });
