/*
 * 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
 */
/**
 * B2C operation lifecycle types for CLI plugin extensibility.
 *
 * This module defines the interfaces for B2C-specific operation lifecycle hooks
 * that allow CLI plugins to observe and control operation execution for jobs,
 * deployments, and other B2C Commerce operations.
 *
 * ## Plugin Usage
 *
 * Plugins implement the `b2c:operation-lifecycle` hook to receive lifecycle events:
 *
 * ```typescript
 * import type { B2COperationLifecycleHook, B2COperationLifecycleProvider } from '@salesforce/b2c-tooling-sdk/cli';
 *
 * const auditProvider: B2COperationLifecycleProvider = {
 *   name: 'audit-logger',
 *   async beforeOperation(context) {
 *     console.log(`Starting ${context.operationType}: ${context.operationId}`);
 *     // Return { skip: true } to prevent execution
 *   },
 *   async afterOperation(context, result) {
 *     console.log(`Completed ${context.operationType}: ${result.success ? 'SUCCESS' : 'FAILED'}`);
 *   },
 * };
 *
 * const hook: B2COperationLifecycleHook = async function() {
 *   return { providers: [auditProvider] };
 * };
 *
 * export default hook;
 * ```
 *
 * @module cli/lifecycle
 */
import { randomUUID } from 'node:crypto';
/**
 * Creates a new B2C operation context for lifecycle hooks.
 *
 * @param operationType - Type of B2C operation
 * @param metadata - Operation-specific metadata
 * @param instance - B2C instance with configured clients
 * @returns New operation context
 */
export function createB2COperationContext(operationType, metadata, instance) {
    return {
        operationType,
        operationId: randomUUID(),
        instance,
        startTime: Date.now(),
        metadata,
    };
}
/**
 * Helper class for running B2C lifecycle hooks in CLI commands.
 *
 * This class is used internally by CLI commands to collect and invoke
 * lifecycle providers from plugins.
 */
export class B2CLifecycleRunner {
    providers = [];
    logger;
    constructor(logger) {
        this.logger = logger;
    }
    /**
     * Adds providers to this runner.
     */
    addProviders(providers) {
        this.providers.push(...providers);
    }
    /**
     * Runs beforeOperation hooks for all providers.
     *
     * @param context - Operation context
     * @returns Aggregated result (skip if any provider requests skip)
     */
    async runBefore(context) {
        const aggregatedResult = {};
        for (const provider of this.providers) {
            if (!provider.beforeOperation)
                continue;
            try {
                const result = await provider.beforeOperation(context);
                if (result?.skip) {
                    this.logger?.debug(`Provider ${provider.name} requested skip: ${result.skipReason}`);
                    return result; // First skip wins
                }
                if (result?.context) {
                    Object.assign(context.metadata, result.context);
                }
            }
            catch (error) {
                // Don't fail the operation on hook errors
                this.logger?.warn(`Lifecycle provider ${provider.name} beforeOperation failed: ${error}`);
            }
        }
        return aggregatedResult;
    }
    /**
     * Runs afterOperation hooks for all providers.
     *
     * @param context - Operation context
     * @param result - Operation result
     */
    async runAfter(context, result) {
        for (const provider of this.providers) {
            if (!provider.afterOperation)
                continue;
            try {
                await provider.afterOperation(context, result);
            }
            catch (error) {
                // Don't fail on hook errors
                this.logger?.warn(`Lifecycle provider ${provider.name} afterOperation failed: ${error}`);
            }
        }
    }
    /**
     * Returns the number of registered providers.
     */
    get size() {
        return this.providers.length;
    }
}
//# sourceMappingURL=lifecycle.js.map