/*-------------------------------------------------------------------------
 * Copyright (c) Microsoft Corporation.  All rights reserved.
 *
 * src/configs/feature_flag_configs.c
 *
 * Initialization of GUCs that change behavior that will only be used
 * in tests.
 *-------------------------------------------------------------------------
 */

#include <postgres.h>
#include <miscadmin.h>
#include <utils/guc.h>
#include <limits.h>

#include "metadata/metadata_guc.h"
#include "configs/config_initialization.h"
#include "commands/commands_common.h"

#define DEFAULT_NEXT_COLLECTION_ID NEXT_COLLECTION_ID_UNSET
int NextCollectionId = DEFAULT_NEXT_COLLECTION_ID;

#define DEFAULT_NEXT_COLLECTION_INDEX_ID NEXT_COLLECTION_INDEX_ID_UNSET
int NextCollectionIndexId = DEFAULT_NEXT_COLLECTION_INDEX_ID;

#define DEFAULT_SIMULATE_RECOVERY_STATE false
bool SimulateRecoveryState = DEFAULT_SIMULATE_RECOVERY_STATE;

#define DEFAULT_ENABLE_GENERATE_NON_EXISTS_TERM true
bool EnableGenerateNonExistsTerm = DEFAULT_ENABLE_GENERATE_NON_EXISTS_TERM;

#define DEFAULT_INDEX_TRUNCATION_LIMIT_OVERRIDE INT_MAX
int IndexTruncationLimitOverride = DEFAULT_INDEX_TRUNCATION_LIMIT_OVERRIDE;

#define DEFAULT_ENABLE_CURSORS_ON_AGGREGATION_QUERY_REWRITE false
bool EnableCursorsOnAggregationQueryRewrite =
	DEFAULT_ENABLE_CURSORS_ON_AGGREGATION_QUERY_REWRITE;

#define DEFAULT_UNIQUE_INDEX_KEYHASH_OVERIDE 0
int DefaultUniqueIndexKeyhashOverride = DEFAULT_UNIQUE_INDEX_KEYHASH_OVERIDE;

#define DEFAULT_USE_LOCAL_EXECUTION_SHARD_QUERIES true
bool UseLocalExecutionShardQueries = DEFAULT_USE_LOCAL_EXECUTION_SHARD_QUERIES;

#define DEFAULT_FORCE_LOCAL_EXECUTION_SHARD_QUERIES false
bool ForceLocalExecutionShardQueries = DEFAULT_FORCE_LOCAL_EXECUTION_SHARD_QUERIES;

#define DEFAULT_FORCE_INDEX_TERM_TRUNCATION false
bool ForceIndexTermTruncation = DEFAULT_FORCE_INDEX_TERM_TRUNCATION;

#define DEFAULT_MAX_WORKER_CURSOR_SIZE BSON_MAX_ALLOWED_SIZE
int32_t MaxWorkerCursorSize = DEFAULT_MAX_WORKER_CURSOR_SIZE;

#define DEFAULT_ENABLE_NATIVE_COLOCATION true
bool EnableNativeColocation = DEFAULT_ENABLE_NATIVE_COLOCATION;

#define DEFAULT_MAX_ALLOWED_DOCS_IN_DENSIFY 500000
extern int32 PEC_InternalQueryMaxAllowedDensifyDocs;

#define DEFAULT_FORCE_WILDCARD_REDUCED_TERM false
bool ForceWildcardReducedTerm = DEFAULT_FORCE_WILDCARD_REDUCED_TERM;

extern int32 PEC_InternalDocumentSourceDensifyMaxMemoryBytes;

#define DEFAULT_FORCE_DISABLE_SEQ_SCAN false
bool ForceDisableSeqScan = DEFAULT_FORCE_DISABLE_SEQ_SCAN;

#define DEFAULT_CURRENTOP_ADD_SQL_COMMAND false
bool CurrentOpAddSqlCommand = DEFAULT_CURRENTOP_ADD_SQL_COMMAND;

#define DEFAULT_ALTERNATE_INDEX_HANDLER ""
char *AlternateIndexHandler = DEFAULT_ALTERNATE_INDEX_HANDLER;

#define DEFAULT_LOG_RELATION_INDEXES_ORDER false
bool EnableLogRelationIndexesOrder = DEFAULT_LOG_RELATION_INDEXES_ORDER;

#define DEFAULT_ENABLE_LARGE_UNIQUE_INDEX_KEYS true
bool DefaultEnableLargeUniqueIndexKeys = DEFAULT_ENABLE_LARGE_UNIQUE_INDEX_KEYS;

#define DEFAULT_ENABLE_DEBUG_QUERY_TEXT false
bool EnableDebugQueryText = DEFAULT_ENABLE_DEBUG_QUERY_TEXT;

#define DEFAULT_ENABLE_MULTI_INDEX_RUM_JOIN false
bool EnableMultiIndexRumJoin = DEFAULT_ENABLE_MULTI_INDEX_RUM_JOIN;

void
InitializeTestConfigurations(const char *prefix, const char *newGucPrefix)
{
	DefineCustomIntVariable(
		psprintf("%s.next_collection_id", newGucPrefix),
		gettext_noop("Set the next collection id to use when creationing a collection."),
		gettext_noop("Collection ids are normally generated using a sequence. If "
					 "next_collection_id is set to a value different than "
					 "DEFAULT_NEXT_COLLECTION_ID, then collection will instead be "
					 "generated by incrementing from the value of this GUC and this "
					 "will be reflected in the GUC. This is mainly useful to ensure "
					 "consistent collection ids when running tests in parallel."),
		&NextCollectionId,
		DEFAULT_NEXT_COLLECTION_ID, DEFAULT_NEXT_COLLECTION_ID, INT_MAX,
		PGC_USERSET,
		GUC_NO_SHOW_ALL | GUC_NOT_IN_SAMPLE,
		NULL, NULL, NULL);

	DefineCustomIntVariable(
		psprintf("%s.next_collection_index_id", newGucPrefix),
		gettext_noop("Set the next collection index id to use when creating a "
					 "collection index."),
		gettext_noop("Collection index ids are normally generated using a sequence. "
					 "If next_collection_index_id is set to a value different than "
					 "DEFAULT_NEXT_COLLECTION_INDEX_ID, then collection index ids "
					 "will instead be generated by incrementing from the value of "
					 "this GUC and this will be reflected in the GUC. This is mainly "
					 "useful to ensure consistent collection index ids when running "
					 "tests in parallel."),
		&NextCollectionIndexId,
		DEFAULT_NEXT_COLLECTION_INDEX_ID, DEFAULT_NEXT_COLLECTION_INDEX_ID, INT_MAX,
		PGC_USERSET,
		GUC_NO_SHOW_ALL | GUC_NOT_IN_SAMPLE,
		NULL, NULL, NULL);

	DefineCustomBoolVariable(
		psprintf("%s.simulateRecoveryState", prefix),
		gettext_noop(
			"Simulates a database recovery state and throws an error for read-write operations."),
		NULL, &SimulateRecoveryState, DEFAULT_SIMULATE_RECOVERY_STATE,
		PGC_USERSET, 0, NULL, NULL, NULL);

	/* Added variable for testing cursor continuations */
	DefineCustomIntVariable(
		psprintf("%s.maxWorkerCursorSize", prefix),
		gettext_noop(
			"The maximum size a single cursor response page should be in a worker."),
		NULL, &MaxWorkerCursorSize,
		DEFAULT_MAX_WORKER_CURSOR_SIZE, 1, BSON_MAX_ALLOWED_SIZE,
		PGC_USERSET,
		GUC_NO_SHOW_ALL | GUC_NOT_IN_SAMPLE,
		NULL, NULL, NULL);

	DefineCustomBoolVariable(
		psprintf("%s.enableCursorsOnAggregationQueryRewrite", newGucPrefix),
		gettext_noop(
			"Whether or not to add the cursors on aggregation style queries."),
		NULL,
		&EnableCursorsOnAggregationQueryRewrite,
		DEFAULT_ENABLE_CURSORS_ON_AGGREGATION_QUERY_REWRITE,
		PGC_USERSET,
		0,
		NULL, NULL, NULL);

	DefineCustomBoolVariable(
		psprintf("%s.enableGenerateNonExistsTerm", newGucPrefix),
		gettext_noop(
			"Enables generating the non exists term for new documents in a collection."),
		NULL, &EnableGenerateNonExistsTerm, DEFAULT_ENABLE_GENERATE_NON_EXISTS_TERM,
		PGC_USERSET, 0, NULL, NULL, NULL);

	DefineCustomBoolVariable(
		psprintf("%s.forceIndexTermTruncation", prefix),
		gettext_noop(
			"Whether to force the feature for index term truncation"),
		NULL, &ForceIndexTermTruncation, DEFAULT_FORCE_INDEX_TERM_TRUNCATION,
		PGC_USERSET, 0, NULL, NULL, NULL);

	DefineCustomBoolVariable(
		psprintf("%s.forceWildcardReducedTerm", prefix),
		gettext_noop(
			"Whether to force the feature for the wildcard reduced term generation"),
		NULL, &ForceWildcardReducedTerm, DEFAULT_FORCE_WILDCARD_REDUCED_TERM,
		PGC_USERSET, 0, NULL, NULL, NULL);

	DefineCustomIntVariable(
		psprintf("%s.indexTermLimitOverride", prefix),
		gettext_noop(
			"Override for the index term truncation limit (primarily for tests)."),
		NULL, &IndexTruncationLimitOverride,
		DEFAULT_INDEX_TRUNCATION_LIMIT_OVERRIDE, 1, INT_MAX,
		PGC_USERSET,
		GUC_NO_SHOW_ALL | GUC_NOT_IN_SAMPLE,
		NULL, NULL, NULL);

	DefineCustomBoolVariable(
		psprintf("%s.useLocalExecutionShardQueries", newGucPrefix),
		gettext_noop(
			"Determines whether or not to push local shard queries to the shard directly."),
		NULL, &UseLocalExecutionShardQueries, DEFAULT_USE_LOCAL_EXECUTION_SHARD_QUERIES,
		PGC_USERSET, 0, NULL, NULL, NULL);

	DefineCustomBoolVariable(
		psprintf("%s.forceLocalExecutionShardQueries", newGucPrefix),
		gettext_noop(
			"Determines whether or not to force all shard queries to be executed locally on the shard."),
		NULL, &ForceLocalExecutionShardQueries,
		DEFAULT_FORCE_LOCAL_EXECUTION_SHARD_QUERIES,
		PGC_USERSET, 0, NULL, NULL, NULL);

	DefineCustomIntVariable(
		psprintf("%s.defaultUniqueIndexKeyhashOverride", newGucPrefix),
		gettext_noop(
			"Do not set this in production. GUC used to force a single keyhash result value for testing hash conflicts on unique indexes that require a runtime recheck."),
		NULL, &DefaultUniqueIndexKeyhashOverride,
		DEFAULT_UNIQUE_INDEX_KEYHASH_OVERIDE, 0, INT_MAX,
		PGC_USERSET,
		0,
		NULL, NULL, NULL);

	DefineCustomBoolVariable(
		psprintf("%s.enableNativeColocation", prefix),
		gettext_noop(
			"Determines whether to turn on colocation of tables in a given collection database (and disabled outside the database)"),
		NULL, &EnableNativeColocation, DEFAULT_ENABLE_NATIVE_COLOCATION,
		PGC_USERSET, 0, NULL, NULL, NULL);

	DefineCustomIntVariable(
		psprintf("%s.test.internalQueryMaxAllowedDensifyDocs", newGucPrefix),
		gettext_noop(
			"This GUC is for testing only and it is mapped to external.internalQueryMaxAllowedDensifyDocs."
			"Number of maximum documents that can be generated using $densify stage."),
		NULL,
		&PEC_InternalQueryMaxAllowedDensifyDocs,
		DEFAULT_MAX_ALLOWED_DOCS_IN_DENSIFY, 0, INT32_MAX,
		PGC_USERSET,
		GUC_NO_SHOW_ALL | GUC_NOT_IN_SAMPLE,
		NULL, NULL, NULL);

	DefineCustomIntVariable(
		psprintf("%s.test.internalDocumentSourceDensifyMaxMemoryBytes", newGucPrefix),
		gettext_noop(
			"This GUC is for testing only and it is mapped to external.internalDocumentSourceDensifyMaxMemoryBytes."
			"Maximum memory allowed for the generated documents in $densify stage."),
		NULL,
		&PEC_InternalDocumentSourceDensifyMaxMemoryBytes,
		BSON_MAX_ALLOWED_SIZE_INTERMEDIATE, 0, BSON_MAX_ALLOWED_SIZE_INTERMEDIATE,
		PGC_USERSET,
		GUC_NO_SHOW_ALL | GUC_NOT_IN_SAMPLE,
		NULL, NULL, NULL);

	DefineCustomBoolVariable(
		psprintf("%s.forceDisableSeqScan", newGucPrefix),
		gettext_noop(
			"Whether to force disable sequential type scans on the collection."),
		NULL, &ForceDisableSeqScan, DEFAULT_FORCE_DISABLE_SEQ_SCAN,
		PGC_USERSET, 0, NULL, NULL, NULL);

	DefineCustomBoolVariable(
		psprintf("%s.currentOpAddSqlCommand", newGucPrefix),
		gettext_noop(
			"Whether to add the SQL command to the current operation view."),
		NULL, &CurrentOpAddSqlCommand, DEFAULT_CURRENTOP_ADD_SQL_COMMAND,
		PGC_USERSET, 0, NULL, NULL, NULL);

	DefineCustomStringVariable(
		psprintf("%s.alternate_index_handler_name", prefix),
		gettext_noop(
			"The name of the index handler to use as opposed to rum (currently for testing only)."),
		NULL, &AlternateIndexHandler, DEFAULT_ALTERNATE_INDEX_HANDLER,
		PGC_USERSET, 0, NULL, NULL, NULL);

	DefineCustomBoolVariable(
		psprintf("%s.logRelationIndexesOrder", newGucPrefix),
		gettext_noop(
			"Whether to log the order of indexes in the relation."),
		NULL, &EnableLogRelationIndexesOrder, DEFAULT_LOG_RELATION_INDEXES_ORDER,
		PGC_USERSET, 0, NULL, NULL, NULL);

	DefineCustomBoolVariable(
		psprintf("%s.enable_large_unique_index_keys", newGucPrefix),
		gettext_noop("Whether or not to enable large index keys on unique indexes."),
		NULL, &DefaultEnableLargeUniqueIndexKeys, DEFAULT_ENABLE_LARGE_UNIQUE_INDEX_KEYS,
		PGC_USERSET, 0, NULL, NULL, NULL);

	DefineCustomBoolVariable(
		psprintf("%s.enableDebugQueryText", newGucPrefix),
		gettext_noop(
			"Whether to enable query source text while planning aggregate/find queries for debugging, starts deparsing the query tree and degrades performance."),
		NULL, &EnableDebugQueryText, DEFAULT_ENABLE_DEBUG_QUERY_TEXT,
		PGC_USERSET, 0, NULL, NULL, NULL);

	DefineCustomBoolVariable(
		psprintf("%s.enableMultiIndexRumJoin", newGucPrefix),
		gettext_noop(
			"Whether or not to add the cursors on aggregation style queries."),
		NULL,
		&EnableMultiIndexRumJoin,
		DEFAULT_ENABLE_MULTI_INDEX_RUM_JOIN,
		PGC_USERSET,
		0,
		NULL, NULL, NULL);
}
