/*
 * Copyright (c) 2025, Salesforce, Inc.
 * SPDX-License-Identifier: Apache-2
 * For full license text, see the license.txt file in the repo root or http://www.apache.org/licenses/LICENSE-2.0
 */
/**
 * Custom APIs DX API client for B2C Commerce.
 *
 * Provides a fully typed client for Custom APIs DX API operations using
 * openapi-fetch with OAuth authentication middleware. Used for retrieving
 * the status of deployed Custom API endpoints.
 *
 * @module clients/custom-apis
 */
import createClient, {} from 'openapi-fetch';
import { OAuthStrategy } from '../auth/oauth.js';
import { JwtOAuthStrategy } from '../auth/oauth-jwt.js';
import { createAuthMiddleware, createLoggingMiddleware } from './middleware.js';
import { globalMiddlewareRegistry } from './middleware-registry.js';
/** Default OAuth scopes required for Custom APIs (read-only) */
export const CUSTOM_APIS_DEFAULT_SCOPES = ['sfcc.custom-apis'];
/**
 * Creates a typed Custom APIs DX API client.
 *
 * Returns the openapi-fetch client directly, with authentication
 * handled via middleware. This gives full access to all openapi-fetch
 * features with type-safe paths, parameters, and responses.
 *
 * The client automatically handles OAuth scope requirements:
 * - Domain scope: `sfcc.custom-apis` (or custom via config.scopes)
 * - Tenant scope: `SALESFORCE_COMMERCE_API:{tenantId}`
 *
 * @param config - Custom APIs client configuration including shortCode and tenantId
 * @param auth - Authentication strategy (typically OAuth)
 * @returns Typed openapi-fetch client
 *
 * @example
 * // Create Custom APIs client - scopes are handled automatically
 * const oauthStrategy = new OAuthStrategy({
 *   clientId: 'your-client-id',
 *   clientSecret: 'your-client-secret',
 * });
 *
 * const client = createCustomApisClient(
 *   { shortCode: 'kv7kzm78', tenantId: 'zzxy_prd' },
 *   oauthStrategy
 * );
 *
 * // Get all Custom API endpoints
 * const { data, error } = await client.GET('/organizations/{organizationId}/endpoints', {
 *   params: {
 *     path: { organizationId: toOrganizationId('zzxy_prd') }
 *   }
 * });
 */
export function createCustomApisClient(config, auth) {
    const registry = config.middlewareRegistry ?? globalMiddlewareRegistry;
    const client = createClient({
        baseUrl: `https://${config.shortCode}.api.commercecloud.salesforce.com/dx/custom-apis/v1`,
    });
    // Build required scopes: domain scope + tenant-specific scope
    const requiredScopes = config.scopes ?? [...CUSTOM_APIS_DEFAULT_SCOPES, buildTenantScope(config.tenantId)];
    // If auth supports scopes, add required scopes; otherwise use as-is
    const scopedAuth = auth instanceof OAuthStrategy || auth instanceof JwtOAuthStrategy
        ? auth.withAdditionalScopes(requiredScopes)
        : auth;
    // Core middleware: auth first
    client.use(createAuthMiddleware(scopedAuth));
    // Plugin middleware from registry
    for (const middleware of registry.getMiddleware('custom-apis')) {
        client.use(middleware);
    }
    // Logging middleware last (sees complete request with all modifications)
    client.use(createLoggingMiddleware('CUSTOM-APIS'));
    return client;
}
/** Prefix required for SCAPI organizationId */
export const ORGANIZATION_ID_PREFIX = 'f_ecom_';
/** Prefix for tenant-specific SCAPI OAuth scopes */
export const SCAPI_TENANT_SCOPE_PREFIX = 'SALESFORCE_COMMERCE_API:';
/**
 * Ensures a tenant ID has the required f_ecom_ prefix for use as an SCAPI organizationId.
 * If the value already has the prefix, it's returned as-is.
 *
 * @param tenantId - The tenant ID (e.g., "zzxy_prd" or "f_ecom_zzxy_prd")
 * @returns The organization ID with the f_ecom_ prefix (e.g., "f_ecom_zzxy_prd")
 *
 * @example
 * toOrganizationId('zzxy_prd')        // Returns 'f_ecom_zzxy_prd'
 * toOrganizationId('f_ecom_zzxy_prd') // Returns 'f_ecom_zzxy_prd' (unchanged)
 */
export function toOrganizationId(tenantId) {
    return `${ORGANIZATION_ID_PREFIX}${normalizeTenantId(tenantId)}`;
}
/**
 * Normalizes any parseable tenant/organization ID form to the canonical underscore format.
 *
 * Supported input forms (all resolve to `abcd_123`):
 * - `abcd_123` — canonical tenant ID (returned as-is)
 * - `abcd-123` — hyphenated tenant ID
 * - `f_ecom_abcd_123` — organization ID
 * - `f_ecom_abcd-123` — org ID with hyphenated tenant
 * - `abcd-123.dx.commercecloud.salesforce.com` — sandbox hostname
 *
 * @param value - The tenant ID, organization ID, or hostname
 * @returns The normalized tenant ID in canonical underscore format (e.g., "abcd_123")
 *
 * @example
 * normalizeTenantId('f_ecom_zzxy_prd') // Returns 'zzxy_prd'
 * normalizeTenantId('zzxy-prd')        // Returns 'zzxy_prd'
 * normalizeTenantId('zzxy-prd.dx.commercecloud.salesforce.com') // Returns 'zzxy_prd'
 */
export function normalizeTenantId(value) {
    let id = value.trim();
    // Extract hostname prefix: "abcd-123.dx.commercecloud.salesforce.com" → "abcd-123"
    if (id.includes('.')) {
        id = id.split('.')[0];
    }
    // Strip f_ecom_ prefix (handles org ID form)
    if (id.startsWith(ORGANIZATION_ID_PREFIX)) {
        id = id.slice(ORGANIZATION_ID_PREFIX.length);
    }
    // Convert hyphens to underscores
    id = id.replaceAll('-', '_');
    return id;
}
/**
 * Builds the tenant-specific OAuth scope required for SCAPI APIs.
 *
 * @param tenantId - The tenant ID (with or without f_ecom_ prefix)
 * @returns The tenant-specific scope (e.g., "SALESFORCE_COMMERCE_API:zzxy_prd")
 *
 * @example
 * buildTenantScope('zzxy_prd')        // Returns 'SALESFORCE_COMMERCE_API:zzxy_prd'
 * buildTenantScope('f_ecom_zzxy_prd') // Returns 'SALESFORCE_COMMERCE_API:zzxy_prd'
 */
export function buildTenantScope(tenantId) {
    return `${SCAPI_TENANT_SCOPE_PREFIX}${normalizeTenantId(tenantId)}`;
}
//# sourceMappingURL=custom-apis.js.map