/*
 * 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
 */
import { Flags } from '@oclif/core';
import { OAuthCommand } from './oauth-command.js';
import { loadConfig, extractInstanceFlags } from './config.js';
import { t } from '../i18n/index.js';
import { B2CLifecycleRunner, createB2COperationContext, } from './lifecycle.js';
/**
 * Base command for B2C instance operations.
 * Use this for commands that interact with a specific B2C instance
 * (sites, code upload, jobs, etc.)
 *
 * Environment variables:
 * - SFCC_SERVER: B2C instance hostname
 * - SFCC_WEBDAV_SERVER: Separate WebDAV hostname (optional)
 * - SFCC_CODE_VERSION: Code version
 * - SFCC_USERNAME: Username for Basic Auth
 * - SFCC_PASSWORD: Password/access key for Basic Auth
 * - Plus all from OAuthCommand (SFCC_CLIENT_ID, SFCC_CLIENT_SECRET)
 *
 * Provides:
 * - Server/hostname connection flags
 * - Both Basic auth and OAuth support
 * - Unified B2CInstance with typed API clients
 *
 * @example
 * export default class MySiteCommand extends InstanceCommand<typeof MySiteCommand> {
 *   async run(): Promise<void> {
 *     // Single instance for all operations
 *     const { data } = await this.instance.ocapi.GET('/sites', {});
 *     await this.instance.webdav.mkcol('Cartridges/v1');
 *   }
 * }
 */
export class InstanceCommand extends OAuthCommand {
    static baseFlags = {
        ...OAuthCommand.baseFlags,
        server: Flags.string({
            char: 's',
            description: 'B2C instance hostname',
            env: 'SFCC_SERVER',
            helpGroup: 'INSTANCE',
        }),
        'webdav-server': Flags.string({
            description: 'Separate hostname for WebDAV (cert. hostname, etc)',
            env: 'SFCC_WEBDAV_SERVER',
            helpGroup: 'INSTANCE',
        }),
        'code-version': Flags.string({
            char: 'v',
            description: 'Code version',
            env: 'SFCC_CODE_VERSION',
            helpGroup: 'INSTANCE',
        }),
        username: Flags.string({
            char: 'u',
            description: 'Username for Basic Auth (WebDAV)',
            env: 'SFCC_USERNAME',
            helpGroup: 'AUTH',
        }),
        password: Flags.string({
            char: 'p',
            description: 'Password/access key for Basic Auth (WebDAV)',
            env: 'SFCC_PASSWORD',
            helpGroup: 'AUTH',
        }),
        certificate: Flags.string({
            description: 'Path to PKCS12 certificate for two-factor auth',
            env: 'SFCC_CERTIFICATE',
            helpGroup: 'AUTH',
        }),
        passphrase: Flags.string({
            description: 'Passphrase for the certificate',
            env: 'SFCC_CERTIFICATE_PASSPHRASE',
            helpGroup: 'AUTH',
        }),
        selfsigned: Flags.boolean({
            description: 'Allow self-signed server certificates',
            env: 'SFCC_SELFSIGNED',
            helpGroup: 'AUTH',
            default: false,
        }),
        verify: Flags.boolean({
            description: 'Verify SSL certificates',
            default: true,
            allowNo: true,
            helpGroup: 'AUTH',
        }),
    };
    _instance;
    /** Lifecycle runner for B2C operation hooks */
    lifecycleRunner;
    /**
     * Override init to collect lifecycle providers from plugins.
     */
    async init() {
        await super.init();
        await this.collectLifecycleProviders();
    }
    /**
     * Collects lifecycle providers from plugins via the `b2c:operation-lifecycle` hook.
     */
    async collectLifecycleProviders() {
        this.lifecycleRunner = new B2CLifecycleRunner(this.logger);
        const hookOptions = {
            flags: this.flags,
        };
        const hookResult = await this.config.runHook('b2c:operation-lifecycle', hookOptions);
        for (const success of hookResult.successes) {
            const result = success.result;
            if (!result?.providers?.length)
                continue;
            this.lifecycleRunner.addProviders(result.providers);
        }
        for (const failure of hookResult.failures) {
            this.logger?.warn(`Plugin ${failure.plugin.name} b2c:operation-lifecycle hook failed: ${failure.error.message}`);
        }
        if (this.lifecycleRunner.size > 0) {
            this.logger?.debug(`Registered ${this.lifecycleRunner.size} lifecycle provider(s)`);
        }
    }
    /**
     * Creates a B2C operation context for lifecycle hooks.
     *
     * @param operationType - Type of B2C operation
     * @param metadata - Operation-specific metadata
     * @returns B2C operation context
     */
    createContext(operationType, metadata) {
        return createB2COperationContext(operationType, metadata, this.instance);
    }
    /**
     * Runs beforeOperation hooks for all providers.
     *
     * @param context - B2C operation context
     * @returns Result indicating if operation should be skipped
     */
    async runBeforeHooks(context) {
        if (!this.lifecycleRunner) {
            return {};
        }
        return this.lifecycleRunner.runBefore(context);
    }
    /**
     * Runs afterOperation hooks for all providers.
     *
     * @param context - B2C operation context
     * @param result - Operation result
     */
    async runAfterHooks(context, result) {
        if (!this.lifecycleRunner) {
            return;
        }
        await this.lifecycleRunner.runAfter(context, result);
    }
    async loadConfiguration() {
        return loadConfig(extractInstanceFlags(this.flags), this.getBaseConfigOptions());
    }
    /**
     * Gets the B2CInstance for this command.
     *
     * The instance is lazily created from the resolved configuration.
     * It provides typed API clients for WebDAV and OCAPI operations.
     *
     * @example
     * // WebDAV operations (uses Basic auth if available)
     * await this.instance.webdav.mkcol('Cartridges/v1');
     *
     * // OCAPI operations (uses OAuth)
     * const { data } = await this.instance.ocapi.GET('/sites', {});
     */
    get instance() {
        if (!this._instance) {
            this.requireServer();
            this._instance = this.resolvedConfig.createB2CInstance();
        }
        return this._instance;
    }
    /**
     * Check if WebDAV credentials are available (Basic or OAuth including implicit).
     */
    hasWebDavCredentials() {
        // Basic auth, or OAuth (client-credentials needs secret, implicit only needs clientId)
        return this.resolvedConfig.hasBasicAuthConfig() || this.resolvedConfig.hasOAuthConfig();
    }
    /**
     * Validates that server is configured, errors if not.
     */
    requireServer() {
        if (!this.resolvedConfig.hasB2CInstanceConfig()) {
            this.error(t('error.serverRequired', 'Server is required. Set via --server, SFCC_SERVER env var, or dw.json.'));
        }
    }
    /**
     * Validates that code version is configured, errors if not.
     */
    requireCodeVersion() {
        if (!this.resolvedConfig.values.codeVersion) {
            this.error(t('error.codeVersionRequired', 'Code version is required. Set via --code-version, SFCC_CODE_VERSION env var, or dw.json.'));
        }
    }
    /**
     * Validates that WebDAV credentials are configured, errors if not.
     */
    requireWebDavCredentials() {
        if (!this.hasWebDavCredentials()) {
            this.error(t('error.webdavCredentialsRequiredShort', 'WebDAV credentials required. Provide --username/--password or --client-id/--client-secret, or set corresponding SFCC_* env vars.'));
        }
    }
}
//# sourceMappingURL=instance-command.js.map