import type { DbDataSource, LocationUri, StorageAction } from './squared';

import type { ExternalAsset, StreamAction } from './asset';
import type { ExecuteAction } from './db';

export interface UploadAction {
    cloudUrl?: string;
}

export interface RecursiveAction {
    recursive?: boolean;
}

export interface CloudAsset<T = CloudStorage> extends ExternalAsset, UploadAction, StorageAction<T> {}

export interface CloudService<T = unknown, U = string> {
    service: U;
    credential?: T;
}

export interface CloudDatabase<T = unknown, U = PlainObject, V = unknown, W = unknown, X = unknown> extends CloudService<X>, Omit<DbDataSource<T, U, V>, "credential" | "parallel" | "withCommand" | "usePool">, ExecuteAction<W> {
    id?: string;
}

export interface CloudStorage<T = unknown, U = string> extends CloudService<T, U> {
    bucket?: string;
    admin?: CloudStorageAdmin;
    upload?: CloudStorageUpload;
    download?: CloudStorageDownload;
}

export interface CloudStorageAdmin<T = unknown, U = string, V = unknown, W = unknown, X = unknown, Y = unknown> extends CloudStorageACL<U> {
    emptyBucket?: boolean | DeleteObjectsOptions;
    configBucket?: {
        create?: T;
        policy?: V;
        tags?: unknown;
        website?: BucketWebsiteOptions;
        retentionPolicy?: W;
        cors?: X;
        lifecycle?: Y;
    };
    /** @deprecated */
    recursive?: boolean;
    preservePath?: boolean;
}

export interface CloudStorageAction<T = unknown, U = string, V = unknown, W = unknown, X = unknown, Y = unknown> extends Partial<LocationUri>, StreamAction {
    active?: boolean;
    overwrite?: boolean;
    chunkSize?: number | string;
    chunkLimit?: number;
    flags?: number;
    admin?: CloudStorageAdmin<T, U, V, W, X, Y>;
}

export interface CloudStorageUpload<T = unknown, U = string, V = unknown, W = string, X = unknown, Y = unknown, Z = unknown, A = unknown> extends CloudStorageACL<U>, CloudStorageAction<V, W, unknown, X, Y, Z>, CopyObjectAction<A> {
    buffer?: Buffer | null;
    contentType?: string;
    metadata?: Record<string, string>;
    tags?: Record<string, string> | false;
    options?: T;
    fileGroup?: UploadContent[];
    descendantsGroup?: string[];
    localStorage?: boolean;
    endpoint?: string;
    all?: boolean;
}

export interface CloudStorageACL<T = string> {
    publicRead?: boolean | 0;
    acl?: T;
}

export interface CloudStorageDownload<T = unknown, U = unknown, V = unknown> extends CloudStorageAction, CopyObjectAction<V> {
    keyname?: string;
    versionId?: string;
    options?: U;
    deleteObject?: T;
    waitStatus?: boolean;
}

export interface BucketWebsiteOptions {
    indexPage?: string;
    errorPage?: string;
    indexPath?: string;
    errorPath?: string;
}

export interface DeleteObjectsOptions extends RecursiveAction, PlainObject {}

export interface CopyObjectOptions extends PlainObject {}

export interface UploadData<T = unknown, U = string, V = unknown, W = string, X = unknown, Y = unknown, Z = unknown, A = unknown> extends BucketAction {
    upload: CloudStorageUpload<T, U, V, W, X, Y, Z, A>;
    localUri: string;
    buffer: Buffer;
}

export interface DownloadData<T = unknown, U = unknown, V = unknown> extends BucketAction {
    download: CloudStorageDownload<T, U, V>;
}

export interface BucketAction {
    bucket: string;
}

export interface CopyObjectAction<T = PlainObject> {
    copyObject?: ArrayOf<BucketAction & Partial<LocationUri> & { options?: T }>;
}

export interface UploadAssetOptions {
    contentType?: string;
    ignoreProcess?: boolean;
    preferBuffer?: boolean;
}

export type UploadContent = [Bufferable, string, string?];
export type CloudSource = "atlas" | "aws" | "aws-v3" | "az" | "azure" | "gcp" | "gcloud" | "oci";
export type CloudFeatures = "storage" | "database";
export type CloudFunctions = "upload" | "download";
export type CloudLogMessageType = "SUCCESS" | "FAIL" | "COMMAND" | "WARN" | "UPLOAD" | "DOWNLOAD" | "DELETE" | "DELAYED";