import type { Merge } from 'type-fest';
import type OnyxUtils from './OnyxUtils';
import type { OnyxMethod } from './OnyxUtils';
import type { FastMergeReplaceNullPatch } from './utils';
/**
 * Utility type that excludes `null` from the type `TValue`.
 */
type NonNull<TValue> = TValue extends null ? never : TValue;
/**
 * Utility type that excludes `undefined` from the type `TValue`.
 */
type NonUndefined<TValue> = TValue extends undefined ? never : TValue;
/**
 * Represents a deeply nested record. It maps keys to values,
 * and those values can either be of type `TValue` or further nested `DeepRecord` instances.
 */
type DeepRecord<TKey extends string | number | symbol, TValue> = {
    [key: string]: TValue | DeepRecord<TKey, TValue>;
};
/**
 * Represents type options to configure all Onyx methods.
 * It's a combination of predefined options with user-provided options (CustomTypeOptions).
 *
 * The options are:
 * - `keys`: Represents a string union of all Onyx normal keys.
 * - `collectionKeys`: Represents a string union of all Onyx collection keys.
 * - `values`: Represents a Record where each key is an Onyx key and each value is its corresponding Onyx value type.
 *
 * The user-defined options (CustomTypeOptions) are merged into these predefined options.
 * In case of conflicting properties, the ones from CustomTypeOptions are prioritized.
 */
type TypeOptions = Merge<{
    keys: string;
    collectionKeys: string;
    values: Record<string, unknown>;
}, CustomTypeOptions>;
/**
 * Represents the user-defined options to configure all Onyx methods.
 *
 * The developer can configure Onyx methods by augmenting this library and overriding CustomTypeOptions.
 *
 * @example
 * ```ts
 * // ONYXKEYS.ts
 * import {ValueOf} from 'type-fest';
 * import { Account, Report } from './types';
 *
 * const ONYXKEYS = {
 *     ACCOUNT: 'account',
 *     IS_SIDEBAR_LOADED: 'isSidebarLoaded',
 *
 *     // Collection Keys
 *     COLLECTION: {
 *         REPORT: 'report_',
 *     },
 * } as const;
 *
 * type OnyxKeysMap = typeof ONYXKEYS;
 * type OnyxCollectionKey = ValueOf<OnyxKeysMap['COLLECTION']>;
 * type OnyxKey = DeepValueOf<Omit<OnyxKeysMap, 'COLLECTION'>>;
 *
 * type OnyxValues = {
 *     [ONYXKEYS.ACCOUNT]: Account;
 *     [ONYXKEYS.IS_SIDEBAR_LOADED]: boolean;
 *     [ONYXKEYS.COLLECTION.REPORT]: Report;
 * };
 *
 * export default ONYXKEYS;
 * export type {OnyxKey, OnyxCollectionKey, OnyxValues};
 *
 * // global.d.ts
 * import {OnyxKey, OnyxCollectionKey, OnyxValues} from './ONYXKEYS';
 *
 * declare module 'react-native-onyx' {
 *     interface CustomTypeOptions {
 *         keys: OnyxKey;
 *         collectionKeys: OnyxCollectionKey;
 *         values: OnyxValues;
 *     }
 * }
 * ```
 */
interface CustomTypeOptions {
}
/**
 * Represents a string union of all Onyx normal keys.
 */
type Key = TypeOptions['keys'];
/**
 * Represents a string union of all Onyx collection keys.
 */
type CollectionKeyBase = TypeOptions['collectionKeys'];
/**
 * Represents a literal string union of all Onyx collection keys.
 * It allows appending a string after each collection key e.g. `report_some-id`.
 */
type CollectionKey = `${CollectionKeyBase}${string}`;
/**
 * Represents a string union of all Onyx normal and collection keys.
 */
type OnyxKey = Key | CollectionKey;
/**
 * Represents a selector function type which operates based on the provided `TKey` and `ReturnType`.
 *
 * A `Selector` is a function that accepts a value and returns a processed value.
 * This type accepts two type parameters: `TKey` and `TReturnType`.
 *
 * The type `TKey` extends `OnyxKey` and it is the key used to access a value in `KeyValueMapping`.
 * `TReturnType` is the type of the returned value from the selector function.
 */
type Selector<TKey extends OnyxKey, TReturnType> = (value: OnyxEntry<KeyValueMapping[TKey]>) => TReturnType;
/**
 * Represents a single Onyx entry, that can be either `TOnyxValue` or `undefined` if it doesn't exist.
 * It can be used to specify data retrieved from Onyx.
 */
type OnyxEntry<TOnyxValue> = TOnyxValue | undefined;
/**
 * Represents an Onyx collection of entries, that can be either a record of `TOnyxValue`s or `undefined` if it is empty or doesn't exist.
 * It can be used to specify collection data retrieved from Onyx.
 */
type OnyxCollection<TOnyxValue> = OnyxEntry<Record<string, TOnyxValue | undefined>>;
/**
 * Represents a mapping of Onyx keys to values, where keys are either normal or collection Onyx keys
 * and values are the corresponding values in Onyx's state.
 *
 * For collection keys, `KeyValueMapping` allows any string to be appended
 * to the key (e.g., 'report_some-id', 'download_some-id').
 *
 * The mapping is derived from the `values` property of the `TypeOptions` type.
 */
type KeyValueMapping = {
    [TKey in keyof TypeOptions['values'] as TKey extends CollectionKeyBase ? `${TKey}${string}` : TKey]: TypeOptions['values'][TKey];
};
/**
 * Represents a Onyx value that can be either a single entry or a collection of entries, depending on the `TKey` provided.
 */
type OnyxValue<TKey extends OnyxKey> = string extends TKey ? unknown : TKey extends CollectionKeyBase ? OnyxCollection<KeyValueMapping[TKey]> : OnyxEntry<KeyValueMapping[TKey]>;
/** Utility type to extract `TOnyxValue` from `OnyxCollection<TOnyxValue>` */
type ExtractOnyxCollectionValue<TOnyxCollection> = TOnyxCollection extends NonNullable<OnyxCollection<infer U>> ? U : never;
type Primitive = null | undefined | string | number | boolean | symbol | bigint;
type BuiltIns = Primitive | void | Date | RegExp;
type NonTransformableTypes = BuiltIns | ((...args: any[]) => unknown) | Map<unknown, unknown> | Set<unknown> | ReadonlyMap<unknown, unknown> | ReadonlySet<unknown> | unknown[] | readonly unknown[];
/**
 * Create a type from another type with all keys and nested keys set to optional or null.
 *
 * @example
 * const settings: Settings = {
 *	 textEditor: {
 *	 	fontSize: 14;
 *	 	fontColor: '#000000';
 *	 	fontWeight: 400;
 *	 }
 *	 autosave: true;
 * };
 *
 * const applySavedSettings = (savedSettings: NullishDeep<Settings>) => {
 * 	 return {...settings, ...savedSettings};
 * }
 *
 * settings = applySavedSettings({textEditor: {fontWeight: 500, fontColor: null}});
 */
type NullishDeep<T> = T extends NonTransformableTypes ? T : T extends object ? NullishObjectDeep<T> : unknown;
/**
 * Same as `NullishDeep`, but accepts only `object`s as inputs. Internal helper for `NullishDeep`.
 */
type NullishObjectDeep<ObjectType extends object> = {
    [KeyType in keyof ObjectType]?: NullishDeep<ObjectType[KeyType]> | null;
};
/**
 * Represents a mapping between Onyx collection keys and their respective values.
 *
 * It helps to enforce that a Onyx collection key should not be without suffix (e.g. should always be of the form `${TKey}${string}`),
 * and to map each Onyx collection key with suffix to a value of type `TValue`.
 *
 * Also, the `TMap` type is inferred automatically in `mergeCollection()` method and represents
 * the object of collection keys/values specified in the second parameter of the method.
 */
type Collection<TKey extends CollectionKeyBase, TValue> = Record<`${TKey}${string}`, TValue>;
/** Represents the base options used in `Onyx.connect()` method. */
type BaseConnectOptions = {
    /**
     * If set to `false`, the connection won't be reused between other subscribers that are listening to the same Onyx key
     * with the same connect configurations.
     */
    reuseConnection?: boolean;
};
/** Represents the callback function used in `Onyx.connect()` method with a regular key. */
type DefaultConnectCallback<TKey extends OnyxKey> = (value: OnyxEntry<KeyValueMapping[TKey]>, key: TKey) => void;
/** Represents the callback function used in `Onyx.connect()` method with a collection key. */
type CollectionConnectCallback<TKey extends OnyxKey> = (value: NonUndefined<OnyxCollection<KeyValueMapping[TKey]>>, key: TKey) => void;
/**
 * Represents the options used in `Onyx.connect()` method.
 *
 * For a collection root key (e.g. `ONYXKEYS.COLLECTION.REPORT`), the callback fires
 * with the entire collection object whenever any member changes (signature
 * `(collection, key)`). For any other key, the callback fires with the value at
 * that key (signature `(value, key)`).
 */
type ConnectOptions<TKey extends OnyxKey> = BaseConnectOptions & {
    /** The Onyx key to subscribe to. */
    key: TKey;
    /** A function that will be called when the Onyx data we are subscribed changes. */
    callback?: (value: TKey extends CollectionKeyBase ? NonUndefined<OnyxCollection<KeyValueMapping[TKey]>> : OnyxEntry<KeyValueMapping[TKey]>, key: TKey) => void;
};
type CallbackToStateMapping<TKey extends OnyxKey> = ConnectOptions<TKey> & {
    subscriptionID: number;
};
/**
 * Represents a single Onyx input value, that can be either `TOnyxValue` or `null` if the key should be deleted.
 * This type is used for data passed to Onyx e.g. in `Onyx.merge` and `Onyx.set`.
 */
type OnyxInputValue<TOnyxValue> = TOnyxValue | null;
/**
 * Represents an Onyx collection input, that can be either a record of `TOnyxValue`s or `null` if the key should be deleted.
 */
type OnyxCollectionInputValue<TOnyxValue> = OnyxInputValue<Record<string, TOnyxValue | null>>;
/**
 * Represents an input value that can be passed to Onyx methods, that can be either `TOnyxValue` or `null`.
 * Setting a key to `null` will remove the key from the store.
 * `undefined` is not allowed for setting values, because it will have no effect on the data.
 */
type OnyxInput<TKey extends OnyxKey> = OnyxInputValue<NullishDeep<KeyValueMapping[TKey]>>;
/**
 * Represents a mapping object where each `OnyxKey` maps to either a value of its corresponding type in `KeyValueMapping` or `null`.
 *
 * It's very similar to `KeyValueMapping` but this type is used for inputs to Onyx
 * (set, merge, mergeCollection) and therefore accepts using `null` to remove a key from Onyx.
 */
type OnyxInputKeyValueMapping = {
    [TKey in OnyxKey]: OnyxInput<TKey>;
};
/**
 * This represents the value that can be passed to `Onyx.set` and to `Onyx.update` with the method "SET"
 */
type OnyxSetInput<TKey extends OnyxKey> = OnyxInput<TKey>;
/**
 * This represents the value that can be passed to `Onyx.multiSet` and to `Onyx.update` with the method "MULTI_SET"
 */
type OnyxMultiSetInput = Partial<OnyxInputKeyValueMapping>;
/**
 * This represents the value that can be passed to `Onyx.merge` and to `Onyx.update` with the method "MERGE"
 */
type OnyxMergeInput<TKey extends OnyxKey> = OnyxInput<TKey>;
/**
 * This represents the value that can be passed to `Onyx.merge` and to `Onyx.update` with the method "MERGE"
 */
type OnyxMergeCollectionInput<TKey extends OnyxKey> = Collection<TKey, NonNullable<OnyxInput<TKey>>>;
/**
 * This represents the value that can be passed to `Onyx.setCollection` and to `Onyx.update` with the method "SET_COLLECTION"
 */
type OnyxSetCollectionInput<TKey extends OnyxKey> = Collection<TKey, OnyxInput<TKey>>;
type OnyxMethodMap = typeof OnyxUtils.METHOD;
type ExpandOnyxKeys<TKey extends OnyxKey> = TKey extends CollectionKeyBase ? NoInfer<`${TKey}${string}`> : TKey;
/**
 * OnyxUpdate type includes all onyx methods used in OnyxMethodValueMap.
 * If a new method is added to OnyxUtils.METHOD constant, it must be added to OnyxMethodValueMap type.
 * Otherwise it will show static type errors.
 */
type OnyxUpdate<TKey extends OnyxKey> = {
    [K in TKey]: {
        onyxMethod: typeof OnyxUtils.METHOD.SET;
        key: ExpandOnyxKeys<K>;
        value: OnyxSetInput<K>;
    } | {
        onyxMethod: typeof OnyxUtils.METHOD.MULTI_SET;
        key: ExpandOnyxKeys<K>;
        value: OnyxMultiSetInput;
    } | {
        onyxMethod: typeof OnyxUtils.METHOD.MERGE;
        key: ExpandOnyxKeys<K>;
        value: OnyxMergeInput<K>;
    } | {
        onyxMethod: typeof OnyxUtils.METHOD.CLEAR;
        key: ExpandOnyxKeys<K>;
        value?: never;
    } | {
        onyxMethod: typeof OnyxUtils.METHOD.MERGE_COLLECTION;
        key: K;
        value: OnyxMergeCollectionInput<K>;
    } | {
        onyxMethod: typeof OnyxUtils.METHOD.SET_COLLECTION;
        key: K;
        value: OnyxSetCollectionInput<K>;
    };
}[TKey];
/**
 * Represents the options used in `Onyx.set()` method.
 */
type SetOptions = {
    /** Skip the deep equality check against the cached value. Improves performance for large objects. */
    skipCacheCheck?: boolean;
};
type SetParams<TKey extends OnyxKey> = {
    key: TKey;
    value: OnyxSetInput<TKey>;
    options?: SetOptions;
};
type SetCollectionParams<TKey extends CollectionKeyBase> = {
    collectionKey: TKey;
    collection: OnyxSetCollectionInput<TKey>;
};
type MergeCollectionWithPatchesParams<TKey extends CollectionKeyBase> = {
    collectionKey: TKey;
    collection: OnyxMergeCollectionInput<TKey>;
    mergeReplaceNullPatches?: MultiMergeReplaceNullPatches;
    isProcessingCollectionUpdate?: boolean;
};
type RetriableOnyxOperation = typeof OnyxUtils.setWithRetry | typeof OnyxUtils.multiSetWithRetry | typeof OnyxUtils.setCollectionWithRetry | typeof OnyxUtils.mergeCollectionWithPatches | typeof OnyxUtils.partialSetCollection;
/**
 * Represents the options used in `Onyx.init()` method.
 */
type InitOptions = {
    /** `ONYXKEYS` constants object */
    keys?: DeepRecord<string, OnyxKey>;
    /** initial data to set when `init()` and `clear()` is called */
    initialKeyStates?: Partial<OnyxInputKeyValueMapping>;
    /**
     * This is an array of keys (individual or collection patterns) that when provided to Onyx are flagged
     * as "safe" for removal.
     */
    evictableKeys?: OnyxKey[];
    /**
     * Auto synchronize storage events between multiple instances
     * of Onyx running in different tabs/windows. Defaults to true for platforms that support local storage (web/desktop)
     */
    shouldSyncMultipleInstances?: boolean;
    /**
     * If enabled, it will connect to Redux DevTools Extension for debugging.
     * This allows you to see all Onyx state changes in the Redux DevTools.
     * @default true
     */
    enableDevTools?: boolean;
    /**
     * Array of collection member IDs that Onyx should silently ignore across all operations.
     * This prevents keys formed from invalid or default IDs (e.g. "-1", "0", "undefined") from
     * polluting cache or triggering subscriber notifications.
     */
    skippableCollectionMemberIDs?: string[];
    /**
     * Array of keys that when provided to Onyx are flagged as RAM-only keys, and thus are not saved to disk.
     */
    ramOnlyKeys?: OnyxKey[];
    /**
     * A list of field names that should always be merged into snapshot entries even if those fields are
     * missing in the snapshot. Snapshots are saved "views" of a key's data used to populate read-only
     * or cached lists, and by default Onyx only merges fields that already exist in that saved view.
     * Use this to opt-in to additional fields that must appear in snapshots (for example, pending flags)
     * without hardcoding app-specific logic inside Onyx.
     */
    snapshotMergeKeys?: string[];
};
type GenericFunction = (...args: any[]) => any;
/**
 * Represents a record where the key is a collection member key and the value is a list of
 * tuples that we'll use to replace the nested objects of that collection member record with something else.
 */
type MultiMergeReplaceNullPatches = Record<OnyxKey, FastMergeReplaceNullPatch[]>;
/**
 * Represents a combination of Merge and Set operations that should be executed in Onyx
 */
type MixedOperationsQueue = {
    merge: OnyxInputKeyValueMapping;
    mergeReplaceNullPatches: MultiMergeReplaceNullPatches;
    set: OnyxInputKeyValueMapping;
};
export type { BaseConnectOptions, Collection, CollectionConnectCallback, CollectionKey, CollectionKeyBase, ConnectOptions, CustomTypeOptions, DeepRecord, DefaultConnectCallback, ExtractOnyxCollectionValue, GenericFunction, InitOptions, Key, KeyValueMapping, CallbackToStateMapping, NonNull, NonUndefined, OnyxInputKeyValueMapping, NullishDeep, OnyxCollection, OnyxEntry, OnyxKey, OnyxInputValue, OnyxCollectionInputValue, OnyxInput, OnyxSetInput, OnyxMultiSetInput, OnyxMergeInput, OnyxMergeCollectionInput, OnyxSetCollectionInput, OnyxMethod, OnyxMethodMap, OnyxUpdate, OnyxValue, Selector, SetOptions, SetParams, SetCollectionParams, MergeCollectionWithPatchesParams, MultiMergeReplaceNullPatches, MixedOperationsQueue, RetriableOnyxOperation, };
