/*
 * Vencord, a Discord client mod
 * Copyright (c) 2024 Vendicated and contributors
 * SPDX-License-Identifier: GPL-3.0-or-later
 */

import { ApplicationCommandInputType, ApplicationCommandOptionType, Argument, CommandContext, findOption, sendBotMessage } from "@api/Commands";
import { DataStore } from "@api/index";
import { addAccessory } from "@api/MessageAccessories";
import { Devs } from "@utils/constants";
import definePlugin from "@utils/types";
import { Parser, React, Text } from "@webpack/common";
import { Message } from "discord-types/general";

let userFlags = new Map<string, Flag>();

enum FlagType {
    DANGER = "danger",
    WARNING = "warning",
    INFO = "info",
    POSITIVE = "positive"
}

type FlagRegistryEntry = {
    label: string;
    color: string;
    emoji: string;
};

// worst typing ever?
const flagRegistry: { [key in FlagType]: FlagRegistryEntry } = {
    [FlagType.DANGER]: {
        label: "Danger",
        color: "#ff7473",
        emoji: "🛑"
    } as FlagRegistryEntry,
    [FlagType.WARNING]: {
        label: "Warning",
        color: "#ffb02e",
        emoji: "⚠️"
    } as FlagRegistryEntry,
    [FlagType.INFO]: {
        label: "Info",
        color: "#62a8ff",
        emoji: "🔵"
    } as FlagRegistryEntry,
    [FlagType.POSITIVE]: {
        label: "Positive",
        color: "#62ff74",
        emoji: "✅"
    }
};


type Flag = {
    type: FlagType;
    text: string;
};

function Flag({ id }: { id: string; }) {
    return (
        <div>
            <Text
                variant="text-md/bold"
                style={{ color: flagRegistry[userFlags.get(id)?.type || ""]?.color }}
            >
                {Parser.parse(flagRegistry[userFlags.get(id)?.type || ""]?.emoji)} {userFlags.get(id)?.text}
            </Text>
        </div >
    );
}

export default definePlugin({
    name: "UserFlags",
    description: `Add "flags" to users that will always show under their messages`,
    authors: [Devs.nin0dev],
    dependencies: ["MessageAccessoriesAPI"],
    async start() {
        const savedFlags = await DataStore.get("USERFLAGS");
        if (savedFlags) {
            if (typeof savedFlags === "string") {
                userFlags = new Map<string, Flag>(JSON.parse(savedFlags));
            } else {
                userFlags = new Map(savedFlags);
            }
        }
        addAccessory("flag", (props: Record<string, any>) => {
            if (userFlags.has((props.message as Message).author.id)) {
                return <Flag id={props.message.author.id} />;
            }
            return null;
        }, 4);
    },
    commands: [
        {
            name: "flag set",
            description: "Set a flag on a user",
            inputType: ApplicationCommandInputType.BOT,
            options: [
                {
                    name: "user",
                    type: ApplicationCommandOptionType.USER,
                    description: "The user to set a flag to",
                    required: true
                },
                {
                    "name": "type",
                    "type": ApplicationCommandOptionType.STRING,
                    "description": "The type of flag to add",
                    choices: Object.entries(flagRegistry).map(([key, flag]) => ({
                        name: key,
                        label: flag.label,
                        displayName: flag.label,
                        value: key,
                    })),
                    required: true
                },
                {
                    name: "message",
                    type: ApplicationCommandOptionType.STRING,
                    description: "The flag content",
                    required: true
                },
            ],
            execute: async (args: Argument[], ctx: CommandContext) => {
                const user = findOption(args, "user", "");
                const type = findOption<FlagType>(args, "type", FlagType.INFO);
                const text = findOption(args, "message", "");
                userFlags.set(user, {
                    type,
                    text
                });
                sendBotMessage(ctx.channel.id, {
                    content: `Flag set on <@${user}> with content \`${text}\`!`
                });
                await DataStore.set("USERFLAGS", userFlags);
                return;
            }
        },
        {
            name: "flag delete",
            description: "Delete the flag from a user",
            inputType: ApplicationCommandInputType.BOT,
            options: [
                {
                    name: "user",
                    type: ApplicationCommandOptionType.USER,
                    description: "The user to delete the flag from",
                    required: true
                }
            ],
            execute: async (args: Argument[], ctx: CommandContext) => {
                const user = findOption(args, "user", "");
                userFlags.delete(user);
                sendBotMessage(ctx.channel.id, {
                    content: `Flag removed from <@${user}>`
                });
                await DataStore.set("USERFLAGS", userFlags);
                return;
            }
        }
    ]
});

