import express from "express";
import morgan from "morgan";
import { createServer } from "http";
import { setupRoutes } from "./src/internal/routerHandler/routeHandler.js";
import { printers } from "./src/internal/ocp/printers/printers.js";
import { dirname, join } from "path";
import { fileURLToPath } from "url";
import { db } from "./src/pkg/db/db.js";
import { settings } from "./src/pkg/db/schema/settings.js";
import { validateEnv } from "./src/pkg/utils/envValidator.js";
import { createLogger } from "./src/pkg/logger/logger.js";
import { returnFunc } from "./src/pkg/utils/return.js";
import { initializeProdPool } from "./src/pkg/prodSql/prodSqlConnect.js";
import { tryCatch } from "./src/pkg/utils/tryCatch.js";
import os from "os";
import cors from "cors";
import { sendNotify } from "./src/pkg/utils/notify.js";
import { toNodeHandler } from "better-auth/node";
import { auth } from "./src/pkg/auth/auth.js";

const main = async () => {
    const env = validateEnv(process.env);
    const PORT = Number(env.VITE_PORT) || 4200;
    //create the logger
    const log = createLogger({ module: "system", subModule: "main start" });

    // base path
    let basePath: string = "";

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

    // Db connection stuff
    const res = await tryCatch(db.select().from(settings));

    if (res.error) {
        return returnFunc({
            success: false,
            module: "system",
            level: "fatal",
            message: `Database lookup failed`,
            notify: false,
            data: [],
        });
    }

    if (res.data.length === 0) {
        //return
        // returnFunc({
        //     success: false,
        //     module: "system",
        //     level: "fatal",
        //     message: `This seems to be the first time you have started the app please validate the settings have been intiated`,
        //     notify: false,
        //     data: [],
        // });
    }

    // connect to the prod sql
    await initializeProdPool();

    // express app
    const app = express();

    // global env that run only in dev
    if (process.env.NODE_ENV?.trim() !== "production") {
        app.use(morgan("tiny"));
        basePath = "/lst";

        app.use(
            basePath + "/test",
            express.static(join(__dirname, "../controller"))
        );
    }

    // global middleware
    app.all(basePath + "/api/auth/*splat", toNodeHandler(auth)); // sign-in sign-out
    app.use(express.json());

    const allowedOrigins = [
        "http://localhost:5173", // dev
        "http://localhost:4200",
        env.BETTER_AUTH_URL, // prod
    ];

    app.use(
        cors({
            origin: (origin, callback) => {
                // allow requests with no origin (like curl, service workers, PWAs)
                if (!origin) return callback(null, true);

                if (allowedOrigins.includes(origin)) {
                    return callback(null, true);
                } else {
                    return callback(new Error("Not allowed by CORS"));
                }
            },
            methods: ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"],
            credentials: true,
        })
    );

    // docs and api stuff
    app.use(
        basePath + "/d",
        express.static(join(__dirname, "../lstDocs/build"))
    );
    app.use(
        basePath + "/app",
        express.static(join(__dirname, "../frontend/dist"))
    );

    // register app
    setupRoutes(app, basePath);

    // ws stuff

    // ws + server stuff
    const server = createServer(app);

    // sub systems
    printers();

    // start the server up
    server.listen(PORT, "0.0.0.0", () =>
        log.info(
            { stack: { name: "test" } },
            `Server running in ${
                process.env.NODE_ENV ? process.env.NODE_ENV : "dev"
            }, on http://0.0.0.0:${PORT}${basePath}`
        )
    );

    process.on("uncaughtException", async (err) => {
        //console.log("Uncaught Exception:", err);
        // await closePool();
        // const emailData = {
        //     email: "blake.matthes@alpla.com", // should be moved to the db so it can be reused.
        //     subject: `${os.hostname()} has just encountered a crash.`,
        //     template: "serverCrash",
        //     context: {
        //         error: err,
        //         plant: `${os.hostname()}`,
        //     },
        // };

        if (!process.env.WEBHOOK_URL) {
            // await sendEmail(emailData);
        } else {
            log.fatal({ stack: err.stack }, err.message);
            await sendNotify({
                module: "system",
                subModule: "fatalCrash",
                hostname: os.hostname(),
                message: err.message,
                stack: err?.stack,
            });
        }

        //process.exit(1);
    });

    // setInterval(() => {
    //     const used = process.memoryUsage();
    //     console.log(
    //         `Heap: ${(used.heapUsed / 1024 / 1024).toFixed(2)} MB / RSS: ${(
    //             used.rss /
    //             1024 /
    //             1024
    //         ).toFixed(2)} MB`
    //     );
    // }, 10000);
};

main();
