/**
 * Dependency Service - Core operations for managing dependencies
 *
 * Provides CRUD operations for dependencies:
 * - addDependency: Create a new dependency between elements
 * - removeDependency: Remove an existing dependency
 * - getDependencies: Get all dependencies from a source element
 * - getDependents: Get all elements that depend on a target
 *
 * All operations emit events for audit trail.
 */
import type { StorageBackend } from '@stoneforge/storage';
import type { Dependency, DependencyType, CreateDependencyInput, ElementId, EntityId, EventWithoutId } from '@stoneforge/core';
/**
 * Configuration for cycle detection
 */
export interface CycleDetectionConfig {
    /** Maximum depth to traverse (default: 100) */
    maxDepth: number;
}
/**
 * Default cycle detection configuration
 */
export declare const DEFAULT_CYCLE_DETECTION_CONFIG: CycleDetectionConfig;
/**
 * Result of cycle detection check
 */
export interface CycleDetectionResult {
    /** Whether a cycle would be created */
    hasCycle: boolean;
    /** Path that forms the cycle (if detected) */
    cyclePath?: ElementId[];
    /** Number of nodes visited during detection */
    nodesVisited: number;
    /** Whether depth limit was reached */
    depthLimitReached: boolean;
}
/**
 * Service for managing dependencies between elements
 */
export declare class DependencyService {
    private readonly db;
    constructor(db: StorageBackend);
    /**
     * Initialize the dependencies table schema
     * Should be called during database setup
     */
    initSchema(): void;
    /**
     * Add a new dependency between elements
     *
     * @param input - Dependency creation input
     * @param cycleConfig - Optional configuration for cycle detection
     * @returns The created dependency
     * @throws ValidationError if input is invalid
     * @throws ConflictError if dependency already exists or would create a cycle
     */
    addDependency(input: CreateDependencyInput, cycleConfig?: CycleDetectionConfig): Dependency;
    /**
     * Remove an existing dependency
     *
     * @param blockedId - Blocked element ID
     * @param blockerId - Blocker element ID
     * @param type - Dependency type
     * @param actor - Entity performing the removal (for events)
     * @returns true if dependency was removed
     * @throws NotFoundError if dependency doesn't exist
     */
    removeDependency(blockedId: ElementId, blockerId: ElementId, type: DependencyType, actor: EntityId): boolean;
    /**
     * Get all dependencies where the given element is blocked
     *
     * @param blockedId - Blocked element ID
     * @param type - Optional filter by dependency type
     * @returns Array of dependencies
     */
    getDependencies(blockedId: ElementId, type?: DependencyType): Dependency[];
    /**
     * Get all bidirectional relates-to dependencies for an element
     * (since relates-to is stored with normalized IDs, we need to check both directions)
     *
     * @param elementId - Element ID
     * @returns Array of relates-to dependencies
     */
    getRelatedTo(elementId: ElementId): Dependency[];
    /**
     * Get all elements that are blocked by a given blocker (reverse lookup)
     *
     * @param blockerId - Blocker element ID
     * @param type - Optional filter by dependency type
     * @returns Array of dependencies where blockerId is the blocker
     */
    getDependents(blockerId: ElementId, type?: DependencyType): Dependency[];
    /**
     * Check if a specific dependency exists
     *
     * @param blockedId - Blocked element ID
     * @param blockerId - Blocker element ID
     * @param type - Dependency type
     * @returns true if dependency exists
     */
    exists(blockedId: ElementId, blockerId: ElementId, type: DependencyType): boolean;
    /**
     * Get a specific dependency by its composite key
     *
     * @param blockedId - Blocked element ID
     * @param blockerId - Blocker element ID
     * @param type - Dependency type
     * @returns The dependency or undefined if not found
     */
    getDependency(blockedId: ElementId, blockerId: ElementId, type: DependencyType): Dependency | undefined;
    /**
     * Get all dependencies for multiple source elements
     *
     * @param blockedIds - Array of blocked element IDs
     * @param type - Optional filter by dependency type
     * @returns Array of dependencies
     */
    getDependenciesForMany(blockedIds: ElementId[], type?: DependencyType): Dependency[];
    /**
     * Remove all dependencies from a source element
     *
     * @param blockedId - Blocked element ID
     * @param type - Optional filter by dependency type
     * @returns Number of dependencies removed
     */
    removeAllDependencies(blockedId: ElementId, type?: DependencyType): number;
    /**
     * Remove all dependencies to a target element (cascade on element delete)
     *
     * @param blockerId - Blocker element ID
     * @returns Number of dependencies removed
     */
    removeAllDependents(blockerId: ElementId): number;
    /**
     * Count dependencies from a source element
     */
    countDependencies(blockedId: ElementId, type?: DependencyType): number;
    /**
     * Count dependents of a target element
     */
    countDependents(blockerId: ElementId, type?: DependencyType): number;
    /**
     * Check if adding a dependency would create a cycle
     *
     * Uses BFS traversal from target to check if source is reachable
     * through existing blocking dependencies. Only blocking dependency
     * types participate in cycle detection (blocks, parent-child, awaits).
     *
     * The relates-to type is excluded because it's bidirectional by design.
     *
     * @param blockedId - The blocked element of the proposed dependency
     * @param blockerId - The blocker element of the proposed dependency
     * @param type - The type of dependency being added
     * @param config - Optional configuration for cycle detection
     * @returns CycleDetectionResult with cycle status and details
     */
    detectCycle(blockedId: ElementId, blockerId: ElementId, type: DependencyType, config?: CycleDetectionConfig): CycleDetectionResult;
    /**
     * Check if adding a dependency would create a cycle and throw if so
     *
     * @param blockedId - The blocked element of the proposed dependency
     * @param blockerId - The blocker element of the proposed dependency
     * @param type - The type of dependency being added
     * @param config - Optional configuration for cycle detection
     * @throws ConflictError if a cycle would be created
     */
    checkForCycle(blockedId: ElementId, blockerId: ElementId, type: DependencyType, config?: CycleDetectionConfig): void;
    /**
     * Get all blocking dependencies from an element
     * (internal helper for cycle detection)
     */
    private getBlockingDependenciesFrom;
    /**
     * Convert a database row to a Dependency object
     */
    private rowToDependency;
}
/**
 * Create a dependency_added event
 *
 * Use this to create an audit event when a dependency is added.
 * The event should be persisted by an EventService.
 *
 * @param dependency - The dependency that was added
 * @returns An EventWithoutId ready to be persisted
 */
export declare function createDependencyAddedEvent(dependency: Dependency): EventWithoutId;
/**
 * Create a dependency_removed event
 *
 * Use this to create an audit event when a dependency is removed.
 * The event should be persisted by an EventService.
 *
 * @param dependency - The dependency that was removed
 * @param actor - The entity that removed the dependency
 * @returns An EventWithoutId ready to be persisted
 */
export declare function createDependencyRemovedEvent(dependency: Dependency, actor: EntityId): EventWithoutId;
/**
 * Create a new DependencyService instance
 */
export declare function createDependencyService(db: StorageBackend): DependencyService;
export type { EventWithoutId } from '@stoneforge/core';
//# sourceMappingURL=dependency.d.ts.map