import { Client } from '../index.js';
import * as neverthrow from 'neverthrow';
import { Result } from 'neverthrow';
import 'axios';

type AchievementItem = {
    name: string;
    mission: string;
    points: string;
    icon: string;
    rarity: string;
    category: string;
};
type AllAchievementsResponse = {
    totalAchievements: number;
    achievements: AchievementItem[];
};
type AchievementResponse = AchievementItem;

type BattlepassResponse = {
    season: number;
    seasonName: string;
    items: {
        name: string;
        image: string;
        cost: string;
        isLuxury: boolean;
    }[];
};

type Hero = {
    id: string;
    name: string;
    realName: string;
    imageUrl: string;
    role: string;
    attackType: string;
    team: string[];
    difficulty: string;
    bio: string;
    transformations: {
        id: string;
        name: string;
        icon: string;
        health: string | null;
        movementSpeed: string | null;
    }[];
    costumes: {
        id: string;
        name: string;
        icon: string;
        quality: string;
        description: string;
        appearance: string;
    }[];
    abilities: {
        id: number;
        icon: string;
        name: string;
        isCollab: boolean;
        description: string;
        additionalFields: {
            [key: string]: string | number | boolean | null;
        };
        transformationId: string;
    }[];
};
type HeroLeaderboardEntry = {
    info: {
        name: string;
        icon: {
            playerIconId: string;
            playerIcon: string;
        };
        rankSeason: {
            rankGameId: number;
            level: number;
            rankScore: string;
            maxLevel: number;
            maxRankScore: string;
            updateTime: number;
            winCount: number;
            protectScore: number;
            diffScore: string;
        };
        loginOs: string;
    };
    playerUid: number;
    matches: number;
    wins: number;
    kills: number;
    deaths: number;
    assists: number;
    playTime: string;
    totalHeroDamage: string;
    totalDamageTaken: string;
    totalHeroHeal: string;
    mvps: number;
    svps: number;
};
type HeroLeaderboardResponse = HeroLeaderboardEntry[];

type AllMapsResponse = {
    totalMaps: number;
    maps: {
        id: number;
        name: string;
        fullName: string;
        location: string;
        description: string;
        gameMode: string;
        isCompetitive: boolean;
        subMap: {
            id: number | null;
            name: string | null;
            thumbnail: string | null;
        };
        video: string | null;
        images: string[];
    }[];
};

type FindPlayerResponse = {
    name: string;
    uid: string;
};
type UpdatePlayerResponse = {
    success: boolean;
    message: string;
    status: number;
};
type OverallStatsEntry = {
    totalMatches: number;
    totalWins: number;
    totalAssists: number;
    totalDeaths: number;
    totalKills: number;
    totalTimePlayed: string;
    totalTimePlayedRaw: number;
    totalMvp: number;
    totalSvp: number;
};
type PlayerHeroStatEntry = {
    heroId: number;
    heroName: string;
    heroThumbnail: string;
    matches: number;
    wins: number;
    mvp: number;
    svp: number;
    kills: number;
    deaths: number;
    assists: number;
    playTime: number;
    damage: number;
    heal: number;
    damageTaken: number;
    mainAttack: {
        total: number;
        hits: number;
    };
};
type PlayerResponse = {
    uid: number;
    name: string;
    updates: {
        infoUpdateTime: string;
        lastHistoryUpdate: string;
        lastInsertedMatch: string;
        lastUpdateRequest: string;
    };
    player: {
        uid: number;
        level: string;
        name: string;
        icon: {
            playerIconId: string;
            playerIcon: string;
        };
        rank: {
            rank: string;
            image: string;
            color: string;
        };
        team: {
            clubTeamId: string;
            clubTeamMiniName: string;
            clubTeamType: string;
        };
        info: {
            completedAchievements: string;
            loginOs: string;
            rankGameSeason: {
                [key: string]: {
                    rankGameId: number;
                    level: number;
                    rankScore: number;
                    maxLevel: number;
                    maxRankScore: number;
                    updateTime: number;
                    winCount: number;
                    protectScore: number;
                    diffScore: number;
                };
            };
        };
    };
    isPrivate: boolean;
    overallStats: {
        totalMatches: number;
        totalWins: number;
        unranked: OverallStatsEntry;
        ranked: OverallStatsEntry;
    };
    matchHistory: {
        matchUid: string;
        matchId: number;
        mapThumbnail: string;
        duration: number;
        season: number;
        winnerSide: number;
        mvpUid: number;
        svpUid: number;
        matchTimeStamp: number;
        playModeId: number;
        gameModeId: number;
        scoreInfo: {
            [key: string]: number;
        };
        playerPerformance: {
            playerUid: number;
            heroId: number;
            heroName: string;
            heroType: string;
            kills: number;
            deaths: number;
            assists: number;
            isWin: {
                score: number;
                isWin: boolean;
            };
            disconnected: boolean;
            camp: number;
            scoreChange: number;
            level: number;
            newLevel: number;
            newScore: number;
        };
    }[];
    rankHistory: {
        matchTimeStamp: number;
        levelProgression: {
            from: number;
            to: number;
        };
        scoreProgression: {
            addScore: number;
            totalScore: number;
        };
    }[];
    heroMatchups: {
        heroId: number;
        heroName: string;
        heroClass: string;
        heroThumbnail: string;
        matches: number;
        wins: number;
        winRate: string;
    }[];
    teamMates: {
        playerInfo: {
            nickName: string;
            playerIcon: string;
            playerUid: number;
        };
        matches: number;
        wins: number;
        winRate: string;
    }[];
    heroesRanked: PlayerHeroStatEntry[];
    heroesUnranked: PlayerHeroStatEntry[];
    maps: {
        mapId: number;
        mapThumbnail: string;
        matches: number;
        wins: number;
        kills: number;
        deaths: number;
        assists: number;
        playTime: number;
    }[];
};
type PlayerMatchHistoryEntry = {
    matchMapId: number;
    mapThumbnail: string;
    matchPlayDuration: number;
    matchSeason: number;
    matchUid: string;
    matchWinnerSide: number;
    mvpUid: number;
    svpUid: number;
    scoreInfo: {
        [key: string]: number;
    };
    matchTimeStamp: number;
    playModeId: number;
    gameModeId: number;
    matchPlayer: {
        assists: number;
        kills: number;
        deaths: number;
        isWin: {
            score: number;
            isWin: boolean;
        };
        disconnected: boolean;
        playerUid: number;
        camp: number | null;
        scoreInfo: {
            addScore: number;
            level: number;
            newLevel: number;
            newScore: number;
        };
        playerHero: {
            heroId: number;
            heroName: string;
            heroType: string;
            kills: number;
            deaths: number;
            assists: number;
            playTime: number;
            totalHeroDamage: number;
            totalDamageTaken: number;
            totalHeroHeal: number;
        };
    };
};

type HealthCheckResponse = {
    error: boolean;
    message: string;
    status: number;
    serverTime: string;
    serverResponseTime: string;
};

/**
 * Retrieves a list of achievements. You can apply pagination.
 *
 * @export
 * @async
 * @param {Client} client
 * @param {number} [page=1]
 * @param {number} [perPage=10]
 * @returns {{Promise<Result<AllAchievementsResponse, string>>}}
 */
declare function getAllAchievements(client: Client, page?: number, perPage?: number): Promise<Result<AllAchievementsResponse, string>>;
/**
 * Allows searching for a specific achievement either by its unique ID or its name.
 *
 * @export
 * @async
 * @param {Client} client
 * @param {string} name
 * @returns {Promise<Result<AchievementResponse, string>>}
 */
declare function getAchievement(client: Client, name: string): Promise<Result<AchievementResponse, string>>;

/**
 * Retrieves the battlepass data for a given season, including season details
 * and the list of items available for the selected season.
 *
 * @export
 * @async
 * @param {Client} client
 * @param {?number} [season] Defaults to the current season if not provided.
 * @returns {Promise<Result<BattlepassResponse, string>>}
 */
declare function getBattlepass(client: Client, season?: number): Promise<Result<BattlepassResponse, string>>;

/**
 * Retrieves a list of all available heroes with their details.
 *
 * @export
 * @async
 * @param {Client} client
 * @returns {Promise<Result<Hero[], string>>}
 */
declare function getAllHeroes(client: Client): Promise<Result<Hero[], string>>;
/**
 * Detailed information about a hero. You can either provide the hero's name or ID to retrieve their stats, abilities, and other relevant details.
 *
 * @export
 * @async
 * @param {Client} client
 * @param {string} name
 * @returns {Promise<Result<Hero, string>>}
 */
declare function getHero(client: Client, name: string): Promise<Result<Hero, string>>;
/**
 * Retrieves the leaderboard for a specific hero based on their name or ID.
 * The leaderboard data is fetched from an external API and processed for easy consumption.
 *
 * @export
 * @async
 * @param {Client} client
 * @param {string} name
 * @returns {Promise<Result<HeroLeaderboardResponse, string>>}
 */
declare function getHeroLeaderboard(client: Client, name: string): Promise<Result<HeroLeaderboardResponse, string>>;

/**
 * Retrieves all available maps with optional pagination to control the number of results per page.
 *
 * @export
 * @async
 * @param {Client} client
 * @param {number} [page=1]
 * @param {number} [perPage=10]
 * @returns {Promise<Result<AllMapsResponse, string>>}
 */
declare function getAllMaps(client: Client, page?: number, perPage?: number): Promise<Result<AllMapsResponse, string>>;

/**
 * Retrieve match data for a specific match identified by the matchId. It processes the match details and player stats.
 *
 * @export
 * @async
 * @param {Client} client
 * @param {string} matchId
 * @returns {unknown}
 */
declare function getMatch(client: Client, matchId: string): Promise<neverthrow.Result<{
    matchUid: string;
    gameMode: {
        gameModeId: number;
        gameModeName: string;
    };
    replayId: string;
    mvpUid: number;
    mvpHeroId: number;
    svpUid: number;
    svpHeroId: number;
    dynamicFields: {
        banPickInfo: {
            battleSide: number;
            isOneSide: boolean;
            confId: number;
            roundIdx: number;
            effectBattleSide: number;
            votes: any;
            heroId: number;
            isPick: number;
            voteType: number;
        }[];
    };
    matchPlayers: {
        playerUid: number;
        nickName: string;
        playerIcon: number;
        camp: number;
        curHeroId: number;
        curHeroIcon: string;
        isWin: number;
        kills: number;
        deaths: number;
        assists: number;
        totalHeroDamage: number;
        totalHeroHeal: number;
        totalDamageTaken: number;
        badges?: {
            name: string;
            id: number;
            count: number;
            image: string | null;
        }[];
        playerHeroes: {
            heroId: number;
            playTime: number;
            kills: number;
            deaths: number;
            assists: number;
            sessionHitRate: number;
            heroIcon: string;
        }[];
    }[];
}, string>>;

/**
 * Retrieves player uid for a specific player identified by their username. It returns basic player information such as name and unique identifier (UID).
 *
 * @export
 * @async
 * @param {Client} client
 * @param {string} username
 * @returns {Promise<Result<FindPlayerResponse, string>>}
 */
declare function searchPlayer(client: Client, username: string): Promise<Result<FindPlayerResponse, string>>;
/**
 * Player data for a specific player identified by uid or username. It processes player statistics and related data, such as match history, rank history, heroes, and maps.
 *
 * IMPORTANT: Searching player stats by username is a new feature and is not always reliable. Searching player stats by player uid is more stable.
 *
 * @export
 * @async
 * @param {Client} client
 * @param {string} player This can be either a player uid or username.
 * @param {?number} [season]
 * @returns {Promise<Result<PlayerResponse, string>>}
 */
declare function getPlayer(client: Client, player: string, season?: number): Promise<Result<PlayerResponse, string>>;
/**
 * Triggers an update of player data identified by the uid or username. It performs the necessary updates and returns a success or failure response.
 *
 * IMPORTANT
 * The update player endpoint is a QUEUE & TIME & USER sensitive/locked endpoint at a set time of 30 minutes what this means is it can only be used every 30 minutes on 1 specific player.
 * For more information, please refer to the [API documentation](https://docs.marvelrivalsapi.com/endpoints/player-stats/update-player).
 *
 * @export
 * @async
 * @param {Client} client
 * @param {string} player
 * @returns {Promise<Result<UpdatePlayerResponse, string>>}
 */
declare function updatePlayer(client: Client, player: string): Promise<Result<UpdatePlayerResponse, string>>;
/**
 * Retrieves the match history of a player based on their unique identifier (UID) or username. It allows filtering by season, skip value, and game mode.
 *
 * @export
 * @async
 * @param {Client} client
 * @param {string} uid Player unique identifier (UID) or username.
 * @param {?number} [season] The season to retrieve match history for. Defaults to current season
 * @param {?number} [skip] The number of matches to skip (pagination). Defaults to 20.
 * @param {?number} [gameMode] The game mode to filter matches by. Defaults to 0.
 * @param {?number} [timestamp] Filter matches by timestamp. Only includes matches after the given timestamp.
 * @returns {Promise<Result<PlayerMatchHistoryEntry[], string>>}
 */
declare function getPlayerMatchHistory(client: Client, uid: string, season?: number, skip?: number, gameMode?: number, timestamp?: number): Promise<Result<PlayerMatchHistoryEntry[], string>>;

/**
 * API health check.
 *
 * @export
 * @async
 * @param {Client} client
 * @returns {Promise<Result<HealthCheckResponse, string>>}
 */
declare function getHealthCheck(client: Client): Promise<Result<HealthCheckResponse, string>>;

declare const routes: {
    healthCheck(): string;
    battlepass(season?: number): string;
    allAchievements(page?: number, perPage?: number): string;
    achievement(name: string): string;
    allMaps(page?: number, perPage?: number): string;
    searchPlayer(username: string): string;
    player(player: string, season?: number): string;
    updatePlayer(player: string): string;
    getPlayerMatchHistory(uid: string, season?: number, skip?: number, gameMode?: number, timestamp?: number): string;
    allHeroes(): string;
    hero(name: string): string;
    heroLeaderboard(name: string): string;
    singleMatch(matchId: string): string;
};

export { getAchievement, getAllAchievements, getAllHeroes, getAllMaps, getBattlepass, getHealthCheck, getHero, getHeroLeaderboard, getMatch, getPlayer, getPlayerMatchHistory, routes, searchPlayer, updatePlayer };
