import {adminId, SubcommandData} from "../types"
import {
    ActivityType,
    ApplicationCommandOptionType,
    ApplicationCommandSubCommandData,
    ChatInputCommandInteraction,
} from "discord.js"
import {wrappedRestart} from "../../ipc/restart"
import {fork} from "child_process"
import {defaultPresence} from "../../defaultPresence"
import {resolve as resolvePath} from "path"

class RebuildCommand extends SubcommandData {
    readonly definition: ApplicationCommandSubCommandData = {
        name: "rebuild",
        description: "Rebuilds and restarts the bot.",
        type: ApplicationCommandOptionType.Subcommand,
    }

    async execute(b: ChatInputCommandInteraction): Promise<void> {
        const user = b.user || b.member
        if (!!user && user.id === adminId) {
            await b.reply({
                content: "I dunno... Let's check if this will work...",
                ephemeral: true,
            })
            const self = b.client.user
            self.setPresence({
                status: "online",
                afk: false,
                activities: [
                    {
                        type: ActivityType.Playing,
                        name: "A Test of Your Codes",
                    },
                ],
            })
            try {
                await new Promise<void>((resolve, reject) => {
                    const result = fork(resolvePath("./node_modules/jest-cli/bin/jest"), {
                        execPath: process.execPath,
                        execArgv: process.execArgv,
                        cwd: process.cwd(),
                        stdio: "inherit",
                        detached: true,
                    })
                    result.disconnect()

                    result.on("error", (ex) => {
                        reject(ex)
                    })
                    result.on("exit", (code) => {
                        if (code !== 0) {
                            reject(`Bad exit code ${code}`)
                        } else {
                            resolve()
                        }
                    })
                })
            } catch (ex) {
                console.log(ex)
                self.setPresence(defaultPresence)
                await b.followUp({
                    content: "Oh no... It's not working... Oh well...",
                    ephemeral: true,
                })
                return
            }
            await b.followUp({
                content: "Mmm... let's see... this goes here...",
                ephemeral: true,
            })
            self.setPresence({
                status: "online",
                afk: false,
                activities: [
                    {
                        type: ActivityType.Watching,
                        name: "Compilers at Work",
                    },
                ],
            })
            try {
                await new Promise<void>((resolve, reject) => {
                    const result = fork(resolvePath("./node_modules/typescript/bin/tsc"), {
                        execPath: process.execPath,
                        execArgv: process.execArgv,
                        cwd: process.cwd(),
                        stdio: "inherit",
                        detached: true,
                    })
                    result.disconnect()
                    result.on("error", (ex) => {
                        reject(ex)
                    })
                    result.on("exit", (code) => {
                        if (code !== 0) {
                            reject(`Bad exit code ${code}`)
                        } else {
                            resolve()
                        }
                    })
                })
            } catch (ex) {
                console.log(ex)
                self.setPresence(defaultPresence)
                await b.followUp({
                    ephemeral: true,
                    content: "I dunno... how to fit these together....",
                })
                return
            }
            await b.followUp({
                content: "Hmm hmm~ Annnd some gluuue...",
                ephemeral: true,
            })
            try {
                await new Promise<void>((resolve, reject) => {
                    const result = fork(resolvePath("./node_modules/@babel/cli/bin/babel"),
                        ["src", "--out-dir", "build", "--extensions", ".ts"], {
                            execPath: process.execPath,
                            execArgv: process.execArgv,
                            cwd: process.cwd(),
                            stdio: "inherit",
                            detached: true,
                        })
                    result.disconnect()
                    result.on("error", (ex) => {
                        reject(ex)
                    })
                    result.on("exit", (code) => {
                        if (code !== 0) {
                            reject(`Bad exit code ${code}`)
                        } else {
                            resolve()
                        }
                    })
                })
            } catch (ex) {
                console.log(ex)
                self.setPresence(defaultPresence)
                await b.followUp({
                    ephemeral: true,
                    content: "Oops... I think it's broken... Sowwy...",
                })
                return
            }
            self.setPresence({
                status: "idle",
                afk: true,
                activities: [
                    {
                        type: ActivityType.Listening,
                        name: "Born-Again Bot Girl",
                    },
                ],
            })
            await b.followUp({
                ephemeral: true,
                content: "Phewwww... now I'll just... take a quick nap after all that hard work...",
            })
            await wrappedRestart(b)
        } else {
            await b.reply({
                ephemeral: true,
                content: "Heeey... I don't gotta do what you say...",
            })
        }
    }
}

export const commandBotRebuild = new RebuildCommand()