/**
 * Service for managing B2C instances across multiple config sources.
 *
 * This class aggregates instance management operations from all sources
 * that implement the optional instance management methods.
 *
 * @example
 * ```typescript
 * import { InstanceManager, DwJsonSource } from '@salesforce/b2c-tooling-sdk/config';
 *
 * const manager = new InstanceManager([new DwJsonSource()]);
 *
 * // List all instances
 * const instances = manager.listAllInstances();
 *
 * // Create a new instance
 * manager.createInstance({
 *   name: 'staging',
 *   config: { hostname: 'staging.example.com' },
 *   setActive: true,
 * });
 * ```
 */
export class InstanceManager {
    sources;
    constructor(sources) {
        this.sources = sources;
    }
    /**
     * List instances from all sources that implement listInstances().
     *
     * @param options - Resolution options
     * @returns Array of all instances from all sources
     */
    async listAllInstances(options) {
        const allInstances = [];
        for (const source of this.sources) {
            if (source.listInstances) {
                const instances = await source.listInstances(options);
                allInstances.push(...instances);
            }
        }
        return allInstances;
    }
    /**
     * Get sources that can create instances.
     *
     * @returns Array of sources with createInstance() method
     */
    getInstanceSources() {
        return this.sources.filter((s) => s.createInstance);
    }
    /**
     * Get sources that can store a specific credential field.
     *
     * @param field - The credential field to check
     * @returns Array of sources that can store the field
     */
    getCredentialSources(field) {
        return this.sources.filter((s) => s.credentialFields?.includes(field));
    }
    /**
     * Create an instance in the specified source (or default to first instance source).
     *
     * @param options - Instance creation options
     * @param targetSource - Source name to use (optional, defaults to first available)
     * @throws Error if no instance sources available or specified source not found
     */
    async createInstance(options, targetSource) {
        const instanceSources = this.getInstanceSources();
        if (instanceSources.length === 0) {
            throw new Error('No config sources support instance creation');
        }
        let source;
        if (targetSource) {
            const found = instanceSources.find((s) => s.name === targetSource);
            if (!found) {
                throw new Error(`Source "${targetSource}" not found or does not support instance creation`);
            }
            source = found;
        }
        else {
            // Default to first (highest priority) instance source
            source = instanceSources[0];
        }
        await source.createInstance(options);
    }
    /**
     * Remove an instance from the source that contains it.
     *
     * @param name - Instance name to remove
     * @param options - Resolution options
     * @throws Error if instance not found in any source
     */
    async removeInstance(name, options) {
        // Find the source that has this instance
        for (const source of this.sources) {
            if (source.listInstances && source.removeInstance) {
                const instances = await source.listInstances(options);
                if (instances.some((i) => i.name === name)) {
                    await source.removeInstance(name, options);
                    return;
                }
            }
        }
        throw new Error(`Instance "${name}" not found in any source`);
    }
    /**
     * Set an instance as active in the source that contains it.
     *
     * @param name - Instance name to set as active
     * @param options - Resolution options
     * @throws Error if instance not found in any source
     */
    async setActiveInstance(name, options) {
        // Find the source that has this instance
        for (const source of this.sources) {
            if (source.listInstances && source.setActiveInstance) {
                const instances = await source.listInstances(options);
                if (instances.some((i) => i.name === name)) {
                    await source.setActiveInstance(name, options);
                    return;
                }
            }
        }
        throw new Error(`Instance "${name}" not found in any source`);
    }
    /**
     * Store a credential for an instance in the specified source.
     *
     * @param instanceName - Instance name
     * @param field - Config field to store
     * @param value - Value to store
     * @param targetSource - Source name to use (optional)
     * @param options - Resolution options
     * @throws Error if no credential sources support the field
     */
    async storeCredential(instanceName, field, value, targetSource, options) {
        const credentialSources = this.getCredentialSources(field);
        if (credentialSources.length === 0) {
            throw new Error(`No config sources support storing credential field "${String(field)}"`);
        }
        let source;
        if (targetSource) {
            const found = credentialSources.find((s) => s.name === targetSource);
            if (!found) {
                throw new Error(`Source "${targetSource}" not found or does not support credential storage`);
            }
            source = found;
        }
        else {
            source = credentialSources[0];
        }
        await source.storeCredential(instanceName, field, value, options);
    }
}
/**
 * Create an InstanceManager with the given sources.
 *
 * @param sources - Config sources to use
 * @returns InstanceManager instance
 */
export function createInstanceManager(sources) {
    return new InstanceManager(sources);
}
//# sourceMappingURL=instance-manager.js.map