import { spawn } from "child_process";
import { getAppInfo } from "../globalUtils/appInfo.js";
import { db } from "../../database/dbclient.js";
import { serverData } from "../../database/schema/serverData.js";
import { eq, sql } from "drizzle-orm";
import { createLog } from "../services/logger/logger.js";
import { serverSettings } from "../services/server/controller/settings/getSettings.js";

type UpdateServerResponse = {
    success: boolean;
    message: string;
};

export const updateServer = async (
    devApp: string,
    server: string | null,
    all?: boolean | null
): Promise<UpdateServerResponse> => {
    const app = await getAppInfo(devApp);
    const serverInfo = await db
        .select()
        .from(serverData)
        .where(eq(serverData.plantToken, server?.toLowerCase() ?? ""));

    if (serverInfo.length === 0) {
        createLog(
            "error",
            "lst",
            "serverUpdater",
            `Looks like you are missing the plant token or have entered an incorrect one please try again.`
        );
        return {
            success: false,
            message:
                "Looks like you are missing the plant token or have entered an incorrect one please try again.",
        };
    }

    if (serverInfo[0].isUpgrading && !all) {
        createLog(
            "error",
            "lst",
            "serverUpdater",
            `Looks like ${serverInfo[0].plantToken} is upgrading already you cant do this again.`
        );
        return {
            success: false,
            message: `Looks like ${serverInfo[0].plantToken} is upgrading already you cant do this again.`,
        };
    }

    console.log(serverInfo);
    const scriptPath = `${process.env.DEVFOLDER}\\server\\scripts\\update.ps1 `;
    const args = [
        "-NoProfile",
        "-ExecutionPolicy",
        "Bypass",
        "-File",
        scriptPath,
        "-username",
        process.env.ADMUSER, // needs moved to somewhere else.
        "-admpass",
        process.env.ADMPASSWORD, // needs moved to somewhere else.
        "-devFolder",
        process.env.DEVFOLDER,
        "-server",
        serverInfo[0].serverDNS,
        "-serverIP",
        serverInfo[0].idAddress,
        "-token",
        serverInfo[0].plantToken,
        "-build",
        `${process.env.DEVFOLDER}\\builds`,
        "-location",
        serverInfo[0].serverLoc,
        "-obslst",
        serverInfo[0].oldVersion,
        "-obsBuild",
        app.admConfig.oldBuild,
        ,
    ];

    return new Promise(async (resolve, reject) => {
        const process = spawn("powershell", args);
        // change the server to upgradeing
        await db
            .update(serverData)
            .set({ isUpgrading: true })
            .where(eq(serverData.plantToken, server?.toLowerCase() ?? ""));
        //let stdout = "";
        //let stderr = "";

        // Collect stdout data
        process.stdout.on("data", (data) => {
            const output = data.toString().trim();
            createLog("info", "lst", "serverUpdater", `${output}`);
            //onData(output);
        });

        // Collect stderr data
        process.stderr.on("data", (data) => {
            const output = data.toString().trim();
            createLog("info", "lst", "serverUpdater", `${output}`);
            //onData(output);
        });

        // Handle process close
        process.on("close", async (code) => {
            if (code === 0) {
                // if (count >= servers) {
                //     //onClose(`Server completed with code: ${code}`);
                // }
                createLog("info", "lst", "serverUpdater", `${server}`);

                //update the last build.
                try {
                    await db
                        .update(serverData)
                        .set({ lastUpdated: sql`NOW()`, isUpgrading: false })
                        .where(
                            eq(
                                serverData.plantToken,
                                server?.toLowerCase() ?? ""
                            )
                        );
                    createLog(
                        "info",
                        "lst",
                        "serverUpdater",
                        `${server?.toLowerCase()}, has been updated and can now be used again.`
                    );
                } catch (error) {
                    createLog(
                        "error",
                        "lst",
                        "serverUpdater",
                        `There was an error updating the last time the server was updated: ${error}`
                    );
                }

                resolve({
                    success: true,
                    message: `${server?.toLowerCase()}, has been updated and can now be used again.`,
                });
            } else {
                const errorMessage = `Process exited with code ${code}`;

                // if (count >= servers) {
                //     //onClose(code);
                // }

                reject({
                    success: false,
                    message: `${server?.toLowerCase()}, Has encounted an error while updating.`,
                });
            }
        });

        // Handle errors with the process itself
        process.on("error", (error) => {
            //onError(err.message);
            createLog("error", "lst", "serverUpdater", `${error}`);
            reject(error);
        });
    });
};

export async function processAllServers(devApp: string) {
    const servers = await db.select().from(serverData);

    //change all servers to be upgrading
    await db.update(serverData).set({ isUpgrading: true });

    createLog(
        "info",
        "lst",
        "serverUpdater",
        `Running the update on all servers`
    );
    let count = 1;
    for (const server of servers) {
        try {
            const updateToServer = await updateServer(
                devApp,
                server.plantToken,
                true
            );
            createLog(
                "info",
                "lst",
                "serverUpdater",
                `${server.sName} was updated.`
            );
            count = count + 1;

            // return {
            //     success: true,
            //     message: `${server.sName} was updated.`,
            //     data: updateToServer,
            // };
        } catch (error: any) {
            createLog(
                "info",
                "lst",
                "serverUpdater",
                `Error updating ${server.sName}: ${error.message}`
            );
            // return {
            //     success: false,
            //     message: `Error updating ${server.sName}: ${error.message}`,
            // };
        }
    }

    return {
        success: true,
        message: `All Servers are being updated this will take some time.`,
    };
}
