import { AuthorizationHeaderProvider } from '../../http';
import { telemetry } from '../../Telemetry';
import { SeverityLevel } from '@microsoft/applicationinsights-web';
import { TwinfinityHttpClient, TwinfinitySession } from '@twinfinity/authentication';
import { buildInfo } from '../../BuildInfo';

/**
 * Wraps an {@link AuthorizationHeaderProvider} with error handling and telemetry logging.
 * If the provider throws, the error is logged and `undefined` is returned.
 * @param tokenProvider - The authorization header provider to wrap.
 * @returns A new {@link AuthorizationHeaderProvider} that catches errors and logs them.
 */
export function wrapAuthorizationHeaderProvider(
    tokenProvider: AuthorizationHeaderProvider
): AuthorizationHeaderProvider {
    return {
        getAuthorizationHeader: async () => {
            try {
                return await tokenProvider.getAuthorizationHeader();
            } catch (error) {
                if (error instanceof Error) {
                    telemetry.trackTrace(
                        {
                            severityLevel: SeverityLevel.Error,
                            message: `Failed to fetch authorization header: ${error.message}`,
                            properties: {
                                error
                            }
                        },
                        { ErrorMessage: error.message }
                    );
                } else {
                    telemetry.trackTrace({
                        severityLevel: SeverityLevel.Error,
                        message: 'Failed to fetch authorization header',
                        properties: {
                            error
                        }
                    });
                }
                return undefined;
            }
        }
    };
}

/**
 * Creates a {@link TwinfinityHttpClient} from a session and application name.
 * If a session is provided, creates an authenticated client; otherwise creates an anonymous client.
 * @param options - Options containing optional session and application name.
 * @returns A configured {@link TwinfinityHttpClient}.
 */
export function createTwinfinityHttpClient(options?: {
    session?: { getAuthorizationHeader: () => Promise<string> };
    applicationName?: string;
}): TwinfinityHttpClient {
    const applicationName = options?.applicationName ?? '-unknown-';
    const clientInfo = { clientName: applicationName, clientVersion: buildInfo.version };

    if (options?.session == null) {
        return TwinfinityHttpClient.createAnonymous(clientInfo);
    }

    const sessionForHttpClient = {
        getAuthorizationHeader: async () => {
            const header = await options.session?.getAuthorizationHeader();
            return header ?? '';
        },
        disconnect: () => {}
    } as TwinfinitySession<unknown>;

    return TwinfinityHttpClient.create(clientInfo, sessionForHttpClient);
}
