import { IChangeSource } from './integration-change-source.protocol.js';
import { ICursorStore } from './integration-cursor-store.protocol.js';
import { IFieldDiffer } from './integration-field-diff.protocol.js';
import { IIntegrationSink } from './integration-sink.protocol.js';
import { IIntegrationRunRecorder } from './integration-run-recorder.protocol.js';
import 'zod';

interface ExecuteIntegrationInput<T> {
    /** The subscription whose cursor/identity frames this run. */
    readonly subscription: {
        readonly id: string;
        readonly domain: string;
        readonly externalRef?: string | null;
    };
    /** Per-run user context; threaded through sink writes. */
    readonly userId: string;
    /** Provider label persisted on saved rows, e.g. `'salesforce-crm'`. */
    readonly provider: string;
    /** Run direction — almost always `'inbound'`. Reserved for writeback. */
    readonly direction: 'inbound' | 'outbound';
    /** Detection mode — maps 1:1 to `integration_runs.action`. */
    readonly action: 'poll' | 'cdc' | 'webhook' | 'manual' | 'writeback';
    /** Multi-tenant deployments pass the tenant id through. */
    readonly tenantId?: string | null;
    /**
     * Optional override — inject a specific change source for this run when
     * the DI-bound source is not the one to use (e.g. manual backfill with
     * a custom cursor). Defaults to the DI-resolved `INTEGRATION_CHANGE_SOURCE`.
     */
    readonly sourceOverride?: IChangeSource<T>;
}
interface ExecuteIntegrationResult {
    readonly runId: string;
    readonly status: 'success' | 'no_changes' | 'failed';
    readonly recordsFound: number;
    readonly recordsProcessed: number;
    readonly recordsFailed: number;
    readonly cursorBefore: unknown | null;
    readonly cursorAfter: unknown | null;
    readonly durationMs: number;
    readonly error?: string | null;
}
declare class ExecuteIntegrationUseCase<T extends Record<string, unknown>> {
    private readonly source;
    private readonly cursors;
    private readonly differ;
    private readonly sink;
    private readonly recorder;
    private readonly multiTenant;
    private readonly logger;
    constructor(source: IChangeSource<T>, cursors: ICursorStore, differ: IFieldDiffer<T>, sink: IIntegrationSink<T>, recorder: IIntegrationRunRecorder, multiTenant?: boolean);
    execute(input: ExecuteIntegrationInput<T>): Promise<ExecuteIntegrationResult>;
    private processChange;
}

export { type ExecuteIntegrationInput, type ExecuteIntegrationResult, ExecuteIntegrationUseCase };
