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;
        values: Record<string, string>;
    }[] = [];

    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: Record<string, string>,
        modal: Discord.ModalBuilder
    ) {
        modal.setCustomId(customId);
        this.modals.push({ buttonText, emoji, customId, modal, values: 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;
            values: Record<string, string>;
        }[];
    }> {
        let cancelled = false;
        let success: boolean | undefined = undefined;
        let returnComponents = false;
        let newReason = undefined;

        while (!cancelled && success === undefined && !returnComponents && !newReason) {
            const fullComponents = [
                new ButtonBuilder()
                    .setCustomId("yes")
                    .setLabel("Confirm")
                    .setStyle(this.inverted ? ButtonStyle.Success : ButtonStyle.Danger)
                    .setEmoji(getEmojiByName("CONTROL.TICK", "id")),
                new ButtonBuilder()
                    .setCustomId("no")
                    .setLabel("Cancel")
                    .setStyle(ButtonStyle.Danger)
                    .setEmoji(getEmojiByName("CONTROL.CROSS", "id"))
            ];
            Object.entries(this.customButtons).forEach(([k, v]) => {
                const button = new 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 ButtonBuilder()
                        .setCustomId(modal.customId)
                        .setLabel(modal.buttonText)
                        .setStyle(ButtonStyle.Primary)
                        .setEmoji(getEmojiByName(modal.emoji, "id"))
                        .setDisabled(false)
                );
            }
            if (this.reason !== null)
                fullComponents.push(
                    new 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<
                        | 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 ? (i.channel!.id === this.interaction.channel!.id) : true),
                    time: 300000
                });
            } catch (e) {
                success = false;
                break;
            }
            if (component.customId === "yes") {
                await 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") {
                await 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<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) {
                    cancelled = true;
                    continue;
                }
                if (out.isButton()) {
                    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<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) {
                    cancelled = true;
                    continue;
                }
                if (out.isButton()) {
                    continue;
                }
                if (out instanceof ModalSubmitInteraction) {
                    out.fields.fields.forEach((f, k) => {
                        chosenModal!.values[k] = f.value;
                    });
                }
                returnComponents = true;
                continue;
            } else {
                await 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;
