import { Locales, Origins, Resource, ResourceResponse } from '@blizzard-api/core';

/**
 * An access token response from the Blizzard API.
 * @see https://develop.battle.net/documentation/guides/using-oauth
 * @see https://develop.battle.net/documentation/guides/using-oauth/client-credentials-flow¨
 * @example
 * const response: AccessToken = {
 *  access_token: 'access-token',
 *  token_type: 'bearer',
 *  expires_in: 86399,
 *  sub: 'client-id',
 * };
 */
interface AccessToken {
    access_token: string;
    expires_in: number;
    sub?: string;
    token_type: 'bearer';
}
/**
 * An access token request.
 * @see https://develop.battle.net/documentation/guides/using-oauth/client-credentials-flow
 * @example
 * const request: AccessTokenRequestArguments = {
 *  origin: 'eu',
 *  key: 'client',
 *  secret: 'secret'
 * };
 */
interface AccessTokenRequestArguments {
    key?: string;
    origin?: Origins;
    secret?: string;
}
type AxiosCompatability<T> = T & {
    /**
     * @deprecated
     * This property is only here for backward compatibility, it will be removed in the next major version.
     * All data should be accessed directly from the response object instead of through this property.
     */
    data: T;
};
/**
 * A client configuration object.
 * @example
 * const options: ClientOptions = {
 *  key: 'client',
 *  secret: 'secret',
 *  origin: 'eu',
 *  locale: 'en_GB',
 *  token: 'access'
 * };
 */
interface ClientOptions {
    key: string;
    locale?: Locales;
    origin: Origins;
    secret: string;
    token?: string;
}
/**
 * A Blizzard API client.
 */
interface IBlizzardApiClient {
    getAccessToken: (options: AccessTokenRequestArguments) => Promise<AxiosCompatability<AccessToken>>;
    refreshAccessToken: (options: AccessTokenRequestArguments) => Promise<AxiosCompatability<AccessToken>>;
    setAccessToken: (token: string) => void;
    validateAccessToken: (options: ValidateAccessTokenArguments) => Promise<AxiosCompatability<ValidateAccessTokenResponse>>;
}
/**
 * Validate an access token.
 * @see https://develop.battle.net/documentation/guides/using-oauth/client-credentials-flow
 * @example
 * const request: ValidateAccessTokenArguments = {
 *  origin: 'eu',
 *  token: 'access'
 * };
 */
interface ValidateAccessTokenArguments {
    origin?: Origins;
    token?: string;
}
/**
 * A response from validating an access token.
 * @see https://develop.battle.net/documentation/guides/using-oauth/client-credentials-flow
 * @example
 * const response: ValidateAccessTokenResponse = {
 *  scope: ['wow.profile'],
 *  account_authorities: [],
 *  exp: 1617000000,
 *  client_authorities: [],
 *  authorities: ['wow.profile'],
 *  client_id: 'client'
 * };
 */
interface ValidateAccessTokenResponse {
    account_authorities: Array<unknown>;
    authorities: Array<string>;
    client_authorities: Array<unknown>;
    client_id: string;
    exp: number;
    scope: Array<string>;
}

/**
 * A Blizzard API client.
 * @classdesc A client to interact with the Blizzard API.
 * @example
 * const client = new BlizzardApiClient({
 *  key: 'client',
 *  secret: 'secret',
 *  origin: 'eu',
 *  locale: 'en_GB',
 *  token: 'access'
 * });
 */
declare class BlizzardApiClient implements IBlizzardApiClient {
    defaults: {
        key: string;
        locale: Locales;
        origin: Origins;
        secret: string;
        token?: string;
    };
    private ky;
    constructor(options: ClientOptions);
    /**
     * Get an access token.
     * @param options The access token request arguments. See {@link AccessTokenRequestArguments}.
     * @returns The access token. See {@link AccessToken}.
     * @example
     * const response = await client.getAccessToken();
     * const { access_token, token_type, expires_in, sub } = response;
     * console.log(access_token, token_type, expires_in, sub);
     * // => 'access'
     * // => 'bearer'
     * // => 86399
     * // => 'client-id'
     */
    getAccessToken: (options?: AccessTokenRequestArguments) => Promise<AxiosCompatability<AccessToken>>;
    /**
     * Set the access token.
     * @param token The access token.
     */
    setAccessToken: (token: string) => void;
    /**
     * Refresh the access token.
     * @param options The access token request arguments. See {@link AccessTokenRequestArguments}.
     * @returns The access token. See {@link AccessToken}.
     * @example
     * const response = await client.refreshAccessToken();
     * const { access_token, token_type, expires_in, sub } = response;
     * console.log(access_token, token_type, expires_in, sub);
     * // => 'access'
     * // => 'bearer'
     * // => 86399
     * // => 'client-id'
     */
    refreshAccessToken: (options?: AccessTokenRequestArguments) => Promise<AxiosCompatability<AccessToken>>;
    /**
     * Validate an access token.
     * @param options The validate access token arguments. See {@link ValidateAccessTokenArguments}.
     * @returns The response from the Blizzard API. See {@link ValidateAccessTokenResponse}.
     * @example
     * const response = await client.validateAccessToken({ token: 'access' });
     * console.log(response.client_id);
     * // => 'client-id'
     */
    validateAccessToken: (options?: ValidateAccessTokenArguments) => Promise<AxiosCompatability<ValidateAccessTokenResponse>>;
    /**
     * Get the request configuration.
     * @param resource The resource to fetch. See {@link Resource}.
     * @param options Client options. See {@link ClientOptions}.
     * @param headers Additional headers to include in the request.
     * @returns The request configuration.
     */
    getRequestConfig<T, Protected extends boolean = false>(resource: Resource<T, object, Protected>, options?: Partial<ClientOptions>, headers?: Record<string, string>): {
        headers: {
            Authorization: string;
            'Content-Type': string;
            'Battlenet-Namespace'?: string | undefined;
        };
        searchParams: {
            locale: "de_DE" | "en_GB" | "en_US" | "es_ES" | "es_MX" | "fr_FR" | "it_IT" | "ko_KR" | "multi" | "pt_BR" | "pt_PT" | "ru_RU" | "zh_CN" | "zh_TW";
        };
    };
    /**
     * Get the request URL.
     * @param resource The resource to fetch. See {@link Resource}.
     * @param options Client options. See {@link ClientOptions}.
     * @returns The request URL.
     */
    getRequestUrl<T, Protected extends boolean = false>(resource: Resource<T, object, Protected>, options?: Partial<ClientOptions>): string;
    /**
     * Send a request to the Blizzard API.
     * @param resource The resource to fetch. See {@link Resource}.
     * @param options Client options. See {@link ClientOptions}.
     * @param headers Additional headers to include in the request.
     * @returns The response from the Blizzard API. See {@link ResourceResponse}.
     */
    sendRequest<T, Protected extends boolean = false>(resource: Resource<T, object, Protected>, options?: Partial<ClientOptions>, headers?: Record<string, string>): ResourceResponse<AxiosCompatability<T>>;
}

/**
 * Create a new Blizzard API client.
 * @param options Client options, see {@link ClientOptions} & https://develop.battle.net/documentation/guides/getting-started
 * @param onTokenRefresh Callback function to handle token refresh. If set to `true`, the client will automatically refresh the token. If set to `false`, the client will not refresh the token. If set to a function, the function will be called with the new token.
 * @returns A new Blizzard API client.
 */
declare const createBlizzardApiClient: (options: ClientOptions, onTokenRefresh?: ((token: AccessToken) => void) | boolean) => Promise<BlizzardApiClient>;

export { type AccessToken, type AccessTokenRequestArguments, type AxiosCompatability, type ClientOptions, type IBlizzardApiClient, type ValidateAccessTokenArguments, type ValidateAccessTokenResponse, createBlizzardApiClient, createBlizzardApiClient as default };
