import { JoinOptions } from './JoinOptions';
import { FindOptionsWhere } from './FindOptionsWhere';
import { FindOptionsSelect, FindOptionsSelectByString } from './FindOptionsSelect';
import { FindOptionsRelationByString, FindOptionsRelations } from './FindOptionsRelations';
import { FindOptionsOrder } from './FindOptionsOrder';

/**
 * Defines a special criteria to find specific entity.
 */
export interface FindOneOptions<Entity = any> {
	/**
	 * Adds a comment with the supplied string in the generated query.  This is
	 * helpful for debugging purposes, such as finding a specific query in the
	 * database server's logs, or for categorization using an APM product.
	 */
	comment?: string;

	/**
	 * Specifies what columns should be retrieved.
	 */
	select?: FindOptionsSelect<Entity> | FindOptionsSelectByString<Entity>;

	/**
	 * Simple condition that should be applied to match entities.
	 */
	where?: FindOptionsWhere<Entity>[] | FindOptionsWhere<Entity>;

	/**
	 * Indicates what relations of entity should be loaded (simplified left join form).
	 */
	relations?: FindOptionsRelations<Entity> | FindOptionsRelationByString;

	/**
	 * Specifies how relations must be loaded - using "joins" or separate queries.
	 * If you are loading too much data with nested joins it's better to load relations
	 * using separate queries.
	 *
	 * Default strategy is "join", but default can be customized in connection options.
	 */
	relationLoadStrategy?: 'join' | 'query';

	/**
	 * Specifies what relations should be loaded.
	 *
	 * @deprecated
	 */
	join?: JoinOptions;

	/**
	 * Order, in which entities should be ordered.
	 */
	order?: FindOptionsOrder<Entity>;

	/**
	 * Enables or disables query result caching.
	 */
	cache?: boolean | number | { id: any; milliseconds: number };

	/**
	 * Indicates what locking mode should be used.
	 *
	 * Note: For lock tables, you must specify the table names and not the relation names
	 */
	lock?:
		| { mode: 'optimistic'; version: number | Date }
		| {
				mode:
					| 'pessimistic_read'
					| 'pessimistic_write'
					| 'dirty_read'
					/*
                    "pessimistic_partial_write" and "pessimistic_write_or_fail" are deprecated and
                    will be removed in a future version.

                    Use onLocked instead.
                 */
					| 'pessimistic_partial_write'
					| 'pessimistic_write_or_fail'
					| 'for_no_key_update'
					| 'for_key_share';
				tables?: string[];
				onLocked?: 'nowait' | 'skip_locked';
		  };

	/**
	 * Indicates if soft-deleted rows should be included in entity result.
	 */
	withDeleted?: boolean;

	/**
	 * If sets to true then loads all relation ids of the entity and maps them into relation values (not relation objects).
	 * If array of strings is given then loads only relation ids of the given properties.
	 */
	loadRelationIds?: boolean | { relations?: string[]; disableMixedMap?: boolean }; // todo: extract options into separate interface, reuse

	/**
	 * Indicates if eager relations should be loaded or not.
	 * By default, they are loaded when find methods are used.
	 */
	loadEagerRelations?: boolean;

	/**
	 * If this is set to true, SELECT query in a `find` method will be executed in a transaction.
	 */
	transaction?: boolean;
}
