import { Requestor } from '@net-vert/core';
import { UnifiedRequestor } from '@net-vert/core';

declare class BigFileUploader implements Uploader {
    file: File;
    private _status;
    tasks: UploadTask[];
    totalChunks: number;
    fileInfo: any | null;
    constructor(file: File);
    start(): Promise<any>;
    private preupload;
    private uploadFile;
    private uploadChunks;
    setTask(chunk: UploadChunk, index: number): void;
    private mergeChunks;
    pause(): void;
    cancel(): void;
    get progressInfo(): {
        total: number;
        loaded: number;
        progress: number;
    };
    get status(): STATUS;
}

declare type ChunkParams = {
    /** 原始文件 */
    file: File;
    /** 切片起始位置 */
    start: number;
    /** 切片结束位置 */
    end: number;
    /** 配置的切片大小 */
    chunkSize: number;
};

export declare const config: (cfg: UserConfig) => {
    requestor: Requestor;
};

export declare function createFileUploader(file: File): SimpleFileUploader | BigFileUploader;

declare type Pool = {
    add: (id: string, task: Task) => Promise<any>;
    remove: (id: string) => void;
} & Record<string, any>;

declare interface PoolConfig {
    /** 并发上传的切片数量 */
    parallelCount?: number;
    /** 每个分片上传失败后的最大重试次数 */
    retries?: number;
}

declare type ProgressInfo = {
    loaded: number;
    total: number;
    progress: number;
};

declare type SetTask = (chunk: UploadChunk, index: number) => void;

declare class SimpleFileUploader implements Uploader {
    file: File;
    private _status;
    tasks: UploadTask[];
    fileInfo: any | null;
    constructor(file: File);
    start(): Promise<any>;
    private uploadFile;
    pause(): void;
    cancel(): void;
    get progressInfo(): ProgressInfo;
    get status(): STATUS;
}

declare type SliceFile = (e: ChunkParams, callBack: SetTask) => Promise<UploadChunk[]>;

export declare enum STATUS {
    PREPARING = "preparing",//准备中,可能有增强文件信息需要异步获取
    PREPARE_FAILED = "prepare_failed",// 准备失败状态
    PENDING = "pending",//上传前，没点击开始上传
    PAUSE = "pause",//上传暂停
    UPLOADING = "uploading",//上传中
    SUCCESS = "success",//上传成功
    FAIL = "fail"
}

declare type Task = () => Promise<any>;

declare enum TASK_STATUS {
    PENDING = "pending",//等待中
    SUCCESS = "success",
    FAIL = "fail"
}

declare interface UploadChunk {
    /** 文件数据 */
    readonly chunk: Blob;
    /** 文件位序 */
    readonly index: number;
    /** 开始位置 */
    readonly start: number;
    /** 结束位置 */
    readonly end: number;
    /** 文件大小 */
    readonly size: number;
    /** 文件哈希 */
    readonly hash?: string;
}

declare interface UploadConfig<N extends Number = number, R extends any = any> {
    /** 最大允许上传的文件大小（单位：字节）, 若开启 mergeApi, 超过会走大文件上传 */
    maxSize: N;
    /**
     * 切片大小（单位：字节），默认建议 1~10MB
     * 注意: 当自定义 sliceFile 函数时，应当遵循此处设置的 chunkSize 值进行切片
     * 如果必须使用不同的切片大小，请确保上传逻辑能够正确处理
     */
    chunkSize: N | number;
    /** hash 接口（可选） */
    hashApi?: (hash: string) => boolean | Promise<boolean>;
    /** 自定义hash计算函数 */
    hashcalculation?: (blob: Blob) => string | Promise<string>;
    /** 多线程计算 */
    multiThread: boolean;
    /** 请求者 */
    requestor: Requestor;
    /**
     * 上传接口地址
     */
    uploadUrl: string;
    /**
     * 上传接口方式
     */
    uploadMethod: "get" | "post" | "delete" | "put";
    /**
     * 上传前处理钩子
     * 用于处理上传数据，返回最终发送的数据
     * @param chunk 上传块信息
     * @returns 处理后的请求数据
     */
    beforeUpload?: (chunk: UploadChunk, uploader: Uploader) => FormData | Record<string, any> | Promise<FormData | Record<string, any>>;
    /**
     * 合并切片接口地址（可选）
     */
    mergeApi?: (results: R[], uploader: Uploader) => any | Promise<any>;
    /**
     * 合并前处理钩子（可选）
     * 用于处理合并请求的数据
     * @param results 所有切片上传成功的结果数组
     * @returns 处理后的合并请求数据
     */
    beforeMerge?: (results: R[], uploader: Uploader) => any | Promise<any>;
    /**
     * 自定义文件切片
     * @param file 要切片的文件
     * @param chunkSize 配置中指定的切片大小，建议遵循此值
     * @param callback 每个切片的回调函数
     */
    sliceFile: SliceFile;
    /**
     * 异步文件信息提供器（可选）
     * 在上传开始前异步获取或增强文件信息
     * @param file 原始文件对象
     * @returns Promise 返回原始File或增强的文件信息
     */
    prepareFileInfo?: (file: File) => Promise<any>;
    /** 自定义并发池 */
    pool: Pool;
}

export declare interface Uploader {
    progressInfo: ProgressInfo;
    status: UploadStatus;
    tasks: UploadTask[];
    file: File;
    start: () => Promise<void>;
    pause: () => void;
    cancel: () => void;
}

export declare interface Uploader {
    progressInfo: ProgressInfo;
    status: UploadStatus;
    tasks: UploadTask[];
    file: File;
    fileInfo: any;
    start: () => Promise<void>;
    pause: () => void;
    cancel: () => void;
}

declare type UploadStatus = STATUS;

declare interface UploadTask<T = any> {
    /** 唯一任务标识 */
    readonly id: string;
    /** 任务进度 0-任务大小 */
    progressInfo: ProgressInfo;
    /** 任务状态 */
    status: TASK_STATUS;
    /** 剩余重试次数 */
    /** 取消控制器 */
    controller: AbortController;
    /** 执行任务 */
    execute: () => Promise<T>;
    /** 取消任务 */
    cancel: () => void;
    /** 暂停任务 */
    pause: () => void;
    /** 文件元数据 */
    metadata: UploadChunk;
    /** 父上传器信息 */
    uploader: Uploader;
    /** 当前任务promise */
    promise: Promise<T>;
}

declare interface UploadTask<T = any> {
    /** 唯一任务标识 */
    readonly id: string;
    /** 任务进度 0-任务大小 */
    progressInfo: ProgressInfo;
    /** 任务状态 */
    status: TASK_STATUS;
    /** 剩余重试次数 */
    /** 取消控制器 */
    controller: AbortController;
    /** 执行任务 */
    execute: () => Promise<T>;
    /** 取消任务 */
    cancel: () => void;
    /** 暂停任务 */
    pause: () => void;
    /** 文件元数据 */
    metadata: UploadChunk;
    /** 当前任务promise */
    promise: Promise<T>;
}

declare type UserConfig<R extends any = any> = UserRequestConfig & PoolConfig & Partial<UploadConfig<number, R>>;

declare type UserRequestConfig = {
    /** 接口 请求体 */
    request: UnifiedRequestor;
    uploadUrl: string;
};

export { }
