import express from "express";
import dotenv from "dotenv";
import { AppDataSource } from "./data-source.js";
import { authentication } from "./middleware/authenticationMiddleware.js";
import { requestLoggerMiddleware } from "./middleware/requestLoggerMiddleware.js";
import { errorLoggerMiddleware } from "./middleware/errorLoggerMiddleware.js";
import { corsHeaders } from "./middleware/corsMiddleware.js";
import { logger } from "./utils/logger.js";
import { HttpStatusCode } from "./api/apiHelpers/HttpStatusCodes.js";
import authRoutes, { authBasicRoute } from "./api/endpoints/AuthRestResource.js";
import userRoutes, { userBasicRoute } from "./api/endpoints/UserRestResource.js";
import compactRecipeRoutes, {compactRecipeBasicRoute} from "./api/endpoints/CompactRecipeRestResource.js";
import recipeRoutes, {recipeBasicRoute} from "./api/endpoints/RecipeRestResource.js";
import tagRoutes, {tagBasicRoute} from "./api/endpoints/TagRestResource.js";

dotenv.config();

const app = express();

async function startServer() {
    try {
        logger.info("Starting server...");

        // Initialize database
        await AppDataSource.initialize();
        logger.info("Database connection established");

        // Run pending migrations
        if (AppDataSource.migrations.length > 0) {
            await AppDataSource.runMigrations();
            logger.info("Migrations executed");
        }

        // Body parser middleware
        app.use(express.json());
        app.use(express.urlencoded({ extended: true }));

        // Enable CORS
        app.use(corsHeaders);

        // Request logging - logs all incoming requests
        app.use(requestLoggerMiddleware);

        // Authentication
        app.use(authentication);

        // Setup routes
        app.use(authBasicRoute, authRoutes);
        app.use(userBasicRoute, userRoutes);
        app.use(recipeBasicRoute, recipeRoutes);
        app.use(compactRecipeBasicRoute, compactRecipeRoutes);
        app.use(tagBasicRoute,tagRoutes)

        // Catch-all for unknown routes
        app.use((req, res) => {
            logger.warn(`Unknown route accessed: ${req.method} ${req.originalUrl}`);
            res.status(HttpStatusCode.NOT_FOUND).json({
                statusCode: HttpStatusCode.NOT_FOUND,
                error: "Route not found"
            });
        });

        // Error logging and handling - MUST be last
        app.use(errorLoggerMiddleware);

        // Start listening
        const PORT = Number(process.env.PORT) || 4000;
        const HOST = process.env.HOST || "localhost";

        app.listen(PORT, HOST, () => {
            logger.info(`Server running on http://${HOST}:${PORT}`);
            logger.info(`Environment: ${process.env.NODE_ENV || "development"}`);
        });
    } catch (err) {
        logger.error("Error during server initialization:", err);
        process.exit(1);
    }
}

// Handle uncaught exceptions
process.on("uncaughtException", (error) => {
    logger.error("Uncaught Exception:", { error });
    process.exit(1);
});

// Handle unhandled promise rejections
process.on("unhandledRejection", (reason, promise) => {
    logger.error("Unhandled Rejection:", { promise, reason });
    process.exit(1);
});

// Start the server
startServer();

export default app;