import * as zod from 'zod';
import { ZodType, ZodError, ZodObject } from 'zod';
import { Firestore, WhereFilterOp, OrderByDirection, FirestoreError, DocumentData, CollectionReference, DocumentReference, WithFieldValue, PartialWithFieldValue, SetOptions, QuerySnapshot, SnapshotListenOptions, Unsubscribe, DocumentSnapshot } from 'firebase/firestore';
import { RulesTestContext } from '@firebase/rules-unit-testing';
import { IsReadonlyArray, WidenIfNotUnion, InferType } from '../types.js';
export { Timestamp } from '@unfire-init';
import 'vue';

declare global {
    interface FirestoreCollectionTypes {
        '{collectionPath}': {
            '{key}': '{value}';
            'num': number;
            'arr': ('a' | 'b')[];
            'bool': boolean;
        };
        '{collectionPath}/{id}/{subCollectionPath}': {
            '{key}': '{value}';
        };
    }
}
declare type ObjectToZodTypes<T extends Object> = {
    [Key in keyof T]: ZodType<T[Key]>;
};
declare type PathString = keyof FirestoreCollectionTypes;
declare type FirestoreInstance = Firestore | ReturnType<RulesTestContext['firestore']>;
declare type WhereQueryBuilder<Path extends PathString = PathString> = <Field extends keyof FirestoreCollectionTypes[Path], OpStr extends Required<FirestoreCollectionTypes[Path]>[Field] extends Array<any> ? WhereFilterOp : Exclude<WhereFilterOp, 'array-contains' | 'array-contains-any'>, Value extends Required<FirestoreCollectionTypes[Path]>[Field]>(fieldPath: Field, opStr: OpStr, value: WidenIfNotUnion<OpStr extends 'array-contains' ? Value extends Array<infer Union> ? Union : never : OpStr extends 'in' | 'not-in' ? InferType<Value>[] : InferType<Value>>) => [
    Field,
    Required<FirestoreCollectionTypes[Path]>[Field] extends Array<any> ? WhereFilterOp : Exclude<WhereFilterOp, 'array-contains' | 'array-contains-any'>,
    WidenIfNotUnion<OpStr extends 'array-contains' ? Value extends Array<infer Union> ? Union : never : OpStr extends 'in' | 'not-in' ? InferType<Value>[] : InferType<Value>>
];
declare const defaultWhereQueryBuilder: WhereQueryBuilder;
declare type QueryOption<Path extends PathString = PathString> = {
    whereQueries?: (builder: {
        where: WhereQueryBuilder<Path>;
    }) => ReadonlyArray<[keyof FirestoreCollectionTypes[Path], WhereFilterOp, unknown]>;
    orderByQuery?: {
        fieldPath: keyof FirestoreCollectionTypes[Path];
        directionStr?: OrderByDirection;
    };
    limitBy?: number;
};
declare type UnfireFirestoreError = FirestoreError | ZodError | Error;
declare type OnErrorFn = (error: UnfireFirestoreError) => void;
declare const createCollection: <DataType = DocumentData>(collectionPath: PathString, firestoreInstance?: FirestoreInstance | undefined) => CollectionReference<DataType>;
declare const getCollectionDocRef: <P extends keyof FirestoreCollectionTypes, DataType = FirestoreCollectionTypes[P]>(collectionPath: P, docId: string, firestoreInstance?: FirestoreInstance | undefined) => DocumentReference<DataType>;
declare const upsertDoc: <CollectionPath extends keyof FirestoreCollectionTypes, DocId extends string | undefined = undefined>(options: {
    data: DocId extends undefined ? WithFieldValue<FirestoreCollectionTypes[CollectionPath]> : PartialWithFieldValue<FirestoreCollectionTypes[CollectionPath]>;
    collectionPath: CollectionPath;
    docId?: DocId | undefined;
    docRef?: DocumentReference<FirestoreCollectionTypes[CollectionPath]> | undefined;
    setOption?: SetOptions | undefined;
    validation?: Boolean | undefined;
    customSchema?: ZodObject<ObjectToZodTypes<FirestoreCollectionTypes[CollectionPath]>, "strip", zod.ZodTypeAny, { [k_1 in keyof zod.objectUtil.addQuestionMarks<{ [k in keyof ObjectToZodTypes<FirestoreCollectionTypes[CollectionPath]>]: ObjectToZodTypes<FirestoreCollectionTypes[CollectionPath]>[k]["_output"]; }>]: zod.objectUtil.addQuestionMarks<{ [k in keyof ObjectToZodTypes<FirestoreCollectionTypes[CollectionPath]>]: ObjectToZodTypes<FirestoreCollectionTypes[CollectionPath]>[k]["_output"]; }>[k_1]; }, { [k_3 in keyof zod.objectUtil.addQuestionMarks<{ [k_2 in keyof ObjectToZodTypes<FirestoreCollectionTypes[CollectionPath]>]: ObjectToZodTypes<FirestoreCollectionTypes[CollectionPath]>[k_2]["_input"]; }>]: zod.objectUtil.addQuestionMarks<{ [k_2 in keyof ObjectToZodTypes<FirestoreCollectionTypes[CollectionPath]>]: ObjectToZodTypes<FirestoreCollectionTypes[CollectionPath]>[k_2]["_input"]; }>[k_3]; }> | undefined;
    onSuccess?: ((upsertedData: DocId extends undefined ? WithFieldValue<FirestoreCollectionTypes[CollectionPath]> : PartialWithFieldValue<FirestoreCollectionTypes[CollectionPath]>) => void) | undefined;
    onError?: OnErrorFn | undefined;
}) => Promise<DocumentReference<FirestoreCollectionTypes[CollectionPath]>>;
declare const queryCollection: <CollectionPath extends keyof FirestoreCollectionTypes, ReturnDataType = FirestoreCollectionTypes[CollectionPath]>(options: {
    collectionPath: CollectionPath;
    onSnapshot: (result: {
        snapshot: QuerySnapshot<ReturnDataType>;
        docsData: (ReturnDataType & {
            id: string;
        })[];
    }) => void;
    onError?: OnErrorFn | undefined;
    queryOption?: QueryOption<CollectionPath> | undefined;
    snapshotListenOptions?: SnapshotListenOptions | undefined;
}) => {
    unsubscribe?: Unsubscribe;
    error?: UnfireFirestoreError;
};
declare const getCollectionDocsOnce: <CollectionPath extends keyof FirestoreCollectionTypes, ReturnDataType = FirestoreCollectionTypes[CollectionPath]>(options: {
    collectionPath: CollectionPath;
    queryOption?: QueryOption<CollectionPath> | undefined;
    onError?: OnErrorFn | undefined;
}) => Promise<{
    snapshot?: QuerySnapshot<ReturnDataType> | undefined;
    docsData?: (ReturnDataType & {
        id: string;
    })[] | undefined;
    error?: UnfireFirestoreError | undefined;
}>;
declare const queryDoc: <CollectionPath extends keyof FirestoreCollectionTypes, ReturnDataType = FirestoreCollectionTypes[CollectionPath], DocId extends string | undefined = undefined>(options: {
    collectionPath: CollectionPath;
    docId?: DocId | undefined;
    docRef?: DocumentReference<ReturnDataType> | undefined;
    onSnapshot: (result: {
        snapshot: DocumentSnapshot<ReturnDataType>;
        docData: ReturnDataType & {
            id: string;
        };
    }) => void;
    onError?: OnErrorFn | undefined;
    snapshotListenOptions?: SnapshotListenOptions | undefined;
}) => {
    unsubscribe?: Unsubscribe;
    error?: UnfireFirestoreError;
};
declare const getDocOnce: <CollectionPath extends keyof FirestoreCollectionTypes, ReturnDataType = FirestoreCollectionTypes[CollectionPath], DocId extends string | undefined = undefined>(options: {
    collectionPath?: CollectionPath | undefined;
    docId?: DocId | undefined;
    docRef?: DocumentReference<ReturnDataType> | undefined;
    firestoreInstance?: FirestoreInstance | undefined;
    onError?: OnErrorFn | undefined;
}) => Promise<{
    documentSnapshot?: DocumentSnapshot<ReturnDataType> | undefined;
    data?: (ReturnDataType & {
        id: string;
    }) | undefined;
    error?: UnfireFirestoreError | undefined;
}>;
declare const deleteDoc: <CollectionPath extends keyof FirestoreCollectionTypes, DocId extends string | undefined = undefined>(options: {
    collectionPath?: CollectionPath | undefined;
    docId?: DocId | undefined;
    docRef?: DocumentReference<DocumentData> | undefined;
    onError?: OnErrorFn | undefined;
}) => Promise<void> | undefined;
declare const whereFilterOps: string[];
/**
 * Firestore utility types
 */
declare type AllWhereQueriesRecord<CollectionPath extends PathString> = NonNullable<{
    [Field in keyof FirestoreCollectionTypes[CollectionPath]]: {
        fieldPath: Field;
        opStr: Required<FirestoreCollectionTypes[CollectionPath]>[Field] extends Array<any> ? WhereFilterOp : Exclude<WhereFilterOp, 'array-contains' | 'array-contains-any'>;
        value: FirestoreCollectionTypes[CollectionPath][Field];
    };
}[keyof FirestoreCollectionTypes[CollectionPath]]>[];
declare type MapWhereQueriesArrayToRecord<T, CollectionPath extends PathString> = IsReadonlyArray<T> extends true ? T extends readonly [...infer U] ? [
    ...{
        [K in keyof U]: U[K] extends readonly [infer Field, infer OpStr, infer Value] ? {
            fieldPath: Field;
            opStr: OpStr;
            value: Value;
        } : never;
    },
    ...AllWhereQueriesRecord<CollectionPath>
] : never : AllWhereQueriesRecord<CollectionPath>;

export { AllWhereQueriesRecord, FirestoreInstance, MapWhereQueriesArrayToRecord, ObjectToZodTypes, OnErrorFn, PathString, QueryOption, UnfireFirestoreError, createCollection, defaultWhereQueryBuilder, deleteDoc, getCollectionDocRef, getCollectionDocsOnce, getDocOnce, queryCollection, queryDoc, upsertDoc, whereFilterOps };
