import { request as uRequest } from "undici";
import { discordBot } from "../helpers/discord.bot";

import type { FastifyRequest } from "fastify";
import type { Presence } from "oceanic.js";
import type { IRouteInfo } from "../interfaces/routes";

const routeInfo: IRouteInfo = {
    enabled: true,
    path: "/status",
    method: "GET",
    websocket: true
};

async function route(socket: WebSocket, _request: FastifyRequest): Promise<void> {
    discordBot.addWebSocket(socket);

    socket.on("message", async (message: string) => {
        try {
            const data = JSON.parse(message);

            if (data.type === "getStatus") {
                let userPresences = Array.from(discordBot.getUserPresences()).reduce((acc, [key, value]) => {
                    acc[key] = value;
                    return acc;
                }, {} as Record<string, Presence>);

                for (const [userId, presence] of Object.entries(userPresences)) {
                    if (presence.activities) {
                        for (let index = 0; index < presence.activities.length; index++) {
                            const activity = presence.activities[index];

                            if (activity && activity.type === 0 && (!activity.assets || !activity.assets.largeImage)) {
                                const gameName = activity.name;

                                const iconUrl = await getSteamGameIcon(gameName);

                                if (iconUrl) {
                                    presence.activities[index].assets = {
                                        largeImage: iconUrl,
                                        largeText: gameName
                                    };
                                }
                            }
                        }
                    }
                }

                socket.send(JSON.stringify({
                    type: "statusUpdate",
                    status: userPresences
                }));
            } else if (data.type === "getUsers") {
                const usersInfo = Array.from(discordBot.getUsersInfo()).reduce((acc, [key, member]) => {
                    if (member && member.user) {
                        acc[key] = {
                            id: member.user.id,
                            username: member.user.username,
                            discriminator: member.user.discriminator,
                            nick: member.nick ?? member.user.username,
                            avatar: member.user.avatar
                                ? `https://cdn.discordapp.com/avatars/${member.user.id}/${member.user.avatar}`
                                : `https://cdn.discordapp.com/embed/avatars/${parseInt(member.user.discriminator) % 5}`,
                            avatarDecoration: member.user.avatarDecoration
                                ? `https://cdn.discordapp.com/avatar-decoration-presets/${member.user.avatarDecoration}`
                                : null,
                            banner: member.user.banner
                                ? `https://cdn.discordapp.com/banners/${member.user.id}/${member.user.banner}`
                                : null,
                            roles: member.roles,
                            joinedAt: member.joinedAt,
                            premiumSince: member.premiumSince,
                            user: member.user
                        };
                    } else {
                        console.warn(`Invalid member data for key: ${key}`, member);
                    }
                    return acc;
                }, {} as Record<string, any>);

                socket.send(JSON.stringify({
                    type: "usersUpdate",
                    users: usersInfo
                }));
            } else if (data.type === "getBadges" && data.userId) {
                let badgesFull: any[] = [];
                const vencordLink = "https://badges.vencord.dev/badges.json";
                const equicordLink = "https://raw.githubusercontent.com/Equicord/Equibored/refs/heads/main/badges.json";

                try {
                    const response = await uRequest(equicordLink);
                    const text = await response.body.text();
                    const body: any = JSON.parse(text);

                    if (!body) return;

                    const badges = body[data.userId];
                    if (badges && Array.isArray(badges)) {
                        badgesFull.push(...badges);
                    }
                } catch (error) {
                    console.error("Error fetching Equicord badges:", error);
                }

                try {
                    const response = await uRequest(vencordLink);
                    const body: any = await response.body.json();

                    if (!body) return;

                    const badges = body[data.userId];
                    if (badges && Array.isArray(badges)) {
                        badgesFull.push(...badges);
                    }
                } catch (error) {
                    console.error("Error fetching Vencord badges:", error);
                }

                socket.send(JSON.stringify({
                    type: "badgesUpdate",
                    badges: badgesFull
                }));
            }
        } catch (error) {
            console.error("Error parsing message", error);
        }
    });

    socket.on("close", () => {
        discordBot.removeWebSocket(socket);
    });
}

let steamAppListCache: { data: any; timestamp: number } | null = null;
const CACHE_DURATION = 60 * 60 * 1000; // 1 hour in milliseconds

async function getSteamAppList() {
    if (steamAppListCache && (Date.now() - steamAppListCache.timestamp < CACHE_DURATION)) {
        return steamAppListCache.data;
    }

    const response = await fetch(`https://api.steampowered.com/ISteamApps/GetAppList/v2/`);
    const data = await response.json();

    steamAppListCache = { data, timestamp: Date.now() };
    return data;
}

async function getSteamAppID(gameName: string) {
    const appList = await getSteamAppList();
    const app = appList.applist.apps.find((app: any) => app.name.toLowerCase() === gameName.toLowerCase());
    return app ? app.appid : null;
}

export async function getSteamGameIcon(gameName: string) {
    const appID = await getSteamAppID(gameName);

    if (!appID) {
        console.error("Game not found on Steam.");
        return;
    }

    const iconHashResponse = await fetch(`https://store.steampowered.com/api/appdetails?appids=${appID}`);
    const iconHashData = await iconHashResponse.json();
    const gameData = iconHashData[appID].data;

    const iconUrl = gameData.icon
        ? `https://cdn.cloudflare.steamstatic.com/steamcommunity/public/images/apps/${appID}/${gameData.icon}.jpg`
        : gameData.capsule_image || gameData.header_image;

    if (iconUrl) {
        return iconUrl;
    } else {
        console.error("Icon not available.");
    }
}


export default { routeInfo, route };