/*
 * Copyright (c) 2023-2025 Datalayer, Inc.
 * Distributed under the terms of the Modified BSD License.
 */
/**
 * OAuth2 API functions for the Datalayer platform.
 *
 * Provides functions for OAuth2 authorization flows with various providers.
 *
 * @module api/iam/oauth2
 */
import { requestDatalayerAPI } from '../DatalayerApi.js';
import { API_BASE_PATHS, DEFAULT_SERVICE_URLS } from '../constants.js';
/**
 * Get the OAuth2 authorization URL for a specific provider
 * @param provider - OAuth2 provider (bluesky, github, linkedin, okta)
 * @param callbackUri - Server endpoint to call with the authz token
 * @param nonce - Optional nonce for security
 * @param baseUrl - Base URL for the API (defaults to production IAM URL)
 * @returns OAuth2 authorization URL response
 * @throws {Error} If required parameters are missing or invalid
 *
 * @remarks
 * This endpoint generates the OAuth2 authorization URL for the specified provider.
 * Users should be redirected to the returned loginURL to begin the OAuth2 flow.
 *
 * Expected status codes:
 * - 200: Successfully generated authorization URL
 * - 400: Invalid parameters
 * - 404: Provider not found or not configured
 */
export const getOAuth2AuthzUrl = async (provider, callbackUri, nonce, baseUrl = DEFAULT_SERVICE_URLS.IAM) => {
    if (!provider) {
        throw new Error('OAuth2 provider is required');
    }
    if (!callbackUri) {
        throw new Error('Callback URI is required');
    }
    // Build query parameters
    const queryParams = new URLSearchParams({
        provider,
        callback_uri: callbackUri,
    });
    if (nonce) {
        queryParams.append('nonce', nonce);
    }
    try {
        const response = await requestDatalayerAPI({
            url: `${baseUrl}${API_BASE_PATHS.IAM}/oauth2/authz/url?${queryParams.toString()}`,
            method: 'GET',
        });
        return response;
    }
    catch (error) {
        // Check if it's a response error with status code information
        if (error.response) {
            const status = error.response.status;
            // Expected errors
            if (status === 400) {
                throw new Error(`Invalid OAuth2 parameters: ${error.message}`);
            }
            if (status === 404) {
                throw new Error(`OAuth2 provider '${provider}' not found or not configured`);
            }
            // Unexpected status codes
            throw new Error(`Failed to get OAuth2 authorization URL: ${status} - ${error.message}`);
        }
        // Re-throw other errors (network errors, etc.)
        throw error;
    }
};
/**
 * Get the OAuth2 authorization URL for linking a provider to an existing account
 * @param provider - OAuth2 provider (bluesky, github, linkedin, okta)
 * @param callbackUri - Server endpoint to call with the authz token
 * @param baseUrl - Base URL for the API (defaults to production IAM URL)
 * @returns OAuth2 authorization URL response
 * @throws {Error} If required parameters are missing or invalid
 *
 * @remarks
 * This endpoint generates the OAuth2 authorization URL for linking a provider to an existing account.
 * Users should be redirected to the returned loginURL to begin the OAuth2 linking flow.
 * This is different from the regular OAuth2 login flow as it links the provider to an existing account.
 *
 * Expected status codes:
 * - 200: Successfully generated authorization URL
 * - 400: Invalid parameters
 * - 404: Provider not found or not configured
 */
export const getOAuth2AuthzUrlForLink = async (provider, callbackUri, baseUrl = DEFAULT_SERVICE_URLS.IAM) => {
    if (!provider) {
        throw new Error('OAuth2 provider is required');
    }
    if (!callbackUri) {
        throw new Error('Callback URI is required');
    }
    // Build query parameters
    const queryParams = new URLSearchParams({
        provider,
        callback_uri: callbackUri,
    });
    try {
        const response = await requestDatalayerAPI({
            url: `${baseUrl}${API_BASE_PATHS.IAM}/oauth2/authz/url/link?${queryParams.toString()}`,
            method: 'GET',
        });
        return response;
    }
    catch (error) {
        // Check if it's a response error with status code information
        if (error.response) {
            const status = error.response.status;
            // Expected errors
            if (status === 400) {
                throw new Error(`Invalid OAuth2 link parameters: ${error.message}`);
            }
            if (status === 404) {
                throw new Error(`OAuth2 provider '${provider}' not found or not configured for linking`);
            }
            // Unexpected status codes
            throw new Error(`Failed to get OAuth2 link authorization URL: ${status} - ${error.message}`);
        }
        // Re-throw other errors (network errors, etc.)
        throw error;
    }
};
/**
 * Handle GitHub OAuth2 callback
 * @param params - OAuth2 callback parameters
 * @param baseUrl - Base URL for the API (defaults to production IAM URL)
 * @returns HTML response from the callback handler
 * @throws {Error} If state parameter is missing
 * @throws {Error} If the callback fails
 *
 * @remarks
 * This endpoint handles the callback from GitHub after the user authorizes the application.
 * It returns HTML content that typically includes JavaScript to handle the OAuth flow completion.
 *
 * Expected status codes:
 * - 200: Callback processed successfully (returns HTML)
 * - 403: Unauthorized
 */
export const handleGitHubOAuth2Callback = async (params, baseUrl = DEFAULT_SERVICE_URLS.IAM) => {
    if (!params.state) {
        throw new Error('State parameter is required for OAuth2 callback');
    }
    // Build query parameters
    const queryParams = new URLSearchParams();
    queryParams.append('state', params.state);
    if (params.code) {
        queryParams.append('code', params.code);
    }
    if (params.error) {
        queryParams.append('error', params.error);
    }
    if (params.error_description) {
        queryParams.append('error_description', params.error_description);
    }
    if (params.error_uri) {
        queryParams.append('error_uri', params.error_uri);
    }
    try {
        const response = await requestDatalayerAPI({
            url: `${baseUrl}${API_BASE_PATHS.IAM}/oauth2/github/callback?${queryParams.toString()}`,
            method: 'GET',
            // Note: This endpoint returns HTML, not JSON
            headers: {
                Accept: 'text/html',
            },
        });
        return response;
    }
    catch (error) {
        // Check if it's a response error with status code information
        if (error.response) {
            const status = error.response.status;
            // Expected errors
            if (status === 403) {
                throw new Error(`GitHub OAuth2 callback unauthorized: ${error.message}`);
            }
            // Unexpected status codes
            throw new Error(`GitHub OAuth2 callback failed: ${status} - ${error.message}`);
        }
        // Re-throw other errors (network errors, etc.)
        throw error;
    }
};
/**
 * Handle LinkedIn OAuth2 callback
 * @param params - OAuth2 callback parameters
 * @param baseUrl - Base URL for the API (defaults to production IAM URL)
 * @returns HTML response from the callback handler
 * @throws {Error} If state parameter is missing
 * @throws {Error} If the callback fails
 *
 * @remarks
 * This endpoint handles the callback from LinkedIn after the user authorizes the application.
 * It returns HTML content that typically includes JavaScript to handle the OAuth flow completion.
 *
 * Expected status codes:
 * - 200: Callback processed successfully (returns HTML)
 * - 403: Unauthorized
 */
export const handleLinkedInOAuth2Callback = async (params, baseUrl = DEFAULT_SERVICE_URLS.IAM) => {
    if (!params.state) {
        throw new Error('State parameter is required for OAuth2 callback');
    }
    // Build query parameters
    const queryParams = new URLSearchParams();
    queryParams.append('state', params.state);
    if (params.code) {
        queryParams.append('code', params.code);
    }
    if (params.error) {
        queryParams.append('error', params.error);
    }
    if (params.error_description) {
        queryParams.append('error_description', params.error_description);
    }
    if (params.error_uri) {
        queryParams.append('error_uri', params.error_uri);
    }
    try {
        const response = await requestDatalayerAPI({
            url: `${baseUrl}${API_BASE_PATHS.IAM}/oauth2/linkedin/callback?${queryParams.toString()}`,
            method: 'GET',
            // Note: This endpoint returns HTML, not JSON
            headers: {
                Accept: 'text/html',
            },
        });
        return response;
    }
    catch (error) {
        // Check if it's a response error with status code information
        if (error.response) {
            const status = error.response.status;
            // Expected errors
            if (status === 403) {
                throw new Error(`LinkedIn OAuth2 callback unauthorized: ${error.message}`);
            }
            // Unexpected status codes
            throw new Error(`LinkedIn OAuth2 callback failed: ${status} - ${error.message}`);
        }
        // Re-throw other errors (network errors, etc.)
        throw error;
    }
};
/**
 * Handle Okta OAuth2 callback
 * @param params - OAuth2 callback parameters
 * @param baseUrl - Base URL for the API (defaults to production IAM URL)
 * @returns HTML response from the callback handler
 * @throws {Error} If state parameter is missing
 * @throws {Error} If the callback fails
 *
 * @remarks
 * This endpoint handles the callback from Okta after the user authorizes the application.
 * It returns HTML content that typically includes JavaScript to handle the OAuth flow completion.
 *
 * Expected status codes:
 * - 200: Callback processed successfully (returns HTML)
 * - 403: Unauthorized
 */
export const handleOktaOAuth2Callback = async (params, baseUrl = DEFAULT_SERVICE_URLS.IAM) => {
    if (!params.state) {
        throw new Error('State parameter is required for OAuth2 callback');
    }
    // Build query parameters
    const queryParams = new URLSearchParams();
    queryParams.append('state', params.state);
    if (params.code) {
        queryParams.append('code', params.code);
    }
    if (params.error) {
        queryParams.append('error', params.error);
    }
    if (params.error_description) {
        queryParams.append('error_description', params.error_description);
    }
    if (params.error_uri) {
        queryParams.append('error_uri', params.error_uri);
    }
    try {
        const response = await requestDatalayerAPI({
            url: `${baseUrl}${API_BASE_PATHS.IAM}/oauth2/okta/callback?${queryParams.toString()}`,
            method: 'GET',
            // Note: This endpoint returns HTML, not JSON
            headers: {
                Accept: 'text/html',
            },
        });
        return response;
    }
    catch (error) {
        // Check if it's a response error with status code information
        if (error.response) {
            const status = error.response.status;
            // Expected errors
            if (status === 403) {
                throw new Error(`Okta OAuth2 callback unauthorized: ${error.message}`);
            }
            // Unexpected status codes
            throw new Error(`Okta OAuth2 callback failed: ${status} - ${error.message}`);
        }
        // Re-throw other errors (network errors, etc.)
        throw error;
    }
};
