/**
 * Typed error codes shared across the evaluations save flow (controller → 4xx body)
 * and the run flow (`test_run.errorCode`). Source of truth is design spec §6.
 */
export const EvaluationErrorCode = {
	EVALUATION_QUOTA_EXCEEDED: 'EVALUATION_QUOTA_EXCEEDED',
	CONFIG_NOT_FOUND: 'CONFIG_NOT_FOUND',
	CONFIG_INVALID: 'CONFIG_INVALID',
	START_NODE_NOT_FOUND: 'START_NODE_NOT_FOUND',
	END_NODE_NOT_FOUND: 'END_NODE_NOT_FOUND',
	END_NODE_UNREACHABLE: 'END_NODE_UNREACHABLE',
	AMBIGUOUS_ENTRY_NODE: 'AMBIGUOUS_ENTRY_NODE',
	RESERVED_PREFIX_IN_USE: 'RESERVED_PREFIX_IN_USE',
	DATASET_NOT_FOUND: 'DATASET_NOT_FOUND',
	DATASET_ACCESS_DENIED: 'DATASET_ACCESS_DENIED',
	UNSUPPORTED_DATASET_SOURCE: 'UNSUPPORTED_DATASET_SOURCE',
	LLM_PROVIDER_UNSUPPORTED: 'LLM_PROVIDER_UNSUPPORTED',
	LLM_CREDENTIAL_NOT_FOUND: 'LLM_CREDENTIAL_NOT_FOUND',
	LLM_CREDENTIAL_ACCESS_DENIED: 'LLM_CREDENTIAL_ACCESS_DENIED',
	LLM_CREDENTIAL_TYPE_MISMATCH: 'LLM_CREDENTIAL_TYPE_MISMATCH',
	DUPLICATE_METRIC_ID: 'DUPLICATE_METRIC_ID',
	DUPLICATE_METRIC_NAME: 'DUPLICATE_METRIC_NAME',
	BOOLEAN_COERCION_UNSUPPORTED: 'BOOLEAN_COERCION_UNSUPPORTED',
	START_NODE_DELETED: 'START_NODE_DELETED',
	END_NODE_DELETED: 'END_NODE_DELETED',
	METRIC_NODE_REF_DELETED: 'METRIC_NODE_REF_DELETED',
	LLM_PROVIDER_REMOVED: 'LLM_PROVIDER_REMOVED',
	COMPILATION_FAILED: 'COMPILATION_FAILED',
	// A metric's input mapping is whitespace-only after trim — accepts a
	// non-empty string at the schema level but resolves to nothing at run time.
	METRIC_INPUT_EMPTY: 'METRIC_INPUT_EMPTY',
} as const;

export type EvaluationErrorCode = (typeof EvaluationErrorCode)[keyof typeof EvaluationErrorCode];

export type EvaluationApiError = {
	code: EvaluationErrorCode;
	message: string;
	details?: {
		nodeName?: string;
		metricId?: string;
		metricName?: string;
		credentialId?: string;
		nodeType?: string;
		field?: string;
	};
};
