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

import * as DataStore from "@api/DataStore";
import definePlugin from "@utils/types";
import { findStoreLazy } from "@webpack";
import { Menu, Toasts } from "@webpack/common";
const UserProfileStore = findStoreLazy("UserProfileStore");
const userBadgesMap = new Map<string, any[]>();

const removedBadgesMap = new Map<string, Set<string>>();

function getNitroSinceDate(months: number): string {
    const currentDate = new Date();
    const sinceDate = new Date(currentDate);
    sinceDate.setMonth(currentDate.getMonth() - months);
    const month = sinceDate.getMonth() + 1;
    const day = sinceDate.getDate();
    const year = sinceDate.getFullYear();
    return `${month}/${day}/${year.toString().slice(-2)}`;
}

function getBoostSinceDate(months: number): string {
    const currentDate = new Date();
    const sinceDate = new Date(currentDate);
    sinceDate.setMonth(currentDate.getMonth() - months);
    const monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
    return `${monthNames[sinceDate.getMonth()]} ${sinceDate.getDate()}, ${sinceDate.getFullYear()}`;
}

const availableBadges = [
    {
        id: "staff",
        title: "Discord Staff",
        description: "Discord Staff",
        icon: "5e74e9b61934fc1f67c65515d1f7e60d",
        link: "https://discord.com/company"
    },
    {
        id: "premium",
        title: "Nitro Subscriber",
        description: "Subscriber since Dec 22, 2016",
        icon: "2ba85e8026a8614b640c2837bcdfe21b",
        link: "https://discord.com/settings/premium"
    },
    {
        id: "premium_tenure_1_month_v2",
        title: "Nitro Bronze (1 month)",
        description: `Subscriber since ${getNitroSinceDate(1)}`,
        icon: "4f33c4a9c64ce221936bd256c356f91f",
        link: "https://discord.com/nitro"
    },
    {
        id: "premium_tenure_3_month_v2",
        title: "Nitro Silver (3 months)",
        description: `Subscriber since ${getNitroSinceDate(3)}`,
        icon: "4514fab914bdbfb4ad2fa23df76121a6",
        link: "https://discord.com/nitro"
    },
    {
        id: "premium_tenure_6_month_v2",
        title: "Nitro Gold (6 months)",
        description: `Subscriber since ${getNitroSinceDate(6)}`,
        icon: "2895086c18d5531d499862e41d1155a6",
        link: "https://discord.com/nitro"
    },
    {
        id: "premium_tenure_12_month_v2",
        title: "Nitro Platinum (1 year)",
        description: `Subscriber since ${getNitroSinceDate(12)}`,
        icon: "0334688279c8359120922938dcb1d6f8",
        link: "https://discord.com/nitro"
    },
    {
        id: "premium_tenure_24_month_v2",
        title: "Nitro Diamond (2 years)",
        description: `Subscriber since ${getNitroSinceDate(24)}`,
        icon: "0d61871f72bb9a33a7ae568c1fb4f20a",
        link: "https://discord.com/nitro"
    },
    {
        id: "premium_tenure_36_month_v2",
        title: "Nitro Emerald (3 years)",
        description: `Subscriber since ${getNitroSinceDate(36)}`,
        icon: "11e2d339068b55d3a506cff34d3780f3",
        link: "https://discord.com/nitro"
    },
    {
        id: "premium_tenure_60_month_v2",
        title: "Nitro Ruby (5 years)",
        description: `Subscriber since ${getNitroSinceDate(60)}`,
        icon: "cd5e2cfd9d7f27a8cdcd3e8a8d5dc9f4",
        link: "https://discord.com/nitro"
    },
    {
        id: "premium_tenure_72_month_v2",
        title: "Nitro Opal (6+ years)",
        description: `Subscriber since ${getNitroSinceDate(72)}`,
        icon: "5b154df19c53dce2af92c9b61e6be5e2",
        link: "https://discord.com/nitro"
    },
    {
        id: "partner",
        title: "Partnered Server Owner",
        description: "Partnered Server Owner",
        icon: "3f9748e53446a137a052f3454e2de41e",
        link: "https://discord.com/partners"
    },
    {
        id: "certified_moderator",
        title: "Moderator Programs Alumni",
        description: "Moderator Programs Alumni",
        icon: "fee1624003e2fee35cb398e125dc479b",
        link: "https://discord.com/safety"
    },
    {
        id: "hypesquad",
        title: "HypeSquad Events",
        description: "HypeSquad Events",
        icon: "bf01d1073931f921909045f3a39fd264",
        link: "https://discord.com/hypesquad"
    },
    {
        id: "hypesquad_house_1",
        title: "HypeSquad Bravery",
        description: "HypeSquad Bravery",
        icon: "8a88d63823d8a71cd5e390baa45efa02",
        link: "https://discord.com/settings/hypesquad-online"
    },
    {
        id: "hypesquad_house_2",
        title: "HypeSquad Brilliance",
        description: "HypeSquad Brilliance",
        icon: "011940fd013da3f7fb926e4a1cd2e618",
        link: "https://discord.com/settings/hypesquad-online"
    },
    {
        id: "hypesquad_house_3",
        title: "HypeSquad Balance",
        description: "HypeSquad Balance",
        icon: "3aa41de486fa12454c3761e8e223442e",
        link: "https://discord.com/settings/hypesquad-online"
    },
    {
        id: "bug_hunter_level_1",
        title: "Discord Bug Hunter",
        description: "Discord Bug Hunter",
        icon: "2717692c7dca7289b35297368a940dd0",
        link: "https://support.discord.com/hc/en-us/articles/360046057772-Discord-Bugs"
    },
    {
        id: "bug_hunter_level_2",
        title: "Discord Bug Hunter Gold",
        description: "Discord Bug Hunter",
        icon: "848f79194d4be5ff5f81505cbd0ce1e6",
        link: "https://support.discord.com/hc/en-us/articles/360046057772-Discord-Bugs"
    },
    {
        id: "active_developer",
        title: "Active Developer",
        description: "Active Developer",
        icon: "6bdc42827a38498929a4920da12695d9",
        link: "https://support-dev.discord.com/hc/en-us/articles/10113997751447?ref=badge"
    },
    {
        id: "verified_developer",
        title: "Early Verified Bot Developer",
        description: "Early Verified Bot Developer",
        icon: "6df5892e0f35b051f8b61eace34f4967",
        link: "https://discord.com/developers"
    },
    {
        id: "early_supporter",
        title: "Early Supporter",
        description: "Early Supporter",
        icon: "7060786766c9c840eb3019e725d2b358",
        link: "https://discord.com/settings/premium"
    },
    {
        id: "guild_booster_lvl1",
        title: "Server Boost 1 Month",
        description: `Server boosting since ${getBoostSinceDate(1)}`,
        icon: "51040c70d4f20a921ad6674ff86fc95c",
        link: "https://discord.com/settings/premium"
    },
    {
        id: "guild_booster_lvl2",
        title: "Server Boost 2 Months",
        description: `Server boosting since ${getBoostSinceDate(2)}`,
        icon: "0e4080d1d333bc7ad29ef6528b6f2fb7",
        link: "https://discord.com/settings/premium"
    },
    {
        id: "guild_booster_lvl3",
        title: "Server Boost 3 Months",
        description: `Server boosting since ${getBoostSinceDate(3)}`,
        icon: "72bed924410c304dbe3d00a6e593ff59",
        link: "https://discord.com/settings/premium"
    },
    {
        id: "guild_booster_lvl4",
        title: "Server Boost 6 Months",
        description: `Server boosting since ${getBoostSinceDate(6)}`,
        icon: "df199d2050d3ed4ebf84d64ae83989f8",
        link: "https://discord.com/settings/premium"
    },
    {
        id: "guild_booster_lvl5",
        title: "Server Boost 9 Months",
        description: `Server boosting since ${getBoostSinceDate(9)}`,
        icon: "996b3e870e8a22ce519b3a50e6bdd52f",
        link: "https://discord.com/settings/premium"
    },
    {
        id: "guild_booster_lvl6",
        title: "Server Boost 12 Months",
        description: `Server boosting since ${getBoostSinceDate(12)}`,
        icon: "991c9f39ee33d7537d9f408c3e53141e",
        link: "https://discord.com/settings/premium"
    },
    {
        id: "guild_booster_lvl7",
        title: "Server Boost 15 Months",
        description: `Server boosting since ${getBoostSinceDate(15)}`,
        icon: "cb3ae83c15e970e8f3d410bc62cb8b99",
        link: "https://discord.com/settings/premium"
    },
    {
        id: "guild_booster_lvl8",
        title: "Server Boost 18 Months",
        description: `Server boosting since ${getBoostSinceDate(18)}`,
        icon: "7142225d31238f6387d9f09efaa02759",
        link: "https://discord.com/settings/premium"
    },
    {
        id: "guild_booster_lvl9",
        title: "Server Boost 24 Months",
        description: `Server boosting since ${getBoostSinceDate(24)}`,
        icon: "ec92202290b48d0879b7413d2dde3bab",
        link: "https://discord.com/settings/premium"
    },
    {
        id: "legacy_username",
        title: "Legacy Username",
        description: "Originally known as their old username",
        icon: "6de6d34650760ba5551a79732e98ed60",
        link: "https://discord.com"
    },
    {
        id: "quest_completed",
        title: "Quest Completer",
        description: "Completed a Quest",
        icon: "7d9ae358c8c5e118768335dbe68b4fb8",
        link: "https://discord.com/settings/inventory"
    },
    {
        id: "bot_commands",
        title: "Supports Commands",
        description: "Supports Commands",
        icon: "6f9e37f9029ff57aef81db857890005e",
        link: "https://discord.com/blog/welcome-to-the-new-era-of-discord-apps?ref=badge"
    },
    {
        id: "automod",
        title: "Uses AutoMod",
        description: "Uses automod",
        icon: "f2459b691ac7453ed6039bbcfaccbfcd",
        link: "https://discord.com"
    },
    {
        id: "application_guild_subscription",
        title: "Server Subscription",
        description: "Monetized server",
        icon: "d2010c413a8da2208b7e4311042a4b9d",
        link: "https://discord.com"
    },
    {
        id: "orb_profile_badge",
        title: "Orbs",
        description: "Collected the Orb Profile Badge",
        icon: "83d8a1eb09a8d64e59233eec5d4d5c2d",
        link: "https://discord.com"
    }
];

async function loadData() {
    const savedUserBadges = await DataStore.get("userBadges");
    if (savedUserBadges) {
        Object.entries(savedUserBadges).forEach(([userId, badges]) => {
            const updatedBadges = (badges as any[]).map(badge => {
                const freshBadge = availableBadges.find(b => b.id === badge.id);
                if (freshBadge && (badge.id.startsWith("premium_tenure_") || badge.id.startsWith("guild_booster_"))) {
                    return { ...badge, description: freshBadge.description };
                }
                return badge;
            });
            userBadgesMap.set(userId, updatedBadges);
        });
    }

    const savedRemovedBadges = await DataStore.get("removedBadges");
    if (savedRemovedBadges) {
        Object.entries(savedRemovedBadges).forEach(([userId, badgeIds]) => {
            removedBadgesMap.set(userId, new Set(badgeIds as string[]));
        });
    }
}

async function saveData() {
    const userBadgesObject = Object.fromEntries(userBadgesMap);
    await DataStore.set("userBadges", userBadgesObject);

    const removedBadgesObject = Object.fromEntries(
        Array.from(removedBadgesMap.entries()).map(([userId, badgeIds]) => [userId, Array.from(badgeIds)])
    );
    await DataStore.set("removedBadges", removedBadgesObject);
}

function addBadgesToUser(userId: string, badges: any[]) {
    const existingBadges = userBadgesMap.get(userId) || [];
    badges.forEach(badge => {
        const existingIndex = existingBadges.findIndex(b => b.id === badge.id);
        if (existingIndex === -1) {
            existingBadges.push(badge);
        }
    });
    userBadgesMap.set(userId, existingBadges);
    saveData();
}

function removeBadgeFromUser(userId: string, badgeId: string) {
    const existingBadges = userBadgesMap.get(userId) || [];
    const updatedBadges = existingBadges.filter(b => b.id !== badgeId);
    if (updatedBadges.length > 0) {
        userBadgesMap.set(userId, updatedBadges);
    } else {
        userBadgesMap.delete(userId);
    }
    saveData();
}

function getUserBadges(userId: string): any[] {
    return userBadgesMap.get(userId) || [];
}

function hideRealBadge(userId: string, badgeId: string) {
    if (!removedBadgesMap.has(userId)) {
        removedBadgesMap.set(userId, new Set());
    }
    removedBadgesMap.get(userId)!.add(badgeId);
    saveData();
}

function unhideRealBadge(userId: string, badgeId: string) {
    if (removedBadgesMap.has(userId)) {
        removedBadgesMap.get(userId)!.delete(badgeId);
        if (removedBadgesMap.get(userId)!.size === 0) {
            removedBadgesMap.delete(userId);
        }
        saveData();
    }
}

function isRealBadgeHidden(userId: string, badgeId: string): boolean {
    return removedBadgesMap.has(userId) && removedBadgesMap.get(userId)!.has(badgeId);
}

function toggleBadge(userId: string, badge: any, hasActualBadge: boolean) {
    const hasUserBadge = getUserBadges(userId).find(b => b.id === badge.id);
    const isHidden = isRealBadgeHidden(userId, badge.id);

    if (hasActualBadge) {
        if (isHidden) {
            unhideRealBadge(userId, badge.id);
            Toasts.show({
                message: `Restored ${badge.title}`,
                type: Toasts.Type.SUCCESS,
                id: Toasts.genId()
            });
        } else {
            hideRealBadge(userId, badge.id);
            Toasts.show({
                message: `Removed ${badge.title}`,
                type: Toasts.Type.SUCCESS,
                id: Toasts.genId()
            });
        }
    } else {
        if (hasUserBadge) {
            removeBadgeFromUser(userId, badge.id);
            Toasts.show({
                message: `Removed ${badge.title}`,
                type: Toasts.Type.SUCCESS,
                id: Toasts.genId()
            });
        } else {
            addBadgesToUser(userId, [badge]);
            Toasts.show({
                message: `Added ${badge.title}`,
                type: Toasts.Type.SUCCESS,
                id: Toasts.genId()
            });
        }
    }
}

function giveAllBadges(userId: string) {
    addBadgesToUser(userId, availableBadges);
    Toasts.show({
        message: "Added all badges",
        type: Toasts.Type.SUCCESS,
        id: Toasts.genId()
    });
}

function addUserBadge(userId: string) {
    const badgeId = prompt("Enter badge ID:");
    if (!badgeId) return;

    const description = prompt("Enter badge description:");
    if (!description) return;

    const icon = prompt("Enter badge icon hash:");
    if (!icon) return;

    const link = prompt("Enter badge link (optional):", "https://discord.com");

    const userBadge = {
        id: badgeId,
        description: description,
        icon: icon,
        link: link || "https://discord.com"
    };

    addBadgesToUser(userId, [userBadge]);
    Toasts.show({
        message: `Added badge: ${badgeId}`,
        type: Toasts.Type.SUCCESS,
        id: Toasts.genId()
    });
}

let originalGetUserProfile: any;

export default definePlugin({
    name: "BadgeSelector",
    description: "Customize user badges - add, remove, or hide any Discord badge",
    authors: [
        { id: 1263457746829705310n, name: ".q1" },
        { id: 1147940825330876538n, name: "Jelly" },
        { id: 1403404140461297816n, name: "Sami" },
    ],

    async start() {
        await loadData();
        originalGetUserProfile = UserProfileStore.getUserProfile;

        UserProfileStore.getUserProfile = function (userId: string) {
            const userProfile = originalGetUserProfile.call(this, userId);
            if (!userProfile) return userProfile;

            let newBadges = [...(userProfile.badges || [])];

            if (removedBadgesMap.has(userId)) {
                const hiddenBadges = removedBadgesMap.get(userId)!;
                newBadges = newBadges.filter(b => !hiddenBadges.has(b.id));
            }

            if (userBadgesMap.has(userId)) {
                const userBadges = userBadgesMap.get(userId)!;
                userBadges.forEach(badgeObj => {
                    const { id, description, icon, link } = badgeObj;
                    const badgeIndex = newBadges.findIndex(b => b.id === id);
                    if (badgeIndex === -1) {
                        newBadges.push({ id, description, icon, link });
                    }
                });
            }

            newBadges.sort((a, b) => {
                const orderA = availableBadges.findIndex(badge => badge.id === a.id);
                const orderB = availableBadges.findIndex(badge => badge.id === b.id);

                const finalOrderA = orderA === -1 ? 9999 : orderA;
                const finalOrderB = orderB === -1 ? 9999 : orderB;

                return finalOrderA - finalOrderB;
            });

            return {
                ...userProfile,
                badges: newBadges
            };
        };
    },

    stop() {
        if (originalGetUserProfile) {
            UserProfileStore.getUserProfile = originalGetUserProfile;
        }
        userBadgesMap.clear();
        removedBadgesMap.clear();
    },

    contextMenus: {
        "user-context"(children, { user }) {
            if (!user) return;

            const currentUserBadges = getUserBadges(user.id);
            const userProfile = originalGetUserProfile ? originalGetUserProfile.call(UserProfileStore, user.id) : UserProfileStore.getUserProfile(user.id);
            const actualBadges = userProfile?.badges || [];

            children.push(
                <Menu.MenuItem
                    label="Add Badge"
                    key="add-custom-badge"
                    id="user-context-add-custom"
                    color="brand"
                    action={() => addUserBadge(user.id)}
                />,
                <Menu.MenuItem
                    label="Manage Badges"
                    key="custom-badges"
                    id="user-context-custom-badges"
                >
                    {availableBadges.map(badge => {
                        const hasUserBadge = currentUserBadges.find(b => b.id === badge.id);
                        const hasActualBadge = actualBadges.find(b => b.id === badge.id);
                        const isHidden = isRealBadgeHidden(user.id, badge.id);
                        const isChecked = !!hasUserBadge || (!!hasActualBadge && !isHidden);

                        return (
                            <Menu.MenuCheckboxItem
                                key={badge.id}
                                id={`badge-${badge.id}`}
                                // edited here to fix some error
                                // label={
                                //     <div style={{ display: "flex", alignItems: "center", gap: "8px" }}>
                                //         <img
                                //             src={`https://cdn.discordapp.com/badge-icons/${badge.icon}.png`}
                                //             alt=""
                                //             width="18"
                                //             height="18"
                                //             style={{
                                //                 borderRadius: "3px",
                                //                 imageRendering: "crisp-edges"
                                //             }}
                                //         />
                                //         <span>{badge.title}</span>
                                //     </div>
                                // }
                                label={badge.title}
                                checked={isChecked}
                                action={() => toggleBadge(user.id, badge, !!hasActualBadge)}
                            />
                        );
                    })}
                    <Menu.MenuSeparator />
                    <Menu.MenuItem
                        label="Give All Badges"
                        id="give-all-badges"
                        color="brand"
                        action={() => giveAllBadges(user.id)}
                    />
                    <Menu.MenuItem
                        label="Remove All Badges"
                        id="remove-all-badges"
                        color="danger"
                        action={() => {
                            actualBadges.forEach(badge => {
                                hideRealBadge(user.id, badge.id);
                            });
                            userBadgesMap.delete(user.id);

                            Toasts.show({
                                message: "Removed all badges",
                                type: Toasts.Type.SUCCESS,
                                id: Toasts.genId()
                            });
                        }}
                    />
                    <Menu.MenuItem
                        label="Reset to Original"
                        id="reset-badges"
                        color="default"
                        action={() => {
                            userBadgesMap.delete(user.id);
                            removedBadgesMap.delete(user.id);

                            Toasts.show({
                                message: "Reset badges to original state",
                                type: Toasts.Type.SUCCESS,
                                id: Toasts.genId()
                            });
                        }}
                    />
                </Menu.MenuItem>
            );
        }
    }
});
