import { AxiosResponse } from 'axios';
import dayjs, { Dayjs } from 'dayjs';

interface TokenData {
    access_token: string;
    expires_in: number;
    expires_at: string;
    refresh_token: string;
    expires_at_timestamp: number;
}
interface TokenManager {
    read(): Promise<TokenData>;
    write(token: TokenData): Promise<TokenData>;
}

interface DefaultFitbitConfig {
    timeout: number;
    tokenExpiresFactorProcentage: number;
    uris: {
        authorizationUri: string;
        authorizationPath: string;
        tokenUri: string;
        tokenPath: string;
    };
    authorizationUri: {
        scope: string;
        state: string;
    };
}
interface QueuedRequest<T> {
    promise: Promise<AxiosResponse<T>>;
    handler: () => void;
}
interface CompleteFitbitConfig extends DefaultFitbitConfig {
    timeout: number;
    tokenExpiresFactorProcentage: number;
    creds: {
        clientId: string;
        clientSecret: string;
    };
    tokenFilePath?: string;
    uris: {
        authorizationUri: string;
        authorizationPath: string;
        tokenUri: string;
        tokenPath: string;
    };
    authorizationUri: {
        redirectUri: string;
        scope: string;
        state: string;
    };
}
interface FitbitConfig {
    timeout?: number;
    tokenExpiresFactorProcentage?: number;
    creds: {
        clientId: string;
        clientSecret: string;
    };
    tokenFilePath?: string;
    uris?: {
        authorizationUri?: string;
        authorizationPath?: string;
        tokenUri?: string;
        tokenPath?: string;
    };
    authorizationUri: {
        redirectUri: string;
        scope?: string;
        state: string;
    };
}
interface RequestOptions {
    method: 'GET' | 'POST';
    data?: any;
    timeout?: number;
    headers?: Record<string, string>;
    url: string;
}
interface LegacyRequestOptions {
    method: 'GET' | 'POST';
    data?: any;
    timeout?: number;
    headers?: Record<string, string>;
    uri: string;
    url?: string;
}
declare class FitbitBase {
    static setLogger(logger: any): void;
    protected static addExpiresAt(token: TokenData, tokenExpiresFactor: number, requestDateTime?: Date): TokenData;
    protected static createQueuedRequest<T>(options: RequestOptions | LegacyRequestOptions, fitbit: Fitbit): QueuedRequest<T>;
    protected static hasTokenExpired(token: TokenData): boolean;
    static createData(data: any): string;
    protected static normalizeOptions(options: RequestOptions | LegacyRequestOptions, config: CompleteFitbitConfig): RequestOptions;
}
declare class Fitbit extends FitbitBase {
    private _config;
    private _tokenManager;
    private _tokenData;
    private _isTokenRefreshingOrInitiating;
    private _tokenExpiresFactor;
    private _requestQueue;
    private _limits?;
    constructor(config: FitbitConfig, tokenManager?: TokenManager);
    authorizeURL(): string;
    fetchToken(code: string): Promise<TokenData>;
    private internalFetchToken;
    private refresh;
    request<T>(options: RequestOptions | LegacyRequestOptions): Promise<AxiosResponse<T>>;
    protected internalRequest<T>(options: RequestOptions): Promise<AxiosResponse<T>>;
    getLimits(): {
        limit: string;
        remaining: string;
        reset: string;
    } | undefined;
}

declare class FileTokenManager implements TokenManager {
    private tokenFilePath;
    constructor(tokenFilePath: string);
    static setLogger(logger: any): void;
    read(): Promise<TokenData>;
    write(token: TokenData): Promise<TokenData>;
}

interface WeightResponse {
    weight: {
        bmi: number;
        date: string;
        fat: number;
        logId: number;
        source: string;
        time: string;
        weight: number;
    }[];
}
interface BodyFatResponse {
    fat: {
        date: string;
        fat: number;
        logId: number;
        source: string;
        time: string;
    }[];
}
interface ProfileResponse {
    user: {
        age: number;
        ambassador: boolean;
        avatar: string;
        avatar150: string;
        avatar640: string;
        averageDailySteps: number;
        challengesBeta: boolean;
        clockTimeDisplayFormat: string;
        corporate: boolean;
        corporateAdmin: boolean;
        country: string;
        dateOfBirth: string;
        displayName: string;
        displayNameSetting: string;
        distanceUnit: string;
        encodedId: string;
        features: {
            exerciseGoal: boolean;
        };
        firstName: string;
        foodsLocale: string;
        fullName: string;
        gender: string;
        glucoseUnit: string;
        height: number;
        heightUnit: string;
        isBugReportEnabled: boolean;
        isChild: boolean;
        isCoach: boolean;
        languageLocale: string;
        lastName: string;
        legalTermsAcceptRequired: boolean;
        locale: string;
        memberSince: string;
        mfaEnabled: boolean;
        offsetFromUTCMillis: number;
        sdkDeveloper: boolean;
        sleepTracking: string;
        startDayOfWeek: string;
        strideLengthRunning: number;
        strideLengthRunningType: string;
        strideLengthWalking: number;
        strideLengthWalkingType: string;
        swimUnit: string;
        temperatureUnit: string;
        timezone: string;
        topBadges: any[];
        visibleUser: boolean;
        waterUnit: string;
        waterUnitName: string;
        weight: number;
        weightUnit: string;
    };
}
interface LifetimeStatsResponse {
    lifetime: {
        total: {
            activeScore: number;
            caloriesOut: number;
            distance: number;
            steps: number;
        };
        tracker: {
            activeScore: number;
            caloriesOut: number;
            distance: number;
            steps: number;
        };
    };
}
declare class FitbitApi {
    private fitbitClient;
    private apiCallInterceptor?;
    constructor(fitbitClient: Fitbit, apiCallInterceptor?: ((config: RequestOptions | LegacyRequestOptions) => boolean) | undefined);
    static fromUTC: (timestamp: number, tz?: string) => dayjs.Dayjs;
    static getDateTime: (dayjsDateOrTimestamp?: Dayjs | number) => {
        date: string;
        time: string;
    };
    static getDate: (dayjsDateOrTimestamp?: Dayjs | number) => string;
    static getLifetimeStatsUrl: (userId?: string) => string;
    static getProfileUrl: (userId?: string) => string;
    static getBodyFatUrl: (dayjsDateOrTimestamp?: Dayjs | number, userId?: string) => string;
    static getLogBodyFatUrl: (userId?: string) => string;
    static getLogWeightUrl: (userId?: string) => string;
    static getWeightUrl: (dayjsDateOrTimestamp?: Dayjs | number, userId?: string) => string;
    getLifetimeStats: (userId?: string) => Promise<LifetimeStatsResponse>;
    getProfile: (userId?: string) => Promise<ProfileResponse>;
    getBodyFat: (dayjsDateOrTimestamp?: Dayjs | number, userId?: string) => Promise<BodyFatResponse>;
    logBodyFat: (fat: any, dayjsDateOrTimestamp?: Dayjs | number, userId?: string) => Promise<any>;
    logWeight: (weight: any, dayjsDateOrTimestamp?: Dayjs | number, userId?: string) => Promise<any>;
    getWeight: (dayjsDateOrTimestamp?: Dayjs | number, userId?: string) => Promise<WeightResponse>;
}

export { BodyFatResponse, FileTokenManager, Fitbit, FitbitApi, FitbitConfig, LifetimeStatsResponse, ProfileResponse, WeightResponse };
