import { ButtonInteraction, TextInputBuilder } from "discord.js";
import Discord, {
    CommandInteraction,
    Message,
    ActionRowBuilder,
    ButtonBuilder,
    ModalSubmitInteraction,
    ButtonStyle,
    TextInputStyle
} from "discord.js";
import { modalInteractionCollector } from "./dualCollector.js";
import EmojiEmbed from "./generateEmojiEmbed.js";
import getEmojiByName from "./getEmojiByName.js";

interface CustomBoolean<T> {
    title: string;
    disabled: boolean;
    value: string | null;
    notValue: string | null;
    emoji: string | undefined;
    active: boolean;
    onClick: () => Promise<T>;
    response: T | null;
}

class confirmationMessage {
    interaction: CommandInteraction | ButtonInteraction;
    title = "";
    emoji = "";
    redEmoji: string | null = null;
    failedMessage: string | null = null;
    failedEmoji: string | null = null;
    failedStatus: "Success" | "Danger" | "Warning" | null = null;
    description = "";
    color: "Danger" | "Warning" | "Success" = "Success";
    customButtons: Record<string, CustomBoolean<unknown>> = {};
    inverted = false;
    reason: string | null = null;

    modals: {
        buttonText: string;
        emoji: string;
        customId: string;
        modal: Discord.ModalBuilder;
        value: string | undefined;
    }[] = [];

    constructor(interaction: CommandInteraction | ButtonInteraction) {
        this.interaction = interaction;
    }

    setTitle(title: string) {
        this.title = title;
        return this;
    }
    setEmoji(emoji: string) {
        this.emoji = emoji;
        return this;
    }
    setDescription(description: string, timedOut?: string) {
        this.description = description;
        if (timedOut) this.failedMessage = timedOut;
        return this;
    }
    setColor(color: "Danger" | "Warning" | "Success") {
        this.color = color;
        return this;
    }
    setInverted(inverted: boolean) {
        this.inverted = inverted;
        return this;
    }
    setFailedMessage(
        text: string,
        failedStatus: "Success" | "Danger" | "Warning" | null,
        failedEmoji: string | null = null
    ) {
        this.failedMessage = text;
        this.failedStatus = failedStatus;
        this.failedEmoji = failedEmoji;
        return this;
    }
    addCustomBoolean(
        customId: string,
        title: string,
        disabled: boolean,
        callback: (() => Promise<unknown>) | null = async () => null,
        callbackClicked: string | null,
        callbackNotClicked: string | null,
        emoji?: string,
        initial?: boolean
    ) {
        this.customButtons[customId] = {
            title: title,
            disabled: disabled,
            value: callbackClicked,
            notValue: callbackNotClicked,
            emoji: emoji,
            active: initial ?? false,
            onClick: callback ?? (async () => null),
            response: null
        };
        return this;
    }
    addReasonButton(reason: string) {
        this.reason = reason;
        return this;
    }
    addModal(buttonText: string, emoji: string, customId: string, current: string, modal: Discord.ModalBuilder) {
        modal.setCustomId(customId);
        this.modals.push({ buttonText, emoji, customId, modal, value: current });
        return this;
    }
    async send(editOnly?: boolean): Promise<{
        success?: boolean;
        cancelled?: boolean;
        components?: Record<string, CustomBoolean<unknown>>;
        newReason?: string;
        modals?: {
            buttonText: string;
            emoji: string;
            customId: string;
            modal: Discord.ModalBuilder;
            value: string | undefined;
        }[];
    }> {
        let cancelled = false;
        let success: boolean | undefined = undefined;
        let returnComponents = false;
        let newReason = undefined;

        while (!cancelled && success === undefined && !returnComponents && !newReason) {
            const fullComponents = [
                new Discord.ButtonBuilder()
                    .setCustomId("yes")
                    .setLabel("Confirm")
                    .setStyle(this.inverted ? ButtonStyle.Success : ButtonStyle.Danger)
                    .setEmoji(getEmojiByName("CONTROL.TICK", "id")),
                new Discord.ButtonBuilder()
                    .setCustomId("no")
                    .setLabel("Cancel")
                    .setStyle(ButtonStyle.Secondary)
                    .setEmoji(getEmojiByName("CONTROL.CROSS", "id"))
            ];
            Object.entries(this.customButtons).forEach(([k, v]) => {
                const button = new Discord.ButtonBuilder()
                    .setCustomId(k)
                    .setLabel(v.title)
                    .setStyle(v.active ? ButtonStyle.Success : ButtonStyle.Primary)
                    .setDisabled(v.disabled);
                if (v.emoji !== undefined) button.setEmoji(getEmojiByName(v.emoji, "id"));
                fullComponents.push(button);
            });
            for (const modal of this.modals) {
                fullComponents.push(
                    new Discord.ButtonBuilder()
                        .setCustomId(modal.customId)
                        .setLabel(modal.buttonText)
                        .setStyle(ButtonStyle.Primary)
                        .setEmoji(getEmojiByName(modal.emoji, "id"))
                        .setDisabled(false)
                );
            }
            if (this.reason !== null)
                fullComponents.push(
                    new Discord.ButtonBuilder()
                        .setCustomId("reason")
                        .setLabel("Edit Reason")
                        .setStyle(ButtonStyle.Primary)
                        .setEmoji(getEmojiByName("ICONS.EDIT", "id"))
                        .setDisabled(false)
                );
            const components = [];
            for (let i = 0; i < fullComponents.length; i += 5) {
                components.push(
                    new ActionRowBuilder<
                        | Discord.ButtonBuilder
                        | Discord.StringSelectMenuBuilder
                        | Discord.RoleSelectMenuBuilder
                        | Discord.UserSelectMenuBuilder
                    >().addComponents(fullComponents.slice(i, i + 5))
                );
            }
            const object = {
                embeds: [
                    new EmojiEmbed()
                        .setEmoji(this.emoji)
                        .setTitle(this.title)
                        .setDescription(
                            this.description +
                                "\n\n" +
                                Object.values(this.customButtons)
                                    .map((v) => {
                                        if (v.active) {
                                            return v.value ? `*${v.value}*\n` : "";
                                        } else {
                                            return v.notValue ? `*${v.notValue}*\n` : "";
                                        }
                                    })
                                    .join("")
                        )
                        .setStatus(this.color)
                ],
                components: components,
                ephemeral: true,
                fetchReply: true
            };
            let m: Message;
            try {
                if (editOnly) {
                    m = (await this.interaction.editReply(object)) as unknown as Message;
                } else {
                    m = (await this.interaction.reply(object)) as unknown as Message;
                }
            } catch (e) {
                cancelled = true;
                continue;
            }
            let component;
            try {
                component = await m.awaitMessageComponent({
                    filter: (i) =>
                        i.user.id === this.interaction.user.id && i.channel!.id === this.interaction.channel!.id,
                    time: 300000
                });
            } catch (e) {
                success = false;
                break;
            }
            if (component.customId === "yes") {
                component.deferUpdate();
                for (const v of Object.values(this.customButtons)) {
                    if (!v.active) continue;
                    try {
                        v.response = await v.onClick();
                    } catch (e) {
                        console.log(e);
                    }
                }
                success = true;
                returnComponents = true;
                continue;
            } else if (component.customId === "no") {
                component.deferUpdate();
                success = false;
                returnComponents = true;
                continue;
            } else if (component.customId === "reason") {
                await component.showModal(
                    new Discord.ModalBuilder()
                        .setCustomId("modal")
                        .setTitle("Editing reason")
                        .addComponents(
                            new ActionRowBuilder<TextInputBuilder>().addComponents(
                                new TextInputBuilder()
                                    .setCustomId("reason")
                                    .setLabel("Reason")
                                    .setMaxLength(2000)
                                    .setRequired(false)
                                    .setStyle(TextInputStyle.Paragraph)
                                    .setPlaceholder("Spammed in #general")
                                    .setValue(this.reason ? this.reason : "")
                            )
                        )
                );
                await this.interaction.editReply({
                    embeds: [
                        new EmojiEmbed()
                            .setTitle(this.title)
                            .setDescription("Modal opened. If you can't see it, click back and try again.")
                            .setStatus(this.color)
                            .setEmoji(this.emoji)
                    ],
                    components: [
                        new ActionRowBuilder<Discord.ButtonBuilder>().addComponents(
                            new ButtonBuilder()
                                .setLabel("Back")
                                .setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
                                .setStyle(ButtonStyle.Primary)
                                .setCustomId("back")
                        )
                    ]
                });
                let out;
                try {
                    out = (await modalInteractionCollector(
                        m,
                        this.interaction.user
                    )) as Discord.ModalSubmitInteraction | null;
                } catch (e) {
                    cancelled = true;
                    continue;
                }
                if (out === null || out.isButton()) {
                    cancelled = true;
                    continue;
                }
                if (out instanceof ModalSubmitInteraction) {
                    newReason = out.fields.getTextInputValue("reason");
                    continue;
                } else {
                    returnComponents = true;
                    continue;
                }
            } else if (this.modals.map((m) => m.customId).includes(component.customId)) {
                const chosenModal = this.modals.find(
                    (
                        (component) => (m) =>
                            m.customId === component.customId
                    )(component)
                );
                await component.showModal(chosenModal!.modal);
                await this.interaction.editReply({
                    embeds: [
                        new EmojiEmbed()
                            .setTitle(this.title)
                            .setDescription("Modal opened. If you can't see it, click back and try again.")
                            .setStatus(this.color)
                            .setEmoji(this.emoji)
                    ],
                    components: [
                        new ActionRowBuilder<Discord.ButtonBuilder>().addComponents(
                            new ButtonBuilder()
                                .setLabel("Back")
                                .setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
                                .setStyle(ButtonStyle.Primary)
                                .setCustomId("back")
                        )
                    ]
                });
                let out;
                try {
                    out = (await modalInteractionCollector(
                        m,
                        this.interaction.user
                    )) as Discord.ModalSubmitInteraction | null;
                } catch (e) {
                    console.log(e);
                    cancelled = true;
                    continue;
                }
                if (out === null || out.isButton()) {
                    continue;
                }
                if (out instanceof ModalSubmitInteraction) {
                    chosenModal!.value = out.fields.getTextInputValue("default");
                }
                returnComponents = true;
                continue;
            } else {
                component.deferUpdate();
                this.customButtons[component.customId]!.active = !this.customButtons[component.customId]!.active;
                returnComponents = true;
                continue;
            }
        }
        const returnValue: Awaited<ReturnType<typeof this.send>> = {};

        if (cancelled) {
            await this.timeoutError();
            returnValue.cancelled = true;
        }
        if (success === false) {
            await this.interaction.editReply({
                embeds: [
                    new EmojiEmbed()
                        .setTitle(this.title)
                        .setDescription(this.failedMessage ?? "*Message timed out*")
                        .setStatus(this.failedStatus ?? "Danger")
                        .setEmoji(this.failedEmoji ?? this.redEmoji ?? this.emoji)
                ],
                components: []
            });
            return { success: false, cancelled: returnValue.cancelled ?? false };
        }
        if (returnComponents || success !== undefined) returnValue.components = this.customButtons;
        if (success !== undefined) returnValue.success = success;
        if (newReason) returnValue.newReason = newReason;
        returnValue.modals = this.modals;

        const modals = this.modals;
        const typedReturnValue = returnValue as
            | { cancelled: true }
            | {
                  success: boolean;
                  components: Record<string, CustomBoolean<unknown>>;
                  modals: typeof modals;
                  newReason?: string;
              }
            | { newReason: string; components: Record<string, CustomBoolean<unknown>>; modals: typeof modals }
            | { components: Record<string, CustomBoolean<unknown>>; modals: typeof modals };

        return typedReturnValue;
    }

    async timeoutError(): Promise<void> {
        await this.interaction.editReply({
            embeds: [
                new EmojiEmbed()
                    .setTitle(this.title)
                    .setDescription("We closed this message because it was not used for a while.")
                    .setStatus("Danger")
                    .setEmoji("CONTROL.BLOCKCROSS")
            ],
            components: []
        });
    }
}

export default confirmationMessage;
