import type Database from 'better-sqlite3';
import type { ChangedBy, EntityType, VersionDetail, VersionListItem } from '../../shared/entities.js';
import type { PluginHost } from '../core/plugin-host/types.js';
import type { RawEntityReader, RawEntityType } from '../domain/raw-entity-reader.js';
export type VersionOp = 'create' | 'update' | 'delete';
export interface CreateVersionInput {
    entityType: EntityType;
    entityId: number;
    data: unknown;
    changedBy: ChangedBy;
    changeSummary?: string | null;
    /** M17: which kind of mutation. Required for new code; legacy callers omit. */
    op?: VersionOp;
    /** M17: serializer.version at time of capture. Null for legacy rows. */
    serializerVersion?: string | null;
}
export declare class VersionService {
    private db;
    private snapshotDeps;
    constructor(db: Database.Database);
    /** M17: wire snapshot dependencies. Called once during server bootstrap. */
    configureSnapshot(reader: RawEntityReader, host: PluginHost): void;
    /**
     * M17: capture a deterministic snapshot of an entity into entity_version.
     * Falls back to `createVersion(..., entity, ...)` if snapshot deps not wired
     * yet (very early in bootstrap or for tests). For `op = 'delete'`, calls
     * host.snapshot BEFORE the caller deletes the row — pass `previousSnapshot`
     * explicitly to capture a tombstone with last-known data.
     */
    captureEntitySnapshot(type: RawEntityType, entityId: number, op: VersionOp, actor: ChangedBy, summary: string | null, serializerVersion: string): VersionListItem;
    /**
     * Capture a new version. M17 augments the row with `op` and
     * `serializer_version`; `release_id` always starts NULL and is assigned by
     * `releaseService.createRelease()`.
     */
    createVersion(entityType: EntityType, entityId: number, data: unknown, changedBy: ChangedBy, changeSummary?: string | null, op?: VersionOp, serializerVersion?: string | null): VersionListItem;
    listVersions(entityType: EntityType, entityId: number): VersionListItem[];
    getVersion(entityType: EntityType, entityId: number, version: number): VersionDetail | null;
    /**
     * M17: latest captured version of an entity at-or-before a given release.
     * `releaseId === null` returns the latest unreleased capture (release_id IS NULL).
     * `releaseId === undefined` returns the latest overall (no release filter).
     */
    getLatestVersionForEntity(entityType: EntityType, entityId: number, releaseId?: number | null): VersionDetail | null;
    diff(entityType: EntityType, entityId: number, fromVersion: number, toVersion: number): {
        from: VersionDetail;
        to: VersionDetail;
        changes: DiffEntry[];
    };
    private nextVersionNumber;
    private toListItem;
    private toDetail;
}
export interface DiffEntry {
    path: string;
    from: unknown;
    to: unknown;
}
export declare function computeDiff(from: unknown, to: unknown, prefix?: string): DiffEntry[];
