import "dotenv/config";
import express from "express";
import cors from "cors";
import helmet from "helmet";
import path from "path";
import { fileURLToPath } from "url";
import logger from "./utils/logger.js";
import requestLogger from "./middleware/requestLogger.js";
import { connectDB, checkDBHealth } from "./config/database.js";
import authRoutes from "./routes/authRoutes.js";
import projectRoutes from "./routes/projectRoutes.js";

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

const app = express();
const PORT = process.env.PORT || 3000;

// Set up error handlers FIRST before anything else
// This ensures all errors are caught and converted to strings
process.on("uncaughtException", (error) => {
  try {
    const errorMessage = error instanceof Error ? error.message : String(error);
    const errorStack = error instanceof Error ? error.stack : undefined;

    // Use console.error directly to avoid circular issues
    console.error(`Uncaught Exception: ${errorMessage}`);
    if (errorStack) {
      console.error(`Stack trace: ${errorStack}`);
    }

    // Try to use logger if available
    try {
      if (logger && typeof logger.error === "function") {
        logger.error(`Uncaught Exception: ${errorMessage}`);
        if (errorStack) {
          logger.error(`Stack trace: ${errorStack}`);
        }
      }
    } catch (logError) {
      // Ignore logger errors
    }

    // Exit process after logging
    process.exit(1);
  } catch (handlerError) {
    // Last resort - just exit
    console.error("Fatal error in error handler");
    process.exit(1);
  }
});

// Handle unhandled promise rejections
process.on("unhandledRejection", (reason, promise) => {
  try {
    let errorMessage = "Unhandled Promise Rejection";
    let errorStack = undefined;

    if (reason instanceof Error) {
      errorMessage = reason.message;
      errorStack = reason.stack;
    } else if (typeof reason === "object" && reason !== null) {
      try {
        errorMessage = JSON.stringify(reason);
      } catch (e) {
        errorMessage = String(reason);
      }
    } else {
      errorMessage = String(reason);
    }

    // Use console.error directly
    console.error(`Unhandled Rejection: ${errorMessage}`);
    if (errorStack) {
      console.error(`Stack trace: ${errorStack}`);
    }

    // Try to use logger if available
    try {
      if (logger && typeof logger.error === "function") {
        logger.error(`Unhandled Rejection: ${errorMessage}`);
        if (errorStack) {
          logger.error(`Stack trace: ${errorStack}`);
        }
      }
    } catch (logError) {
      // Ignore logger errors
    }
  } catch (handlerError) {
    // Ignore errors in handler
  }
});

// Middleware
app.use(helmet()); // Security headers
app.use(
  cors({
    origin: "*",
    methods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
    allowedHeaders: ["Content-Type", "Authorization"],
    credentials: true,
  })
); // Enable CORS
app.use(express.json()); // Parse JSON bodies
app.use(express.urlencoded({ extended: true })); // Parse URL-encoded bodies
app.use(requestLogger); // Custom request/response logger

// Serve static files (uploaded images)
app.use("/uploads", express.static(path.join(__dirname, "../uploads")));

// Health check route
app.get("/", (req, res) => {
  try {
    const dbHealth = checkDBHealth();
    res.status(200).json({
      status: "OK",
      message: "Server is running",
      timestamp: new Date().toISOString(),
      database: dbHealth,
    });
  } catch (error) {
    const errorMsg = error instanceof Error ? error.message : String(error);
    res.status(500).json({
      status: "ERROR",
      message: "Server error",
      error: errorMsg,
    });
  }
});

// Health check endpoint
app.get("/health", (req, res) => {
  try {
    const dbHealth = checkDBHealth();
    const isHealthy = dbHealth.isConnected;

    res.status(isHealthy ? 200 : 503).json({
      status: isHealthy ? "healthy" : "unhealthy",
      timestamp: new Date().toISOString(),
      uptime: process.uptime(),
      database: dbHealth,
    });
  } catch (error) {
    const errorMsg = error instanceof Error ? error.message : String(error);
    res.status(500).json({
      status: "error",
      error: errorMsg,
    });
  }
});

// API routes
app.get("/api", (req, res) => {
  res.json({
    message: "Welcome to Samaa Backend API",
    version: "1.0.0",
  });
});

// Authentication routes
app.use("/api/auth", authRoutes);

// Project routes
app.use("/api/projects", projectRoutes);

// 404 handler
app.use((req, res) => {
  res.status(404).json({
    error: "Route not found",
    path: req.path,
  });
});

// Error handler
app.use((err, req, res, next) => {
  try {
    const errorMsg = err instanceof Error ? err.message : String(err);
    const errorStack = err instanceof Error ? err.stack : undefined;

    // Log error
    try {
      if (logger && typeof logger.error === "function") {
        logger.error("Request error", err);
      } else {
        console.error(`Request error: ${errorMsg}`);
        if (errorStack) {
          console.error(`Stack: ${errorStack}`);
        }
      }
    } catch (logError) {
      console.error(`Request error: ${errorMsg}`);
    }

    // Send error response
    res.status(err.status || 500).json({
      error: errorMsg,
      ...(process.env.NODE_ENV === "development" &&
        errorStack && { stack: errorStack }),
    });
  } catch (handlerError) {
    // Last resort error handler
    const handlerErrorMsg =
      handlerError instanceof Error
        ? handlerError.message
        : String(handlerError);
    res.status(500).json({
      error: "Internal Server Error",
      details: handlerErrorMsg,
    });
  }
});

// Initialize database connection and start server
const startServer = async () => {
  try {
    // Connect to database
    if (process.env.MONGODB_URI) {
      await connectDB();
      if (logger && typeof logger.info === "function") {
        logger.info("✅ Database connection initialized");
      } else {
        console.log("✅ Database connection initialized");
      }
    } else {
      if (logger && typeof logger.warn === "function") {
        logger.warn("⚠️  MONGODB_URI not set. Database connection skipped.");
      } else {
        console.warn("⚠️  MONGODB_URI not set. Database connection skipped.");
      }
    }

    // Start server
    const server = app.listen(PORT, () => {
      try {
        if (logger && typeof logger.info === "function") {
          logger.info(`🚀 Server is running on port ${PORT}`);
          logger.info(
            `📍 Environment: ${process.env.NODE_ENV || "development"}`
          );
          logger.info(`🌐 Health check: http://localhost:${PORT}/health`);
          logger.info(
            `📝 Logging level: ${
              process.env.LOG_LEVEL ||
              (process.env.NODE_ENV === "production" ? "INFO" : "DEBUG")
            }`
          );
          if (process.env.LOG_TO_FILE === "true") {
            logger.info(`📁 File logging enabled: logs/`);
          }
        } else {
          console.log(`🚀 Server is running on port ${PORT}`);
          console.log(
            `📍 Environment: ${process.env.NODE_ENV || "development"}`
          );
          console.log(`🌐 Health check: http://localhost:${PORT}/health`);
        }
      } catch (logError) {
        // Fallback to console if logger fails
        const errorMsg =
          logError instanceof Error ? logError.message : String(logError);
        console.error(`Failed to log server start: ${errorMsg}`);
      }
    });

    server.on("error", (error) => {
      try {
        const errorMsg = error instanceof Error ? error.message : String(error);
        const errorStack = error instanceof Error ? error.stack : undefined;

        if (logger && typeof logger.error === "function") {
          logger.error(`Server failed to start: ${errorMsg}`);
          if (errorStack) {
            logger.error(`Stack trace: ${errorStack}`);
          }
        } else {
          console.error(`Server failed to start: ${errorMsg}`);
          if (errorStack) {
            console.error(`Stack trace: ${errorStack}`);
          }
        }
      } catch (logError) {
        console.error(`Server failed to start: ${String(error)}`);
      }
      process.exit(1);
    });
  } catch (error) {
    try {
      const errorMsg = error instanceof Error ? error.message : String(error);
      const errorStack = error instanceof Error ? error.stack : undefined;

      if (logger && typeof logger.error === "function") {
        logger.error("Failed to start server", error);
      } else {
        console.error(`Failed to start server: ${errorMsg}`);
        if (errorStack) {
          console.error(`Stack trace: ${errorStack}`);
        }
      }
    } catch (logError) {
      console.error(`Failed to start server: ${String(error)}`);
    }
    process.exit(1);
  }
};

// Wrap startup in try-catch to catch any synchronous errors
try {
  // Start the application
  startServer().catch((error) => {
    try {
      const errorMsg = error instanceof Error ? error.message : String(error);
      console.error(`Failed to start server (async): ${errorMsg}`);
      if (error instanceof Error && error.stack) {
        console.error(`Stack: ${error.stack}`);
      }
    } catch (handlerError) {
      console.error("Fatal error during startup");
    }
    process.exit(1);
  });
} catch (error) {
  try {
    const errorMsg = error instanceof Error ? error.message : String(error);
    console.error(`Failed to start server (sync): ${errorMsg}`);
    if (error instanceof Error && error.stack) {
      console.error(`Stack: ${error.stack}`);
    }
  } catch (handlerError) {
    console.error("Fatal error");
  }
  process.exit(1);
}

export default app;
