import { extractErrorMsg } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
import { GLOBAL_LOG_A_LOT } from '../core-constants.mjs';
import { KeystoneReplenishStrategy, KeystoneChallengeType, } from './keystone-types.mjs';
import { POOL_ID_REVOKE, KEYSTONE_CONFIG_DEFAULT_SIZE, KEYSTONE_CONFIG_DEFAULT_BINDING, KEYSTONE_CONFIG_DEFAULT_REPLENISH_STRATEGY, KEYSTONE_CONFIG_DEFAULT_SEQUENTIAL, KEYSTONE_CONFIG_DEFAULT_RANDOM, KEYSTONE_CONFIG_DEFAULT_SIZE_HIGHSECURITY, KEYSTONE_CONFIG_DEFAULT_SEQUENTIAL_HIGHSECURITY, KEYSTONE_CONFIG_DEFAULT_RANDOM_HIGHSECURITY, KEYSTONE_CONFIG_DEFAULT_BINDING_HIGHSECURITY, KEYSTONE_CONFIG_DEFAULT_REPLENISH_STRATEGY_HIGHSECURITY, KeystoneVerb, KEYSTONE_CONFIG_DEFAULT_HASH_ALGORITHM, KEYSTONE_CONFIG_DEFAULT_HASH_ROUNDS, KEYSTONE_CONFIG_DEFAULT_HASH_ALGORITHM_HIGHSECURITY, KEYSTONE_CONFIG_DEFAULT_HASH_ROUNDS_HIGHSECURITY, POOL_ID_SYNC, POOL_ID_CONNECT, POOL_ID_MANAGE } from './keystone-constants.mjs';
const logalot = GLOBAL_LOG_A_LOT;
/**
 * Abstract Base Builder.
 * Handles configuration common to ALL strategies (Salt, Size, Replenishment, Selection).
 *
 * @template TConfig The concrete config type being built.
 */
export class KeystoneConfigBuilderBase {
    _id;
    _salt;
    _size;
    _replenish;
    _seq;
    _rand;
    _verbs = [];
    _targetBinding;
    /**
     * Sets the unique id for this pool.
     */
    withId(id) {
        this._id = id;
        return this;
    }
    /**
     * Sets the unique salt for this pool.
     */
    withSalt(salt) {
        this._salt = salt;
        return this;
    }
    /**
     * Sets the total number of challenges to maintain in the pool.
     */
    withSize(size) {
        this._size = size;
        return this;
    }
    /**
    * Binds challenge selection to the content address of the target.
    * @param chars Number of hex characters to match (e.g. 4).
    */
    withTargetBinding(chars) {
        this._targetBinding = chars;
        return this;
    }
    /**
     * Configures the pool to use strictly Sequential (FIFO) selection.
     * @param count Number of challenges to consume per sign.
     */
    withFIFO(count) {
        this._seq = count;
        this._rand = 0;
        return this;
    }
    /**
     * Configures the pool to use strictly Random selection.
     * @param count Number of challenges to consume per sign.
     */
    withRandom(count) {
        this._seq = 0;
        this._rand = count;
        return this;
    }
    /**
     * Configures the pool to use Hybrid (Both FIFO and Random) selection.
     */
    withHybrid({ seqCount, randCount }) {
        this._seq = seqCount;
        this._rand = randCount;
        return this;
    }
    /**
     * Sets the replenishment strategy.
     */
    withReplenishStrategy(strategy) {
        this._replenish = strategy;
        return this;
    }
    /**
     * Constructs the behavioral config object.
     * Helper for subclasses.
     */
    buildBehavior() {
        if (this._size === undefined) {
            throw new Error(`size required (E: 68320865d9adb8477836485b20b08826)`);
        }
        if (this._replenish === undefined) {
            throw new Error(`replenish strategy required (E: 9f8798d1a568763a282e53c89185b826)`);
        }
        if (this._seq === undefined) {
            throw new Error(`sequential required (E: e0da08a24e9790d0a8c1a9322f8eb826)`);
        }
        if (this._rand === undefined) {
            throw new Error(`selectRandomly required (E: 7721d84d1a8b7d020d0ab33c3f811426)`);
        }
        if (this._targetBinding === undefined) {
            throw new Error(`targetBinding required (E: 9add64d7e8e8cba01d901727a8e9b826)`);
        }
        return {
            size: this._size,
            replenish: this._replenish,
            selectSequentially: this._seq,
            selectRandomly: this._rand,
            targetBindingCount: this._targetBinding,
        };
    }
    /**
     * Restricts this pool to specific verbs.
     * @param verbs List of verb addresses (e.g. 'revoke^gib')
     */
    forVerbs(verbs) {
        this._verbs = verbs;
        return this;
    }
}
/**
 * Concrete Builder for Hash-Reveal V1 Strategy.
 */
export class KeystoneConfigBuilder_HashV1 extends KeystoneConfigBuilderBase {
    lc = `[${KeystoneConfigBuilder_HashV1}]`;
    _algo;
    _rounds;
    /**
     * Sets the hashing strength.
     */
    withHash({ algo, rounds }) {
        const lc = `${this.lc}[${this.withHash.name}]`;
        try {
            if (logalot) {
                console.log(`${lc} starting... (I: 15d1b3bd2e98bba33fc6c78228755826)`);
            }
            this._algo = algo;
            this._rounds = rounds;
            return this;
        }
        catch (error) {
            console.error(`${lc} ${extractErrorMsg(error)}`);
            throw error;
        }
        finally {
            if (logalot) {
                console.log(`${lc} complete.`);
            }
        }
    }
    build() {
        const lc = `${this.lc}[${this.build.name}]`;
        try {
            if (logalot) {
                console.log(`${lc} starting... (I: 5df568c63c4993bb98df0a319ee16826)`);
            }
            if (!this._id) {
                throw new Error(`id required (E: b50d082adf38bcbf463552f80d2c3226)`);
            }
            if (!this._salt) {
                throw new Error(`salt required (E: b0f1926657b8d7d3a88fb9385ead5826)`);
            }
            if (!this._algo) {
                throw new Error(`algorithm required (E: cff228f9898fd6383ef752088dae6826)`);
            }
            if (this._rounds === undefined) {
                throw new Error(`rounds required (E: eb72580f3b014cda18cba3e399683c26)`);
            }
            const result = {
                id: this._id,
                type: KeystoneChallengeType.hash_reveal_v1,
                salt: this._salt,
                allowedVerbs: this._verbs,
                behavior: this.buildBehavior(),
                algo: this._algo,
                rounds: this._rounds,
            };
            return result;
        }
        catch (error) {
            console.error(`${lc} ${extractErrorMsg(error)}`);
            throw error;
        }
        finally {
            if (logalot) {
                console.log(`${lc} complete.`);
            }
        }
    }
}
// ===========================================================================
// STATIC ENTRY POINT (Optional Convenience)
// ===========================================================================
export class KeystoneConfig {
    static hash() {
        return new KeystoneConfigBuilder_HashV1();
    }
}
export function createStandardPoolConfig(opts) {
    if (opts.type && opts.type !== KeystoneChallengeType.hash_reveal_v1) {
        throw new Error(`invalid type (${opts.type}). Only ${KeystoneChallengeType.hash_reveal_v1} currently implemented. (E: c38616cd7a459149f670418f88766526)`);
    }
    const { salt, id, size, sequential, random, targetBinding, replenishStrategy, verbs, hashAlgorithm, hashRounds, } = opts;
    return KeystoneConfig.hash()
        .withId(id)
        .withSalt(salt)
        .withSize(size ?? KEYSTONE_CONFIG_DEFAULT_SIZE)
        .withHybrid({
        seqCount: sequential ?? KEYSTONE_CONFIG_DEFAULT_SEQUENTIAL,
        randCount: random ?? KEYSTONE_CONFIG_DEFAULT_RANDOM,
    })
        .withTargetBinding(targetBinding ?? KEYSTONE_CONFIG_DEFAULT_BINDING)
        .withReplenishStrategy(replenishStrategy ?? KEYSTONE_CONFIG_DEFAULT_REPLENISH_STRATEGY)
        .withHash({
        algo: hashAlgorithm ?? KEYSTONE_CONFIG_DEFAULT_HASH_ALGORITHM,
        rounds: hashRounds ?? KEYSTONE_CONFIG_DEFAULT_HASH_ROUNDS
    })
        .forVerbs(verbs ?? [])
        .build();
}
export function createHighSecurityPoolConfig(opts) {
    if (opts.type && opts.type !== KeystoneChallengeType.hash_reveal_v1) {
        throw new Error(`invalid type (${opts.type}). Only ${KeystoneChallengeType.hash_reveal_v1} currently implemented. (E: 09c1f7772bd2a7910f5562b4934d3826)`);
    }
    const { salt, id, size, sequential, random, targetBinding, replenishStrategy, verbs, hashAlgorithm, hashRounds, } = opts;
    return KeystoneConfig.hash()
        .withId(id)
        .withSalt(salt)
        .withSize(size ?? KEYSTONE_CONFIG_DEFAULT_SIZE_HIGHSECURITY)
        .withHybrid({
        seqCount: sequential ?? KEYSTONE_CONFIG_DEFAULT_SEQUENTIAL_HIGHSECURITY,
        randCount: random ?? KEYSTONE_CONFIG_DEFAULT_RANDOM_HIGHSECURITY,
    })
        .withTargetBinding(targetBinding ?? KEYSTONE_CONFIG_DEFAULT_BINDING_HIGHSECURITY)
        .withReplenishStrategy(replenishStrategy ?? KEYSTONE_CONFIG_DEFAULT_REPLENISH_STRATEGY_HIGHSECURITY)
        .withHash({
        algo: hashAlgorithm ?? KEYSTONE_CONFIG_DEFAULT_HASH_ALGORITHM_HIGHSECURITY,
        rounds: hashRounds ?? KEYSTONE_CONFIG_DEFAULT_HASH_ROUNDS_HIGHSECURITY
    })
        .forVerbs(verbs ?? [])
        .build();
}
export function createManagePoolConfig(opts) {
    return createHighSecurityPoolConfig({
        ...opts,
        id: opts.id ?? POOL_ID_MANAGE,
        verbs: opts.verbs ?? [KeystoneVerb.MANAGE],
    });
}
export function createRevocationPoolConfig(opts) {
    return createHighSecurityPoolConfig({
        ...opts,
        id: opts.id ?? POOL_ID_REVOKE,
        verbs: opts.verbs ?? [KeystoneVerb.REVOKE],
        replenishStrategy: opts.replenishStrategy ?? KeystoneReplenishStrategy.deleteAll,
    });
}
export function createSyncPoolConfig(opts) {
    return createStandardPoolConfig({
        ...opts,
        id: opts.id ?? POOL_ID_SYNC,
        verbs: opts.verbs ?? [KeystoneVerb.SYNC],
    });
}
export function createConnectPoolConfig(opts) {
    return createStandardPoolConfig({
        ...opts,
        id: opts.id ?? POOL_ID_CONNECT,
        verbs: opts.verbs ?? [KeystoneVerb.CONNECT],
        replenishStrategy: opts.replenishStrategy ?? KeystoneReplenishStrategy.deleteAll,
    });
}
/**
 * Builds a KeystonePoolConfig from a JSON-sourced KeystonePoolTemplate.
 */
export function createPoolConfigFromJson({ template, salt }) {
    const behavior = template.behavior;
    return KeystoneConfig.hash()
        .withId(template.id)
        .withSalt(salt)
        .withSize(behavior.size)
        .withHybrid({
        seqCount: behavior.selectSequentially,
        randCount: behavior.selectRandomly,
    })
        .withTargetBinding(behavior.targetBindingCount)
        .withReplenishStrategy(behavior.replenish)
        .withHash({
        algo: template.algo,
        rounds: template.rounds
    })
        .forVerbs(template.allowedVerbs)
        .build();
}
//# sourceMappingURL=keystone-config-builder.mjs.map