import { createCommand } from "@lib/utils";
import { SlashCommandBuilder, PermissionFlagsBits, MessageFlags, ComponentType } from "discord.js";
import { UpdateService } from "@/modules/admin/update.service";
import {
    getCheckingEmbed,
    getNoUpdatesEmbed,
    getUpdatesAvailableMessage,
    getPreparingEmbed,
    getUpdatingEmbed,
    getCancelledEmbed,
    getTimeoutEmbed,
    getErrorEmbed
} from "@/modules/admin/update.view";

export const update = createCommand({
    data: new SlashCommandBuilder()
        .setName("update")
        .setDescription("Check for updates and restart the bot")
        .addBooleanOption(option =>
            option.setName("force")
                .setDescription("Force update even if checks fail (not recommended)")
                .setRequired(false)
        )
        .setDefaultMemberPermissions(PermissionFlagsBits.Administrator),
    execute: async (interaction) => {
        await interaction.deferReply({ flags: MessageFlags.Ephemeral });
        const force = interaction.options.getBoolean("force") || false;

        try {
            await interaction.editReply({ embeds: [getCheckingEmbed()] });

            const { hasUpdates, log, branch } = await UpdateService.checkForUpdates();

            if (!hasUpdates && !force) {
                await interaction.editReply({ embeds: [getNoUpdatesEmbed()] });
                return;
            }

            const { embeds, components } = getUpdatesAvailableMessage(branch, log, force);
            const response = await interaction.editReply({ embeds, components });

            try {
                const confirmation = await response.awaitMessageComponent({
                    filter: (i) => i.user.id === interaction.user.id,
                    componentType: ComponentType.Button,
                    time: 30000
                });

                if (confirmation.customId === "confirm_update") {
                    await confirmation.update({
                        embeds: [getPreparingEmbed()],
                        components: []
                    });

                    // 1. Check what the update requires
                    const { needsInstall, needsMigrations } = await UpdateService.checkUpdateRequirements(branch);

                    // 2. Prepare context BEFORE update
                    await UpdateService.prepareRestartContext({
                        channelId: interaction.channelId,
                        userId: interaction.user.id,
                        timestamp: Date.now(),
                        runMigrations: needsMigrations,
                        installDependencies: needsInstall
                    });

                    // 3. Update UI to "Restarting" state
                    await interaction.editReply({ embeds: [getUpdatingEmbed(needsInstall)] });

                    // 4. Perform Update (Danger Zone)
                    await UpdateService.performUpdate(branch);

                    // 5. Trigger Restart (if we are still alive)
                    await UpdateService.triggerRestart();

                } else {
                    await confirmation.update({
                        embeds: [getCancelledEmbed()],
                        components: []
                    });
                }

            } catch (e) {
                if (e instanceof Error && e.message.includes("time")) {
                    await interaction.editReply({
                        embeds: [getTimeoutEmbed()],
                        components: []
                    });
                } else {
                    throw e;
                }
            }

        } catch (error) {
            console.error("Update failed:", error);
            await interaction.editReply({ embeds: [getErrorEmbed(error)] });
        }
    }
});
