import {
    NSQLITE_TURBOCI_ADMIN_USERS_PORTS,
    NSQLiteTables,
} from "@/src/db/types";
import {
    NormalizedServerObject,
    ParsedDeploymentServiceConfig,
    PrivateServerTtydParadigms,
    TtydInfoObject,
    User,
} from "@/src/types";
import grabDirNames from "@/src/utils/grab-dir-names";
import getNextAvailablePort from "@/src/utils/grab-next-available-port";
import grabSSHPrefix from "@/src/utils/grab-ssh-prefix";
import grabTtydCmd from "@/src/utils/grab-ttyd-cmd";
import grabConnectedWebsocketUserdata from "@/src/websocket/(utils)/grab-connected-websocket-user-data";
import BunSQLite from "@moduletrace/bun-sqlite";
import { exec } from "child_process";

const { TURBOCI_SSH_KEY_FILE } = grabDirNames();

type Params = {
    user: User;
    service?: Omit<ParsedDeploymentServiceConfig, "servers">;
    server?: NormalizedServerObject;
    paradigm: (typeof PrivateServerTtydParadigms)[number]["name"];
    cmd?: string;
};

export default async function grabTtydServerInfo({
    server,
    service,
    user,
    paradigm,
    cmd: passed_log_cmd,
}: Params): Promise<TtydInfoObject> {
    const first_log = service?.logs?.[0];
    const final_first_log =
        typeof first_log == "string" ? first_log : first_log?.cmd;

    const final_log = passed_log_cmd || final_first_log;

    if (paradigm == "logs" && !final_log) {
        throw new Error(
            `Service \`${service?.service_name}\` Doesn't have logs.`,
        );
    }

    const available_port = await getNextAvailablePort();

    let url = `/ttyd/${available_port}`;

    let cmd = ``;

    cmd += ` ${grabSSHPrefix()}`;

    // if (paradigm == "logs") {
    // } else {
    //     cmd += ` ssh -i ${TURBOCI_SSH_KEY_FILE}`;
    // }

    cmd += ` root@${server?.private_ip}`;

    if (paradigm == "logs" && final_log) {
        cmd += ` ${final_log}`;
    }

    const ttyd_cmd = grabTtydCmd({
        cmd,
        port: available_port,
    });

    const ttyd_exec = exec(ttyd_cmd.cmd);

    await Bun.sleep(2000);

    const connected_user_data = grabConnectedWebsocketUserdata({ user });

    await BunSQLite.insert<
        NSQLITE_TURBOCI_ADMIN_USERS_PORTS,
        (typeof NSQLiteTables)[number]
    >({
        data: [{ user_id: user.id, port: available_port }],
        table: "users_ports",
    });

    connected_user_data.child_processes.push(ttyd_exec);
    connected_user_data.ports.push(available_port);

    return { port: available_port, url };
}
