import { createMrtClient, DEFAULT_MRT_ORIGIN } from '../../clients/mrt.js';
import { getLogger } from '../../logging/logger.js';
import { createBundle } from './bundle.js';
/**
 * Pushes a bundle to a Managed Runtime project.
 *
 * This function creates a bundle from the build directory and uploads it
 * to the specified MRT project. Optionally, it can also deploy the bundle
 * to a target environment.
 *
 * @param options - Push configuration options
 * @param auth - Authentication strategy (ApiKeyStrategy)
 * @returns Result of the push operation
 * @throws Error if push fails
 *
 * @example
 * ```typescript
 * import { ApiKeyStrategy } from '@salesforce/b2c-tooling-sdk/auth';
 * import { pushBundle } from '@salesforce/b2c-tooling-sdk/operations/mrt';
 *
 * const auth = new ApiKeyStrategy(process.env.MRT_API_KEY!, 'Authorization');
 *
 * const result = await pushBundle({
 *   projectSlug: 'my-storefront',
 *   ssrOnly: ['ssr.js'],
 *   ssrShared: ['**\/*.js', 'static/**\/*'],
 *   buildDirectory: './build',
 *   message: 'Release v1.0.0',
 *   target: 'staging'  // Optional: deploy after push
 * }, auth);
 *
 * console.log(`Bundle ${result.bundleId} pushed to ${result.projectSlug}`);
 * if (result.deployed) {
 *   console.log(`Deployed to ${result.target}`);
 * }
 * ```
 */
export async function pushBundle(options, auth) {
    const logger = getLogger();
    const { projectSlug, target, origin } = options;
    logger.debug({ projectSlug, target }, '[MRT] Pushing bundle');
    // Create the bundle
    const bundle = await createBundle(options);
    // Create MRT client
    const client = createMrtClient({ origin: origin || DEFAULT_MRT_ORIGIN }, auth);
    // Upload the bundle
    const result = await uploadBundle(client, projectSlug, bundle, target);
    logger.debug({ bundleId: result.bundleId, deployed: result.deployed }, '[MRT] Bundle pushed successfully');
    return result;
}
/**
 * Uploads a pre-created bundle to MRT.
 *
 * Use this if you've already created a bundle and want to upload it separately.
 *
 * @param client - MRT client instance
 * @param projectSlug - Project to upload to
 * @param bundle - Bundle to upload
 * @param target - Optional target to deploy to
 * @returns Result of the upload
 */
export async function uploadBundle(client, projectSlug, bundle, target) {
    const logger = getLogger();
    // Choose endpoint based on whether we're deploying
    if (target) {
        logger.debug({ projectSlug, target }, '[MRT] Uploading and deploying bundle');
        const { data, error } = await client.POST('/api/projects/{project_slug}/builds/{target_slug}/', {
            params: {
                path: {
                    project_slug: projectSlug,
                    target_slug: target,
                },
            },
            body: {
                message: bundle.message,
                encoding: bundle.encoding,
                data: bundle.data,
                ssr_parameters: bundle.ssr_parameters,
                ssr_only: bundle.ssr_only,
                ssr_shared: bundle.ssr_shared,
            },
        });
        if (error) {
            throw new Error(`Failed to push bundle: ${JSON.stringify(error)}`);
        }
        const buildData = data;
        return {
            bundleId: buildData.bundle_id,
            projectSlug,
            target,
            deployed: true,
            message: bundle.message,
        };
    }
    else {
        logger.debug({ projectSlug }, '[MRT] Uploading bundle (no deployment)');
        const { data, error } = await client.POST('/api/projects/{project_slug}/builds/', {
            params: {
                path: {
                    project_slug: projectSlug,
                },
            },
            body: {
                message: bundle.message,
                encoding: bundle.encoding,
                data: bundle.data,
                ssr_parameters: bundle.ssr_parameters,
                ssr_only: bundle.ssr_only,
                ssr_shared: bundle.ssr_shared,
            },
        });
        if (error) {
            throw new Error(`Failed to push bundle: ${JSON.stringify(error)}`);
        }
        const buildData = data;
        buildData.warnings.forEach((warning) => {
            logger.warn(warning);
        });
        return {
            bundleId: buildData.bundle_id,
            projectSlug,
            deployed: false,
            message: bundle.message,
        };
    }
}
/**
 * Lists bundles for an MRT project.
 *
 * @param options - List options including project slug
 * @param auth - Authentication strategy (ApiKeyStrategy)
 * @returns Paginated list of bundles
 * @throws Error if request fails
 *
 * @example
 * ```typescript
 * import { ApiKeyStrategy } from '@salesforce/b2c-tooling-sdk/auth';
 * import { listBundles } from '@salesforce/b2c-tooling-sdk/operations/mrt';
 *
 * const auth = new ApiKeyStrategy(process.env.MRT_API_KEY!, 'Authorization');
 *
 * const result = await listBundles({
 *   projectSlug: 'my-storefront'
 * }, auth);
 *
 * for (const bundle of result.bundles) {
 *   console.log(`Bundle ${bundle.id}: ${bundle.message}`);
 * }
 * ```
 */
export async function listBundles(options, auth) {
    const logger = getLogger();
    const { projectSlug, limit, offset, origin } = options;
    logger.debug({ projectSlug }, '[MRT] Listing bundles');
    const client = createMrtClient({ origin: origin || DEFAULT_MRT_ORIGIN }, auth);
    const { data, error } = await client.GET('/api/projects/{project_slug}/bundles/', {
        params: {
            path: { project_slug: projectSlug },
            query: {
                limit,
                offset,
            },
        },
    });
    if (error) {
        const errorMessage = typeof error === 'object' && error !== null && 'message' in error
            ? String(error.message)
            : JSON.stringify(error);
        throw new Error(`Failed to list bundles: ${errorMessage}`);
    }
    logger.debug({ count: data.count }, '[MRT] Bundles listed');
    return {
        count: data.count ?? 0,
        next: data.next ?? null,
        previous: data.previous ?? null,
        bundles: data.results ?? [],
    };
}
/**
 * Gets a presigned URL to download a bundle archive.
 *
 * The returned URL is valid for one hour.
 *
 * @param options - Download options
 * @param auth - Authentication strategy (ApiKeyStrategy)
 * @returns Download URL result
 * @throws Error if request fails
 *
 * @example
 * ```typescript
 * import { ApiKeyStrategy } from '@salesforce/b2c-tooling-sdk/auth';
 * import { downloadBundle } from '@salesforce/b2c-tooling-sdk/operations/mrt';
 *
 * const auth = new ApiKeyStrategy(process.env.MRT_API_KEY!, 'Authorization');
 *
 * const result = await downloadBundle({
 *   projectSlug: 'my-storefront',
 *   bundleId: 12345
 * }, auth);
 *
 * console.log(`Download URL: ${result.downloadUrl}`);
 * ```
 */
export async function downloadBundle(options, auth) {
    const logger = getLogger();
    const { projectSlug, bundleId, origin } = options;
    logger.debug({ projectSlug, bundleId }, '[MRT] Getting bundle download URL');
    const client = createMrtClient({ origin: origin || DEFAULT_MRT_ORIGIN }, auth);
    const { data, error } = await client.GET('/api/projects/{project_slug}/bundles/{bundle_id}/download/', {
        params: {
            path: { project_slug: projectSlug, bundle_id: String(bundleId) },
        },
    });
    if (error) {
        const errorMessage = typeof error === 'object' && error !== null && 'message' in error
            ? String(error.message)
            : JSON.stringify(error);
        throw new Error(`Failed to get bundle download URL: ${errorMessage}`);
    }
    logger.debug({ bundleId }, '[MRT] Bundle download URL retrieved');
    return {
        downloadUrl: data.download_url,
    };
}
/**
 * Requests deletion of a single bundle. Bundles are deleted asynchronously.
 * Only project admins can perform this operation.
 *
 * @param options - Delete options
 * @param auth - Authentication strategy
 * @throws Error if the request fails
 */
export async function deleteBundle(options, auth) {
    const logger = getLogger();
    const { projectSlug, bundleId, origin } = options;
    logger.debug({ projectSlug, bundleId }, '[MRT] Deleting bundle');
    const client = createMrtClient({ origin: origin || DEFAULT_MRT_ORIGIN }, auth);
    const { error } = await client.DELETE('/api/projects/{project_slug}/bundles/{bundle_id}/', {
        params: {
            path: { project_slug: projectSlug, bundle_id: String(bundleId) },
        },
    });
    if (error) {
        const errorMessage = typeof error === 'object' && error !== null && 'message' in error
            ? String(error.message)
            : JSON.stringify(error);
        throw new Error(`Failed to delete bundle: ${errorMessage}`);
    }
    logger.debug({ bundleId }, '[MRT] Bundle queued for deletion');
}
/**
 * Requests deletion of multiple bundles in a single call.
 *
 * The response indicates which bundles were queued and which were rejected.
 * Only project admins can perform this operation.
 *
 * @param options - Bulk delete options
 * @param auth - Authentication strategy
 * @returns Lists of queued and rejected bundle IDs
 * @throws Error if the request itself fails
 */
export async function bulkDeleteBundles(options, auth) {
    const logger = getLogger();
    const { projectSlug, bundleIds, origin } = options;
    logger.debug({ projectSlug, count: bundleIds.length }, '[MRT] Bulk-deleting bundles');
    const client = createMrtClient({ origin: origin || DEFAULT_MRT_ORIGIN }, auth);
    const { data, error } = await client.POST('/api/projects/{project_slug}/bundles/bulk-delete/', {
        params: {
            path: { project_slug: projectSlug },
        },
        body: { bundle_ids: bundleIds },
    });
    if (error) {
        const errorMessage = typeof error === 'object' && error !== null && 'message' in error
            ? String(error.message)
            : JSON.stringify(error);
        throw new Error(`Failed to bulk-delete bundles: ${errorMessage}`);
    }
    const rejected = (data?.rejected_bundles ?? []).map((entry) => ({
        bundleId: entry.bundle_id,
        reason: entry.errors,
    }));
    return {
        queued: data?.bundles_queued_for_cleanup ?? [],
        rejected,
    };
}
//# sourceMappingURL=push.js.map