/**
 * Cross-provider object-storage migration.
 *
 * Copies objects from one S3-compatible bucket to another — AWS S3, Backblaze
 * B2, Hetzner Object Storage, in any direction. Both sides are driven by the
 * same {@link createObjectStorageClient}, so the only thing that changes per
 * side is the provider/region/endpoint/credentials.
 *
 * Bytes are copied (not strings) via {@link S3Client.getObjectBytes}, so binary
 * payloads (images, archives, mail attachments) survive intact. Content-Type is
 * preserved when the source reports it.
 *
 * The copy is idempotent: an object already present at the destination with the
 * same size is skipped unless `force` is set. Keys may be remapped by stripping
 * `fromPrefix` and prepending `toPrefix`, and filtered with include/exclude
 * prefix lists so an operator can clearly see what was migrated vs. deliberately
 * left behind.
 */
import type { S3Client } from '../aws/s3';
import type { ObjectStorageProvider } from './index';
/** One side (source or destination) of a migration. */
export interface MigrateEndpoint {
    provider: ObjectStorageProvider;
    bucket: string;
    region?: string;
    /** Endpoint host override (no scheme). Defaults to the provider's standard endpoint. */
    endpoint?: string;
    forcePathStyle?: boolean;
    /** Key prefix. On the source it scopes/strips; on the dest it is prepended. */
    prefix?: string;
    /** Explicit credentials. When omitted, resolved from the provider's env vars. */
    credentials?: {
        accessKeyId: string;
        secretAccessKey: string;
        sessionToken?: string;
    };
    /** Pre-built client (used by tests to inject an in-memory mock). */
    client?: S3Client;
}
export interface MigrateOptions {
    from: MigrateEndpoint;
    to: MigrateEndpoint;
    /** Only copy keys whose (source) key starts with one of these prefixes. */
    include?: string[];
    /** Skip keys whose (source) key starts with one of these prefixes. */
    exclude?: string[];
    /** Plan only — do not write to the destination. */
    dryRun?: boolean;
    /** Re-copy even if the destination already has an object of the same size. */
    force?: boolean;
    /** Delete destination keys (within the dest prefix) that are not in the copied set. Default OFF. */
    deleteExtraneous?: boolean;
    /** Max in-flight copies. Default 8. */
    concurrency?: number;
    /** After copying, re-list the destination and assert counts + sizes match the copied set. */
    verify?: boolean;
    /** Optional progress callback, invoked per object after it is copied/skipped. */
    onProgress?: (event: MigrateProgress) => void;
}
export interface MigrateProgress {
    /** Source key. */
    key: string;
    /** Destination key the object maps to. */
    destKey: string;
    size: number;
    action: 'copied' | 'skipped' | 'excluded' | 'error' | 'planned';
    /** 1-based index of this object within the full source listing. */
    index: number;
    total: number;
}
export interface MigrateError {
    key: string;
    message: string;
}
export interface MigratePlanItem {
    key: string;
    destKey: string;
    size: number;
}
export interface MigrateResult {
    copied: number;
    skipped: number;
    excluded: number;
    bytesCopied: number;
    errors: MigrateError[];
    /** Keys that were excluded by include/exclude filters (source keys). */
    excludedKeys: string[];
    /** Keys deleted from the destination via `deleteExtraneous`. */
    deleted: string[];
    /** When `dryRun` is set, the objects that would be copied. */
    plan?: MigratePlanItem[];
    /** Verification outcome when `verify` is set. */
    verification?: MigrateVerification;
}
export interface MigrateVerification {
    ok: boolean;
    /** Number of (key,size) pairs that matched at the destination. */
    matched: number;
    /** Copied keys missing at the destination. */
    missing: string[];
    /** Copied keys present at the destination but with a different size. */
    sizeMismatches: Array<{
        key: string;
        expected: number;
        actual: number;
    }>;
}
/**
 * Compute the destination key for a source key: strip the source prefix, then
 * prepend the destination prefix. Exported for unit testing.
 */
export declare function remapKey(sourceKey: string, fromPrefix?: string, toPrefix?: string): string;
/**
 * Decide whether a source key passes the include/exclude prefix filters.
 * `include` (when non-empty) is a whitelist; `exclude` always wins. Exported for
 * unit testing.
 */
export declare function keyMatchesFilters(key: string, include?: string[], exclude?: string[]): boolean;
/**
 * Migrate objects from one S3-compatible bucket to another.
 *
 * @returns a structured {@link MigrateResult} so callers (CLI, buddy, scripts)
 * can report exactly what was copied, skipped, excluded, deleted and verified.
 */
export declare function migrateObjectStorage(options: MigrateOptions): Promise<MigrateResult>;
