import ContinuumArtifactAuthority from "./ContinuumArtifactAuthority.js";
import ContinuumFamilyId from "./ContinuumFamilyId.js";
import WarpError from "../errors/WarpError.js";
/** Runtime-backed descriptor for a generated Continuum family artifact. */
export default class ContinuumArtifactDescriptor {
    familyId;
    sourceSchemaPath;
    generatedBy;
    artifactKind;
    authority;
    targets;
    version;
    witnessScope;
    artifactDigest;
    schemaHash;
    sourceHash;
    integrityStatus;
    integrityScope;
    hashAlgorithm;
    signatureAlgorithm;
    signatureKeyId;
    generatedLegs;
    generatedFiles;
    constructor(fields) {
        const { familyId, sourceSchemaPath, generatedBy, artifactKind, authority, targets } = fields;
        this.familyId = normalizeFamilyId(familyId);
        this.sourceSchemaPath = requireNonEmptyString(sourceSchemaPath, 'sourceSchemaPath');
        this.generatedBy = requireNonEmptyString(generatedBy, 'generatedBy');
        this.artifactKind = requireNonEmptyString(artifactKind, 'artifactKind');
        this.authority = normalizeAuthority(authority);
        this.targets = freezeTargets(targets);
        this.version = optionalNonEmptyString(fields.version, 'version');
        this.witnessScope = optionalNonEmptyString(fields.witnessScope, 'witnessScope');
        this.artifactDigest = optionalNonEmptyString(fields.artifactDigest, 'artifactDigest');
        this.schemaHash = optionalNonEmptyString(fields.schemaHash, 'schemaHash');
        this.sourceHash = optionalNonEmptyString(fields.sourceHash, 'sourceHash');
        this.integrityStatus = optionalNonEmptyString(fields.integrityStatus, 'integrityStatus');
        this.integrityScope = optionalNonEmptyString(fields.integrityScope, 'integrityScope');
        this.hashAlgorithm = optionalNonEmptyString(fields.hashAlgorithm, 'hashAlgorithm');
        this.signatureAlgorithm = optionalNonEmptyString(fields.signatureAlgorithm, 'signatureAlgorithm');
        this.signatureKeyId = optionalNonEmptyString(fields.signatureKeyId, 'signatureKeyId');
        this.generatedLegs = optionalStringArray(fields.generatedLegs, 'generatedLegs');
        this.generatedFiles = optionalStringArray(fields.generatedFiles, 'generatedFiles');
        Object.freeze(this);
    }
    /** Returns true when the descriptor includes the requested generation target. */
    hasTarget(target) {
        return this.targets.includes(target);
    }
    /** Returns true when the artifact may be used as generated authority. */
    hasGeneratedAuthority() {
        return this.authority.isGeneratedAuthority();
    }
}
/** Normalizes a family id carrier. */
function normalizeFamilyId(value) {
    if (value instanceof ContinuumFamilyId) {
        return value;
    }
    return new ContinuumFamilyId(value);
}
/** Normalizes an authority carrier. */
function normalizeAuthority(value) {
    if (value instanceof ContinuumArtifactAuthority) {
        return value;
    }
    return new ContinuumArtifactAuthority(value);
}
/** Validates a required non-empty string. */
function requireNonEmptyString(value, name) {
    if (typeof value !== 'string' || value.length === 0) {
        throw new WarpError(`${name} must be a non-empty string`, 'E_VALIDATION');
    }
    return value;
}
/** Validates an optional non-empty string. */
function optionalNonEmptyString(value, name) {
    if (value === undefined) {
        return undefined;
    }
    return requireNonEmptyString(value, name);
}
/** Freezes and validates a generated target list. */
function freezeTargets(targets) {
    if (!Array.isArray(targets) || targets.length === 0) {
        throw new WarpError('targets must contain at least one generated target', 'E_VALIDATION');
    }
    return freezeStringArray(targets, 'targets[]');
}
/** Validates an optional generated string list. */
function optionalStringArray(value, name) {
    if (value === undefined) {
        return undefined;
    }
    if (!Array.isArray(value)) {
        throw new WarpError(`${name} must be a string array`, 'E_VALIDATION');
    }
    return freezeStringArray(value, `${name}[]`);
}
/** Freezes and validates a generated string list. */
function freezeStringArray(values, name) {
    const normalized = [];
    for (const value of values) {
        normalized.push(requireNonEmptyString(value, name));
    }
    return Object.freeze(normalized);
}
