/**
 * ConflictTargetResolver — runtime-backed target identity for conflict hashing.
 *
 * @module domain/services/strand/ConflictTargetResolver
 */
import { encodeEdgeKey } from "../KeyCodec.js";
import EdgeAdd from "../../types/ops/EdgeAdd.js";
import EdgePropSet from "../../types/ops/EdgePropSet.js";
import EdgeRemove from "../../types/ops/EdgeRemove.js";
import NodeAdd from "../../types/ops/NodeAdd.js";
import NodePropSet from "../../types/ops/NodePropSet.js";
import NodeRemove from "../../types/ops/NodeRemove.js";
import ConflictOpAnchor from "./ConflictOpAnchor.js";
import { EdgeConflictTargetIdentity, EdgePropertyConflictTargetIdentity, NodeConflictTargetIdentity, NodePropertyConflictTargetIdentity, } from "./ConflictTargetIdentityModels.js";
export default class ConflictTargetResolver {
    static nodeFrom(canonOp) {
        return new NodeConflictTargetIdentity(canonOp.node);
    }
    static edgeFrom(canonOp) {
        return EdgeConflictTargetIdentity.fromParts(canonOp.from, canonOp.to, canonOp.label);
    }
    static nodePropertyFrom(canonOp) {
        return new NodePropertyConflictTargetIdentity(canonOp.node, canonOp.key);
    }
    static edgePropertyFrom(canonOp) {
        return new EdgePropertyConflictTargetIdentity(EdgeConflictTargetIdentity.fromParts(canonOp.from, canonOp.to, canonOp.label), canonOp.key);
    }
    static resolve(canonOp, receiptTarget) {
        if (canonOp instanceof ConflictOpAnchor) {
            return ConflictTargetResolver.anchor(canonOp, receiptTarget);
        }
        return ConflictTargetResolver.runtimeStructural(canonOp)
            ?? ConflictTargetResolver.runtimeProperty(canonOp);
    }
    static runtimeStructural(canonOp) {
        if (canonOp instanceof NodeAdd || canonOp instanceof NodeRemove) {
            return ConflictTargetResolver.nodeFrom(canonOp);
        }
        if (canonOp instanceof EdgeAdd || canonOp instanceof EdgeRemove) {
            return ConflictTargetResolver.edgeFrom(canonOp);
        }
        return null;
    }
    static runtimeProperty(canonOp) {
        if (canonOp instanceof NodePropSet) {
            return ConflictTargetResolver.nodePropertyFrom(canonOp);
        }
        if (canonOp instanceof EdgePropSet) {
            return ConflictTargetResolver.edgePropertyFrom(canonOp);
        }
        return null;
    }
    static anchor(anchor, receiptTarget) {
        if (anchor.type === 'NodeAdd' || anchor.type === 'NodeRemove') {
            return ConflictTargetResolver.nodeAnchor(anchor, receiptTarget);
        }
        if (anchor.type === 'EdgeAdd' || anchor.type === 'EdgeRemove') {
            return ConflictTargetResolver.edgeAnchor(anchor, receiptTarget);
        }
        return ConflictTargetResolver.propertyAnchor(anchor);
    }
    static nodeAnchor(anchor, receiptTarget) {
        const entityId = anchor.node ?? (receiptTarget !== '*' ? receiptTarget : null);
        return entityId !== null ? new NodeConflictTargetIdentity(entityId) : null;
    }
    static edgeAnchor(anchor, receiptTarget) {
        return EdgeConflictTargetIdentity.fromOptionalParts({
            from: anchor.from,
            to: anchor.to,
            label: anchor.label,
            edgeKey: encodeEdgeKey(anchor.from ?? '', anchor.to ?? '', anchor.label ?? ''),
        }) ?? EdgeConflictTargetIdentity.fromReceiptTarget(receiptTarget);
    }
    static propertyAnchor(anchor) {
        return ConflictTargetResolver.nodePropertyAnchor(anchor)
            ?? ConflictTargetResolver.edgePropertyAnchor(anchor);
    }
    static nodePropertyAnchor(anchor) {
        return anchor.type === 'NodePropSet' && anchor.node !== null && anchor.key !== null
            ? new NodePropertyConflictTargetIdentity(anchor.node, anchor.key)
            : null;
    }
    static edgePropertyKey(anchor) {
        return anchor.type === 'EdgePropSet' ? anchor.key : null;
    }
    static edgePropertyBase(anchor) {
        return EdgeConflictTargetIdentity.fromOptionalParts({
            from: anchor.from,
            to: anchor.to,
            label: anchor.label,
            edgeKey: encodeEdgeKey(anchor.from ?? '', anchor.to ?? '', anchor.label ?? ''),
        });
    }
    static edgePropertyAnchor(anchor) {
        const propertyKey = ConflictTargetResolver.edgePropertyKey(anchor);
        if (propertyKey === null) {
            return null;
        }
        const edgeIdentity = ConflictTargetResolver.edgePropertyBase(anchor);
        return edgeIdentity !== null ? new EdgePropertyConflictTargetIdentity(edgeIdentity, propertyKey) : null;
    }
}
