// This file was auto-generated by Fern from our API Definition.

import { BearerAuthProvider } from "./auth/BearerAuthProvider.js";
import * as core from "./core/index.js";
import type * as environments from "./environments.js";

export type AuthOption =
    | false
    | core.AuthProvider["getAuthRequest"]
    | core.AuthProvider
    | BearerAuthProvider.AuthOptions;

export type BaseClientOptions = {
    environment?: core.Supplier<environments.CoinbaseApiEnvironment | string>;
    /** Specify a custom URL to connect the client to. */
    baseUrl?: core.Supplier<string>;
    /** Additional headers to include in requests. */
    headers?: Record<string, string | core.EndpointSupplier<string | null | undefined> | null | undefined>;
    /** The default maximum time to wait for a response in seconds. */
    timeoutInSeconds?: number;
    /** The default number of times to retry the request. Defaults to 2. */
    maxRetries?: number;
    /** Provide a custom fetch implementation. Useful for platforms that don't have a built-in fetch or need a custom implementation. */
    fetch?: typeof fetch;
    /** Configure logging for the client. */
    logging?: core.logging.LogConfig | core.logging.Logger;
    /** The CDP API key ID used to authenticate requests. */
    apiKeyId: string;
    /** The CDP API key secret used to sign the Bearer JWT. */
    apiKeySecret: string;
    /** Optional wallet secret used to sign the X-Wallet-Auth header for wallet-scoped endpoints. */
    walletSecret?: string;
    /** Enables verbose debug logging for auth and request signing. */
    debugging?: boolean;
    /** Override auth. Pass false to disable, a function returning auth headers, an AuthProvider, or auth options. */
    auth?: AuthOption;
} & BearerAuthProvider.AuthOptions;

export interface BaseRequestOptions {
    /** The maximum time to wait for a response in seconds. */
    timeoutInSeconds?: number;
    /** The number of times to retry the request. Defaults to 2. */
    maxRetries?: number;
    /** A hook to abort the request. */
    abortSignal?: AbortSignal;
    /** Additional query string parameters to include in the request. */
    queryParams?: Record<string, unknown>;
    /** Additional headers to include in the request. */
    headers?: Record<string, string | core.EndpointSupplier<string | null | undefined> | null | undefined>;
}

export type NormalizedClientOptions<T extends BaseClientOptions = BaseClientOptions> = T & {
    logging: core.logging.Logger;
    authProvider?: core.AuthProvider;
};

export type NormalizedClientOptionsWithAuth<T extends BaseClientOptions = BaseClientOptions> =
    NormalizedClientOptions<T> & {
        authProvider: core.AuthProvider;
    };

export function normalizeClientOptions<T extends BaseClientOptions = BaseClientOptions>(
    options: T,
): NormalizedClientOptions<T> {
    return {
        ...options,
        logging: core.logging.createLogger(options?.logging),
    } as NormalizedClientOptions<T>;
}

export function normalizeClientOptionsWithAuth<T extends BaseClientOptions = BaseClientOptions>(
    options: T,
): NormalizedClientOptionsWithAuth<T> {
    const normalized = normalizeClientOptions(options) as NormalizedClientOptionsWithAuth<T>;

    if (options.auth === false) {
        normalized.authProvider = new core.NoOpAuthProvider();
        return normalized;
    }
    if (options.auth != null) {
        if (typeof options.auth === "function") {
            normalized.authProvider = { getAuthRequest: options.auth };
            return normalized;
        }
        if (core.isAuthProvider(options.auth)) {
            normalized.authProvider = options.auth;
            return normalized;
        }
        Object.assign(normalized, options.auth);
    }

    const normalizedWithNoOpAuthProvider = withNoOpAuthProvider(normalized);
    normalized.authProvider ??= new BearerAuthProvider(normalizedWithNoOpAuthProvider);
    return normalized;
}

function withNoOpAuthProvider<T extends BaseClientOptions = BaseClientOptions>(
    options: NormalizedClientOptions<T>,
): NormalizedClientOptionsWithAuth<T> {
    return {
        ...options,
        authProvider: new core.NoOpAuthProvider(),
    };
}
