export interface Guild {
    id: string;
    name: string;
    icon: string | null;
    owner: boolean;
    permissions: string;
    features: string[];
    botInGuild?: boolean;
    isBetaServer?: boolean;
}


export interface LeaderboardMember {
    user_id: string;
    username: string;
    avatar: string;
    level: number;
    xp: number;
    rank: number;
}

export interface Role {
    role_id: string;
    role_name: string;
    color: number;
    position: number;
}

export interface TrackRole {
    role_name: string;
    role_id: string; // Changed from id to role_id to match backend
    level: number;
}

export interface LevelTrack {
    [trackName: string]: TrackRole[];
}

// ... (previous interfaces)

export interface LevelBridge {
    in_role_id: string;
    out_role_id: string;
}

export interface LevelTracksResponse {
    tracks: LevelTrack[];
}

export async function getGuildLeaderboard(guildId: string): Promise<LeaderboardMember[]> {
    try {
        if (!process.env.BOT_API_URL) return [];

        const response = await fetch(`${process.env.BOT_API_URL}/api/${guildId}/leaderboard`, {
            method: "GET",
            headers: {
                "Content-Type": "application/json",
                "X-API-Key": process.env.BOT_API_KEY as string
            },
            next: { revalidate: 60 }
        });

        if (response.ok) {
            return await response.json();
        }
        console.error(`Fetch Leaderboard failed: ${response.status} ${response.statusText}`);
        return [];
    } catch (e) {
        console.error("Failed to fetch leaderboard", e);
        return [];
    }
}

export async function checkBotMembership(guildIds: string[]): Promise<boolean[]> {
    try {
        if (!process.env.BOT_API_URL) return guildIds.map(() => false);

        const response = await fetch(`${process.env.BOT_API_URL}/api/is_bot_there`, {
            method: "POST",
            headers: {
                "Content-Type": "application/json",
                "X-API-Key": process.env.BOT_API_KEY as string
            },
            body: JSON.stringify({ guild_ids: guildIds }),
            next: { revalidate: 0 } // Don't cache this as it might change
        });

        if (response.ok) {
            const data = await response.json();
            return data.results;
        } else {
            const errorText = await response.text();
            console.error(`CheckBotMembership failed: ${response.status} ${response.statusText}`, errorText);
        }
        return guildIds.map(() => false);
    } catch (e) {
        console.error("Failed to check bot membership", e);
        return guildIds.map(() => false);
    }
}

export async function checkBetaServer(guildIds: string[]): Promise<boolean[]> {
    try {
        if (!process.env.BOT_API_URL) return guildIds.map(() => false);

        // Helper to ensure IDs are numeric strings to prevent injection if we are doing manual JSON
        const safeGuildIds = guildIds.filter(id => /^\d+$/.test(id));

        if (safeGuildIds.length === 0) return guildIds.map(() => false);

        // Use JSON.stringify which matches the backend expectation of strings
        const body = JSON.stringify({ guild_ids: guildIds });

        const response = await fetch(`${process.env.BOT_API_URL}/api/is_beta_server`, {
            method: "POST",
            headers: {
                "Content-Type": "application/json",
                "X-API-Key": process.env.BOT_API_KEY as string
            },
            body: body,
            next: { revalidate: 60 }
        });

        if (response.ok) {
            const data = await response.json();
            return data.results;
        } else {
            const errorText = await response.text();
            console.error(`CheckBetaServer failed: ${response.status} ${response.statusText}`, errorText);
        }
        return guildIds.map(() => false);
    } catch (e) {
        console.error("Failed to check beta server", e);
        return guildIds.map(() => false);
    }
}

export async function getUserGuilds(accessToken: string): Promise<Guild[]> {
    try {
        const response = await fetch("https://discord.com/api/users/@me/guilds", {
            headers: {
                Authorization: `Bearer ${accessToken}`,
            },
            next: { revalidate: 60 } // Cache for 60 seconds
        });

        if (response.ok) {
            const guilds: Guild[] = await response.json();
            // Filter: Manage Guild (0x20) or Administrator (0x8)
            const managedGuilds = guilds.filter((guild: any) => {
                const perms = BigInt(guild.permissions);
                const MANAGE_GUILD = BigInt(0x20);
                const ADMINISTRATOR = BigInt(0x8);
                return (perms & MANAGE_GUILD) === MANAGE_GUILD || (perms & ADMINISTRATOR) === ADMINISTRATOR;
            });

            // Check if bot is in these guilds and if they are beta servers
            const guildIds = managedGuilds.map(g => g.id);
            if (guildIds.length > 0) {
                const [memberships, betaStatuses] = await Promise.all([
                    checkBotMembership(guildIds),
                    checkBetaServer(guildIds)
                ]);

                return managedGuilds.map((guild, index) => ({
                    ...guild,
                    botInGuild: memberships[index] || false,
                    isBetaServer: betaStatuses[index] || false
                }));
            }

            return managedGuilds;
        }
        return [];
    } catch (e) {
        console.error("Failed to fetch guilds", e);
        return [];
    }
}

export async function getGuildRoles(guildId: string, userToken?: string): Promise<Role[]> {
    try {
        if (!process.env.BOT_API_URL) return [];

        const headers: Record<string, string> = {
            "Content-Type": "application/json",
            "X-API-Key": process.env.BOT_API_KEY as string
        };
        if (userToken) {
            headers["X-User-Token"] = userToken;
        }

        const response = await fetch(`${process.env.BOT_API_URL}/api/${guildId}/roles`, {
            method: "GET",
            headers,
            next: { revalidate: 60 }
        });

        if (response.ok) {
            const data = await response.json();
            // Transform API response: { "0": { role_id, role_name, color, position }, ... }
            // to array of Role: { role_id, role_name, color, position }
            if (data && typeof data === 'object') {
                return Object.values(data).map((role: any) => ({
                    role_id: role.role_id || role.id,
                    role_name: role.role_name || role.name,
                    color: role.color ?? 0,
                    position: role.position ?? 0
                }));
            }
            return [];
        }
        console.error(`Fetch Guild Roles failed: ${response.status} ${response.statusText}`);
        return [];
    } catch (e) {
        console.error("Failed to fetch guild roles", e);
        return [];
    }
}

export async function getLevelTracks(guildId: string, userToken?: string): Promise<LevelTrack[]> {
    try {
        if (!process.env.BOT_API_URL) return [];

        const headers: Record<string, string> = {
            "Content-Type": "application/json",
            "X-API-Key": process.env.BOT_API_KEY as string
        };
        if (userToken) {
            headers["X-User-Token"] = userToken;
        }

        const response = await fetch(`${process.env.BOT_API_URL}/api/${guildId}/level/track`, {
            method: "GET",
            headers,
            next: { revalidate: 0 } // Don't cache as this is frequently edited
        });

        if (response.ok) {
            // WORKAROUND: Handle u64 precision loss (JS Numbers are f64)
            // Backend sends role_id as u64 (might be > 2^53).
            // We intercept the raw text and wrap role_id numeric values in quotes before parsing.
            const text = await response.text();
            const safeText = text.replace(/"role_id":\s*(\d+)/g, '"role_id": "$1"');
            return JSON.parse(safeText);
        }
        console.error(`Fetch Level Tracks failed: ${response.status} ${response.statusText}`);
        return [];
    } catch (e) {
        console.error("Failed to fetch level tracks", e);
        return [];
    }
}

// Type for role in track API
export interface TrackRoleUpdate {
    role_id: string; // Changed to string to handle u64 precision on frontend
    level: number;
}

// Create a new track (POST)
export async function createLevelTrack(
    guildId: string,
    data: { track_name: string; roles: TrackRoleUpdate[] },
    userToken: string
): Promise<{ success: boolean; error?: string }> {
    try {
        if (!process.env.BOT_API_URL) return { success: false, error: "Bot API URL not configured" };

        // REMOVED WORKAROUND: Backend now expects strings for u64 IDs
        const bodyJson = JSON.stringify(data);


        const response = await fetch(`${process.env.BOT_API_URL}/api/${guildId}/level/track`, {
            method: "POST",
            headers: {
                "Content-Type": "application/json",
                "X-API-Key": process.env.BOT_API_KEY as string,
                "X-User-Token": userToken
            },
            body: bodyJson
        });

        if (response.ok) {
            return { success: true };
        }
        const errorText = await response.text();
        return { success: false, error: errorText || `Failed with status ${response.status}` };
    } catch (e) {
        console.error("Failed to create level track", e);
        return { success: false, error: "Internal error" };
    }
}

// Update existing track (PATCH)
export async function updateLevelTrack(
    guildId: string,
    data: { track_name: string; roles: TrackRoleUpdate[] },
    userToken: string
): Promise<{ success: boolean; error?: string }> {
    try {
        if (!process.env.BOT_API_URL) return { success: false, error: "Bot API URL not configured" };

        // REMOVED WORKAROUND: Backend now expects strings for u64 IDs
        const bodyJson = JSON.stringify(data);


        const response = await fetch(`${process.env.BOT_API_URL}/api/${guildId}/level/track`, {
            method: "PATCH",
            headers: {
                "Content-Type": "application/json",
                "X-API-Key": process.env.BOT_API_KEY as string,
                "X-User-Token": userToken
            },
            body: bodyJson
        });

        if (response.ok) {
            return { success: true };
        }
        const errorText = await response.text();
        return { success: false, error: errorText || `Failed with status ${response.status}` };
    } catch (e) {
        console.error("Failed to update level track", e);
        return { success: false, error: "Internal error" };
    }
}

// Delete a track (DELETE)
export async function deleteLevelTrack(
    guildId: string,
    trackName: string,
    userToken: string
): Promise<{ success: boolean; error?: string }> {
    try {
        if (!process.env.BOT_API_URL) return { success: false, error: "Bot API URL not configured" };

        const response = await fetch(`${process.env.BOT_API_URL}/api/${guildId}/level/track`, {
            method: "DELETE",
            headers: {
                "Content-Type": "application/json",
                "X-API-Key": process.env.BOT_API_KEY as string,
                "X-User-Token": userToken
            },
            body: JSON.stringify({ track_name: trackName })
        });

        if (response.ok) {
            return { success: true };
        }
        const errorText = await response.text();
        return { success: false, error: errorText || `Failed with status ${response.status}` };
    } catch (e) {
        console.error("Failed to delete level track", e);
        return { success: false, error: "Internal error" };
    }
}
// ... (previous code)

// Level Bridger API Helpers

export async function getLevelBridges(guildId: string, userToken: string): Promise<LevelBridge[]> {
    try {
        if (!process.env.BOT_API_URL) return [];

        const headers: Record<string, string> = {
            "Content-Type": "application/json",
            "X-API-Key": process.env.BOT_API_KEY as string,
            "X-User-Token": userToken
        };

        const response = await fetch(`${process.env.BOT_API_URL}/api/${guildId}/level_bridger`, {
            method: "GET",
            headers,
            next: { revalidate: 0 }
        });

        if (response.ok) {
            // WORKAROUND: Handle u64 precision loss if needed, though usually these simple objects survive better
            // But let's be safe like we were with tracks if the backend sends huge numbers.
            const text = await response.text();
            // Regex to safely wrap role_id's if they come as raw numbers
            const safeText = text.replace(/("in_role_id"|"out_role_id"):\s*(\d+)/g, '$1: "$2"');
            return JSON.parse(safeText);
        }
        console.error(`Fetch Level Bridges failed: ${response.status} ${response.statusText}`);
        return [];
    } catch (e) {
        console.error("Failed to fetch level bridges", e);
        return [];
    }
}

export async function createLevelBridge(
    guildId: string,
    bridge: LevelBridge,
    userToken: string
): Promise<{ success: boolean; error?: string }> {
    try {
        if (!process.env.BOT_API_URL) return { success: false, error: "Bot API URL not configured" };

        // REMOVED WORKAROUND: Backend now expects strings for u64 IDs
        const bodyJson = JSON.stringify(bridge);


        const response = await fetch(`${process.env.BOT_API_URL}/api/${guildId}/level_bridger`, {
            method: "POST",
            headers: {
                "Content-Type": "application/json",
                "X-API-Key": process.env.BOT_API_KEY as string,
                "X-User-Token": userToken
            },
            body: bodyJson
        });

        if (response.ok) {
            return { success: true };
        }
        const errorText = await response.text();
        return { success: false, error: errorText || `Failed with status ${response.status}` };
    } catch (e) {
        console.error("Failed to create level bridge", e);
        return { success: false, error: "Internal error" };
    }
}

export async function updateLevelBridge(
    guildId: string,
    bridge: LevelBridge,
    userToken: string
): Promise<{ success: boolean; error?: string }> {
    try {
        if (!process.env.BOT_API_URL) return { success: false, error: "Bot API URL not configured" };

        const bodyJson = JSON.stringify(bridge);


        const response = await fetch(`${process.env.BOT_API_URL}/api/${guildId}/level_bridger`, {
            method: "PUT",
            headers: {
                "Content-Type": "application/json",
                "X-API-Key": process.env.BOT_API_KEY as string,
                "X-User-Token": userToken
            },
            body: bodyJson
        });

        if (response.ok) {
            return { success: true };
        }
        const errorText = await response.text();
        return { success: false, error: errorText || `Failed with status ${response.status}` };
    } catch (e) {
        console.error("Failed to update level bridge", e);
        return { success: false, error: "Internal error" };
    }
}

export async function deleteLevelBridge(
    guildId: string,
    inRoleId: string,
    userToken: string
): Promise<{ success: boolean; error?: string }> {
    try {
        if (!process.env.BOT_API_URL) return { success: false, error: "Bot API URL not configured" };

        const bodyJson = JSON.stringify({ in_role_id: inRoleId });


        const response = await fetch(`${process.env.BOT_API_URL}/api/${guildId}/level_bridger`, {
            method: "DELETE",
            headers: {
                "Content-Type": "application/json",
                "X-API-Key": process.env.BOT_API_KEY as string,
                "X-User-Token": userToken
            },
            body: bodyJson
        });

        if (response.ok) {
            return { success: true };
        }
        const errorText = await response.text();
        return { success: false, error: errorText || `Failed with status ${response.status}` };
    } catch (e) {
        console.error("Failed to delete level bridge", e);
        return { success: false, error: "Internal error" };
    }
}
