/**
 * ConflictTargetIdentityModels — runtime-backed conflict target identities.
 *
 * @module domain/services/strand/ConflictTargetIdentityModels
 */
import WarpError from "../../errors/WarpError.js";
import { decodeEdgeKey, encodeEdgeKey } from "../KeyCodec.js";
function requireNonEmpty(value, fieldName) {
    if (value.length === 0) {
        throw new WarpError(`ConflictTargetIdentity: ${fieldName} must be non-empty`, 'E_VALIDATION');
    }
    return value;
}
function optionalNonEmpty(value) {
    return value !== null && value.length > 0 ? value : null;
}
export class NodeConflictTargetIdentity {
    targetKind = 'node';
    entityId;
    constructor(entityId) {
        this.entityId = requireNonEmpty(entityId, 'entityId');
        Object.freeze(this);
    }
}
export class EdgeConflictTargetIdentity {
    targetKind = 'edge';
    from;
    to;
    label;
    edgeKey;
    constructor({ from, to, label, edgeKey }) {
        this.from = requireNonEmpty(from, 'from');
        this.to = requireNonEmpty(to, 'to');
        this.label = requireNonEmpty(label, 'label');
        this.edgeKey = requireNonEmpty(edgeKey, 'edgeKey');
        Object.freeze(this);
    }
    static fromParts(from, to, label) {
        return new EdgeConflictTargetIdentity({ from, to, label, edgeKey: encodeEdgeKey(from, to, label) });
    }
    static fromReceiptTarget(receiptTarget) {
        if (receiptTarget === '*') {
            return null;
        }
        const decoded = decodeEdgeKey(receiptTarget);
        return EdgeConflictTargetIdentity.fromOptionalParts({
            from: decoded.from,
            to: decoded.to,
            label: decoded.label,
            edgeKey: receiptTarget,
        });
    }
    static fromOptionalParts({ from, to, label, edgeKey }) {
        const validFrom = optionalNonEmpty(from);
        const validTo = optionalNonEmpty(to);
        const validLabel = optionalNonEmpty(label);
        return validFrom !== null && validTo !== null && validLabel !== null
            ? new EdgeConflictTargetIdentity({ from: validFrom, to: validTo, label: validLabel, edgeKey })
            : null;
    }
}
export class NodePropertyConflictTargetIdentity {
    targetKind = 'node_property';
    entityId;
    propertyKey;
    constructor(entityId, propertyKey) {
        this.entityId = requireNonEmpty(entityId, 'entityId');
        this.propertyKey = requireNonEmpty(propertyKey, 'propertyKey');
        Object.freeze(this);
    }
}
export class EdgePropertyConflictTargetIdentity {
    targetKind = 'edge_property';
    from;
    to;
    label;
    edgeKey;
    propertyKey;
    constructor(edgeIdentity, propertyKey) {
        this.from = edgeIdentity.from;
        this.to = edgeIdentity.to;
        this.label = edgeIdentity.label;
        this.edgeKey = edgeIdentity.edgeKey;
        this.propertyKey = requireNonEmpty(propertyKey, 'propertyKey');
        Object.freeze(this);
    }
}
