import { createCommand } from "@shared/lib/utils";
import { SlashCommandBuilder, PermissionFlagsBits, MessageFlags, ComponentType } from "discord.js";
import { config } from "@shared/lib/config";
import { pruneService } from "@modules/moderation/prune.service";
import {
    getConfirmationMessage,
    getProgressEmbed,
    getSuccessEmbed,
    getPruneErrorEmbed,
    getPruneWarningEmbed,
    getCancelledEmbed
} from "@/modules/moderation/prune.view";
import { withCommandErrorHandling } from "@lib/commandUtils";
import { PRUNE_CUSTOM_IDS } from "@modules/moderation/prune.types";

export const prune = createCommand({
    data: new SlashCommandBuilder()
        .setName("prune")
        .setDescription("Delete messages in bulk (admin only)")
        .addIntegerOption(option =>
            option
                .setName("amount")
                .setDescription(`Number of messages to delete (1-${config.moderation?.prune?.maxAmount || 100})`)
                .setRequired(false)
                .setMinValue(1)
                .setMaxValue(config.moderation?.prune?.maxAmount || 100)
        )
        .addUserOption(option =>
            option
                .setName("user")
                .setDescription("Only delete messages from this user")
                .setRequired(false)
        )
        .addBooleanOption(option =>
            option
                .setName("all")
                .setDescription("Delete all messages in the channel")
                .setRequired(false)
        )
        .setDefaultMemberPermissions(PermissionFlagsBits.Administrator),

    execute: async (interaction) => {
        await withCommandErrorHandling(
            interaction,
            async () => {
                const amount = interaction.options.getInteger("amount");
                const user = interaction.options.getUser("user");
                const all = interaction.options.getBoolean("all") || false;

                // Validate inputs
                if (!amount && !all) {
                    // Default to 10 messages
                } else if (amount && all) {
                    await interaction.editReply({
                        embeds: [getPruneErrorEmbed("Cannot specify both `amount` and `all`. Please use one or the other.")]
                    });
                    return;
                }

                const finalAmount = all ? 'all' : (amount || 10);
                const confirmThreshold = config.moderation.prune.confirmThreshold;

                // Check if confirmation is needed
                const needsConfirmation = all || (typeof finalAmount === 'number' && finalAmount > confirmThreshold);

                if (needsConfirmation) {
                    // Estimate message count for confirmation
                    let estimatedCount: number | undefined;
                    if (all) {
                        try {
                            estimatedCount = await pruneService.estimateMessageCount(interaction.channel!);
                        } catch {
                            estimatedCount = undefined;
                        }
                    }

                    const { embeds, components } = getConfirmationMessage(finalAmount, estimatedCount);
                    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 === PRUNE_CUSTOM_IDS.CANCEL) {
                            await confirmation.update({
                                embeds: [getCancelledEmbed()],
                                components: []
                            });
                            return;
                        }

                        // User confirmed, proceed with deletion
                        await confirmation.update({
                            embeds: [getProgressEmbed({ current: 0, total: estimatedCount || finalAmount as number })],
                            components: []
                        });

                        // Execute deletion with progress callback for 'all' mode
                        const result = await pruneService.deleteMessages(
                            interaction.channel!,
                            {
                                amount: typeof finalAmount === 'number' ? finalAmount : undefined,
                                userId: user?.id,
                                all
                            },
                            all ? async (progress) => {
                                await interaction.editReply({
                                    embeds: [getProgressEmbed(progress)]
                                });
                            } : undefined
                        );

                        // Show success
                        await interaction.editReply({
                            embeds: [getSuccessEmbed(result)],
                            components: []
                        });

                    } catch (error) {
                        if (error instanceof Error && error.message.includes("time")) {
                            await interaction.editReply({
                                embeds: [getPruneWarningEmbed("Confirmation timed out. Please try again.")],
                                components: []
                            });
                        } else {
                            throw error;
                        }
                    }
                } else {
                    // No confirmation needed, proceed directly
                    const result = await pruneService.deleteMessages(
                        interaction.channel!,
                        {
                            amount: finalAmount as number,
                            userId: user?.id,
                            all: false
                        }
                    );

                    // Check if no messages were found
                    if (result.deletedCount === 0) {
                        if (user) {
                            await interaction.editReply({
                                embeds: [getPruneWarningEmbed(`No messages found from **${user.username}** in the last ${finalAmount} messages.`)]
                            });
                        } else {
                            await interaction.editReply({
                                embeds: [getPruneWarningEmbed("No messages found to delete.")]
                            });
                        }
                        return;
                    }

                    await interaction.editReply({
                        embeds: [getSuccessEmbed(result)]
                    });
                }
            },
            { ephemeral: true }
        );
    }
});
