import { EventEmitter } from 'events';

type APIConfig = {
    apiUrl: string;
    uploadUrl: string;
};
type BucketConfig = {
    bucketSlug: string;
    readKey: string;
    writeKey?: string;
    apiVersion?: 'v3';
    apiEnvironment?: 'staging' | 'production';
    custom?: APIConfig;
};

interface GenerateTextOptions {
    prompt?: string;
    media_url?: string;
    model?: string;
    max_tokens?: number;
    stream?: boolean;
    messages?: Array<{
        role: 'user' | 'assistant';
        content: string;
    }>;
}
interface GenerateImageOptions {
    prompt: string;
    model?: string;
    metadata?: Record<string, any>;
    folder?: string;
    alt_text?: string;
}
interface TextGenerationResponseBase {
    text: string;
    usage: {
        input_tokens: number;
        output_tokens: number;
    };
}
type TextGenerationResponse = TextGenerationResponseBase;
interface ImageGenerationResponse {
    media: {
        id: string;
        name: string;
        original_name: string;
        size: number;
        type: string;
        bucket: string;
        created_at: string;
        created_by: string | null;
        modified_at: string;
        modified_by: string | null;
        width: number;
        height: number;
        alt_text?: string;
        url: string;
        imgix_url: string;
        metadata?: Record<string, any>;
        folder?: string | null;
    };
    revised_prompt: string;
}
/**
 * A class for handling streaming text generation responses
 * with an Anthropic-like API.
 */
declare class TextStreamingResponse extends EventEmitter implements TextGenerationResponseBase {
    private stream;
    private usageInfo;
    text: string;
    constructor(stream: any);
    private setupListeners;
    /**
     * Get the usage information if available
     */
    get usage(): any;
    /**
     * Implement AsyncIterator interface to support for-await loops
     */
    [Symbol.asyncIterator](): {
        next: () => Promise<IteratorResult<any>>;
    };
}

type GenericObject = Record<string, any>;
type NonEmptyObject<T extends Record<string, unknown>> = T extends Record<string, never> ? never : T;

type InsertMediaType = {
    media: any;
    folder?: string;
    metadata?: GenericObject;
    trigger_webhook?: boolean;
};

type PromiseFn<T> = (value: any) => T | PromiseLike<T>;
type PromiseFnType<T> = PromiseFn<T> | null;

declare class MethodChaining {
    endpoint: string;
    opts: any;
    constructor(endpoint: string);
    props(props: string | Array<string>): this;
    private parseGraphQLProps;
    sort(sort: string): this;
    skip(skip: number): this;
    useCache(): this;
}

declare class FindOneChaining$2 extends MethodChaining {
    then<FulfilledResult = any, RejectedResult = never>(onFulfilled?: PromiseFnType<FulfilledResult>, onRejected?: PromiseFnType<RejectedResult>): Promise<void>;
}

declare class FindChaining$2 extends MethodChaining {
    limit(limit: number): this;
    then<FulfilledResult = any, RejectedResult = never>(onFulfilled?: PromiseFnType<FulfilledResult>, onRejected?: PromiseFnType<RejectedResult>): Promise<void>;
}

type InsertObjectRevisionType = {
    title?: string;
    slug?: string;
    content?: string;
    publish_at?: number;
    unpublish_at?: number;
    metadata?: GenericObject;
    locale?: string;
    thumbnail?: string;
    trigger_webhook?: boolean;
    pretty?: boolean;
};

/**
 * Options for fetching object data.
 * @property {Object} media - Options for media objects.
 * @property {string} media.props - Comma-separated list of additional properties to fetch for media objects.
 * @typedef {Object} MediaType
 * @property {string} all - All media properties.
 * @property {string} id - The unique identifier of the media object.
 * @property {string} name - The name of the media file.
 * @property {string} original_name - The original name of the media file.
 * @property {number} size - The size of the media file in bytes.
 * @property {string} type - The MIME type of the media file.
 * @property {string} bucket - The bucket identifier.
 * @property {string} created_at - The creation date of the media object.
 * @property {string} folder - The folder where the media is stored.
 * @property {string} url - The URL of the media file.
 * @property {string} imgix_url - The Imgix URL of the media file.
 * @property {string} alt_text - The alternative text for the media.
 */
type OptionsType$1 = {
    media: {
        props: string;
    };
};
declare class Chaining$1 extends MethodChaining {
    depth(depth: number): this;
    status(status: string): this;
    after(after: string): this;
    options(options: OptionsType$1): this;
}

declare class FindOneChaining$1 extends Chaining$1 {
    private bucketConfig;
    constructor(endpoint: string, bucketConfig: BucketConfig);
    then<FulfilledResult = any, RejectedResult = never>(onFulfilled?: PromiseFnType<FulfilledResult>, onRejected?: PromiseFnType<RejectedResult>): Promise<void>;
}

declare class FindChaining$1 extends Chaining$1 {
    private bucketConfig;
    constructor(endpoint: string, bucketConfig: BucketConfig);
    limit(limit: number): this;
    then<FulfilledResult = any, RejectedResult = never>(onFulfilled?: PromiseFnType<FulfilledResult>, onRejected?: PromiseFnType<RejectedResult>): Promise<void>;
}

/**
 * Options for fetching object data.
 * @property {Object} media - Options for media objects.
 * @property {string} media.props - Comma-separated list of additional properties to fetch for media objects.
 * @typedef {Object} MediaType
 * @property {string} all - All media properties.
 * @property {string} id - The unique identifier of the media object.
 * @property {string} name - The name of the media file.
 * @property {string} original_name - The original name of the media file.
 * @property {number} size - The size of the media file in bytes.
 * @property {string} type - The MIME type of the media file.
 * @property {string} bucket - The bucket identifier.
 * @property {string} created_at - The creation date of the media object.
 * @property {string} folder - The folder where the media is stored.
 * @property {string} url - The URL of the media file.
 * @property {string} imgix_url - The Imgix URL of the media file.
 * @property {string} alt_text - The alternative text for the media.
 */
type OptionsType = {
    media: {
        props: string;
    };
};
declare class Chaining extends MethodChaining {
    depth(depth: number): this;
    status(status: string): this;
    after(after: string): this;
    options(options: OptionsType): this;
}

declare class FindOneChaining extends Chaining {
    private bucketConfig;
    constructor(endpoint: string, bucketConfig: BucketConfig);
    then<FulfilledResult = any, RejectedResult = never>(onFulfilled?: PromiseFnType<FulfilledResult>, onRejected?: PromiseFnType<RejectedResult>): Promise<void>;
}

declare class FindChaining extends Chaining {
    private bucketConfig;
    constructor(endpoint: string, bucketConfig: BucketConfig);
    limit(limit: number): this;
    then<FulfilledResult = any, RejectedResult = never>(onFulfilled?: PromiseFnType<FulfilledResult>, onRejected?: PromiseFnType<RejectedResult>): Promise<void>;
}

declare const createBucketClient: (config: BucketConfig) => {
    objects: {
        find(query: GenericObject): FindChaining;
        findOne<T extends Record<string, unknown>>(query: NonEmptyObject<T>): FindOneChaining;
        insertOne(data: GenericObject): Promise<any>;
        updateOne(id: string, updates: GenericObject): Promise<any>;
        deleteOne(id: string, triggerWebhook?: boolean): Promise<any>;
    };
    objectTypes: {
        find(): Promise<any>;
        findOne(slug: string): Promise<any>;
        insertOne(data: GenericObject): Promise<any>;
        updateOne(slug: string, updates: GenericObject): Promise<any>;
        deleteOne(slug: string): Promise<any>;
    };
    objectRevisions: {
        find(objectId: string): FindChaining$1;
        findOne({ objectId, revisionId }: {
            objectId: string;
            revisionId: string;
        }): FindOneChaining$1;
        insertOne(objectId: string, data: InsertObjectRevisionType): Promise<any>;
    };
    media: {
        find(query?: GenericObject | undefined): FindChaining$2;
        findOne<T_1 extends Record<string, unknown>>(query: NonEmptyObject<T_1>): FindOneChaining$2;
        insertOne(params: InsertMediaType): Promise<any>;
        updateOne(id: string, updates: GenericObject): Promise<any>;
        deleteOne(id: string, triggerWebhook?: boolean): Promise<any>;
    };
    ai: {
        generateText: (options: GenerateTextOptions) => Promise<TextGenerationResponseBase | TextStreamingResponse>;
        stream: (options: Omit<GenerateTextOptions, "stream">) => Promise<TextStreamingResponse>;
        generateImage: (options: GenerateImageOptions) => Promise<ImageGenerationResponse>;
    };
};

export { APIConfig, BucketConfig, GenerateImageOptions, GenerateTextOptions, GenericObject, ImageGenerationResponse, PromiseFnType, TextGenerationResponse, TextStreamingResponse, createBucketClient };
