import { Client, Partials, GatewayIntentBits, ActivityType } from "discord.js";

import { DISCORD_TOKEN, DISCORD_USER_ID, DISCORD_GUILD_ID } from "$env/static/private";

class Bot {
    private client: Client;

    // Normalize a discord.js Activity object into a simple POJO
    private mapActivity(a: any) {
        const type = typeof a.type === 'number' ? a.type : (ActivityType[a.type] ?? a.type);
        const application_id = a.applicationId ?? a.application_id ?? null;

        const rawLarge = a.assets?.largeImage ?? a.assets?.large_image ?? null;
        const rawSmall = a.assets?.smallImage ?? a.assets?.small_image ?? null;

        const formatAsset = (raw: string | null) => {
            if (!raw) return null;
            if (raw.startsWith('mp:external/')) {
                return `https://media.discordapp.net/${raw.replace(/^mp:/, '')}`;
            }
            if (/^https?:\/\//.test(raw)) return raw;
            if (application_id) return `https://cdn.discordapp.com/app-assets/${application_id}/${raw}.webp`;
            return raw;
        };

        return {
            name: a.name ?? null,
            type,
            details: a.details ?? a.state ?? null,
            url: a.url ?? null,
            application_id,
            assets: {
                large_image: formatAsset(rawLarge),
                small_image: formatAsset(rawSmall)
            },
            emoji: a.emoji ? { id: a.emoji.id ?? null, animated: !!a.emoji.animated } : null
        };
    }

    constructor() {
        // Need presence and members intents to read user presence/activity
        this.client = new Client({
            partials: [Partials.User],
            intents: [
                GatewayIntentBits.Guilds,
                GatewayIntentBits.GuildMembers,
                GatewayIntentBits.GuildPresences
            ]
        });

        this.client.login(DISCORD_TOKEN).catch((error) => {
            console.error("Failed to login to Discord:", error);
        });

        this.client.once("clientReady", async () => {
            console.log(`Logged in as ${this.client.user?.tag}`);
        });
    }

    getClient(): Client {
        return this.client;
    }

    /**
     * Look up the user's presence specifically in the given guild.
     * Returns null if guild/member/presence not available.
     */
    async getUserActivityInGuild(guildId: string = DISCORD_GUILD_ID, userId: string = DISCORD_USER_ID) {
        try {
            // Fetch guild from cache or API
            let guild = this.client.guilds.cache.get(guildId) || await this.client.guilds.fetch(guildId).catch(() => null);
            if (!guild) return null;

            // Fetch member (will populate presence if available)
            const member = await guild.members.fetch(userId).catch(() => null);
            if (!member) return null;

            const presence = member.presence;
            const user = member.user;

            // Build avatar URL
            const avatarHash = user.avatar;
            const avatarUrl = avatarHash
                ? `https://cdn.discordapp.com/avatars/${user.id}/${avatarHash}.${avatarHash.startsWith('a_') ? 'gif' : 'webp'}?size=128`
                : `https://cdn.discordapp.com/embed/avatars/${(BigInt(user.id) >> BigInt(22)) % BigInt(6)}.png`;

            // Get guild/clan tag if available
            const guildTag = (user as any).primaryGuild?.tag ?? null;
            const guildTagBadgeImage = `https://cdn.discordapp.com/clan-badges/${(user as any).primaryGuild?.identityGuildId}/${(user as any).primaryGuild?.badge}.png?size=32`;

            if (!presence) return { guildId, status: 'offline', activities: [], displayName: member.displayName, avatarUrl, guildTag, guildTagBadgeImage };

            const status = presence.status;
            const activities = (presence.activities || []).map((a: any) => this.mapActivity(a));

            return { guildId, status, activities, displayName: member.displayName, avatarUrl, guildTag, guildTagBadgeImage };
        } catch (err) {
            return null;
        }
    }
}

export const bot = new Bot();

// Re-export image helper for convenience
export { fetchUserImages } from "./discord/fetchUserImages";