import type { File } from '../../../../shared/contracts/files';
export interface FileUploadError {
    name: string;
    message: string;
}
export type FileProgressStatus = 'pending' | 'uploading' | 'complete' | 'error' | 'cancelled';
/**
 * AI metadata generation phase for a single row, tracked independently from the
 * upload status: a metadata failure never turns a successful upload into an error.
 * `undefined` means the row has no metadata phase at all, i.e. AI metadata is
 * disabled — non-images do get a phase and come back `skipped` from the server.
 */
export type FileMetadataStatus = 'generating' | 'generated' | 'skipped' | 'failed';
export type FileMetadataResultStatus = Exclude<FileMetadataStatus, 'generating'>;
export interface FileProgress {
    name: string;
    index: number;
    status: FileProgressStatus;
    size: number;
    uploadedBytes: number;
    file?: File;
    error?: string;
    metadataStatus?: FileMetadataStatus;
}
export interface UploadProgressState {
    isVisible: boolean;
    isMinimized: boolean;
    totalFiles: number;
    files: FileProgress[];
    errors: FileUploadError[];
    uploadId: number;
}
export interface RootState {
    uploadProgress: UploadProgressState;
}
/**
 * Byte-weighted aggregate progress across the whole batch: `sum(uploadedBytes) / sum(size)`.
 *
 * Falls back to count-based progress (settled files / total files) when all sizes are
 * zero — e.g. URL-flow rows where the file size is unknown up front.
 */
export declare const selectAggregateProgress: ((state: RootState) => number) & import("reselect").OutputSelectorFields<(args_0: FileProgress[]) => number, {
    clearCache: () => void;
}> & {
    clearCache: () => void;
};
/**
 * Count-based metadata progress across the whole batch: `settled / expected`.
 *
 * Count-based rather than byte-weighted because the generation endpoint answers in one
 * go — there is no intermediate progress to weight.
 *
 * The denominator is every row *expected* to enter the phase, not just those that
 * already have. Generation is fired per file as each upload finishes, so counting only
 * started rows made the denominator grow mid-batch and the percentage jump backwards
 * (1/1 = 100%, then a second row starts and it drops to 1/2 = 50%), which flickered the
 * header subtitle on and off once per file.
 *
 * "Expected" is derived from upload outcome rather than from the AI-metadata flag:
 *  - a row still uploading may yet enter the phase, so it counts toward the total;
 *  - an errored or cancelled row never will, so it must not — otherwise a batch with
 *    one failure could never reach 100%.
 *
 * Returns `null` when nothing has entered the phase and nothing is pending — i.e. AI
 * metadata is off, or the batch is done — so the header can hide the subtitle.
 */
export declare const selectMetadataProgress: ((state: RootState) => number | null) & import("reselect").OutputSelectorFields<(args_0: FileProgress[]) => number | null, {
    clearCache: () => void;
}> & {
    clearCache: () => void;
};
/**
 * Whether the metadata phase is still ongoing for the batch as a whole.
 *
 * The header uses this — not `selectMetadataProgress === 100` — to decide when to drop
 * the subtitle. Two distinct reasons the phase can be unfinished:
 *  - a row is generating right now;
 *  - no row is generating this instant, but rows are still uploading and will enter the
 *    phase when they finish.
 *
 * The second clause is what keeps the subtitle stable. Generation for file N typically
 * finishes before file N+1 finishes uploading, so a naive "is anything generating?"
 * check goes false between every pair of files and blinks the subtitle out and back in.
 */
export declare const selectIsGeneratingMetadata: ((state: RootState) => boolean) & import("reselect").OutputSelectorFields<(args_0: FileProgress[]) => boolean, {
    clearCache: () => void;
}> & {
    clearCache: () => void;
};
/**
 * How many rows reached each terminal metadata outcome, for the header's completion
 * message. `null` while the phase is unfinished — or was never entered at all — so the
 * caller has a single check for "there is no settled outcome to report yet".
 *
 * Counts are reported separately rather than collapsed into one total because they are
 * not interchangeable: only `generated` rows actually had metadata written, so only that
 * count can be claimed as a success. A batch of non-images settles entirely on `skipped`,
 * where "generated on 0 files" would be worse than saying nothing.
 */
export declare const selectMetadataOutcome: ((state: RootState) => {
    generated: number;
    skipped: number;
    failed: number;
} | null) & import("reselect").OutputSelectorFields<(args_0: FileProgress[]) => {
    generated: number;
    skipped: number;
    failed: number;
} | null, {
    clearCache: () => void;
}> & {
    clearCache: () => void;
};
export declare const openUploadProgress: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
    totalFiles: number;
    fileNames: string[];
    fileSizes?: number[];
}, "uploadProgress/openUploadProgress">, setFileUploading: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
    name: string;
    index: number;
    size: number;
}, "uploadProgress/setFileUploading">, setFileProgress: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
    index: number;
    bytes: number;
}, "uploadProgress/setFileProgress">, setFileComplete: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
    index: number;
    file: File;
}, "uploadProgress/setFileComplete">, setFileError: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
    index: number;
    name: string;
    message: string;
}, "uploadProgress/setFileError">, setFileMetadataGenerating: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
    index: number;
    uploadId: number;
}, "uploadProgress/setFileMetadataGenerating">, setFileMetadataResult: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
    index: number;
    uploadId: number;
    status: FileMetadataResultStatus;
}, "uploadProgress/setFileMetadataResult">, addUploadErrors: import("@reduxjs/toolkit").ActionCreatorWithPayload<FileUploadError[], "uploadProgress/addUploadErrors">, closeUploadProgress: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"uploadProgress/closeUploadProgress">, toggleMinimize: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"uploadProgress/toggleMinimize">, cancelUpload: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"uploadProgress/cancelUpload">, setUploadFailed: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
    message: string;
}, "uploadProgress/setUploadFailed">, retryCancelledFiles: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"uploadProgress/retryCancelledFiles">;
export declare const uploadProgressReducer: import("redux").Reducer<UploadProgressState>;
