import type { LogLevel, WorkflowSettings } from 'n8n-workflow';

import type {
	ChatHubLLMProvider,
	ChatHubSemanticSearchSettings,
	ChatProviderSettingsDto,
} from './chat-hub';
import type { QuickConnectOption } from './quick-connect';
import type { InsightsDateRange } from './schemas/insights.schema';
import type { WorkflowReviewsPolicy } from './workflow-reviews-policy';

export interface IVersionNotificationSettings {
	enabled: boolean;
	endpoint: string;
	whatsNewEnabled: boolean;
	whatsNewEndpoint: string;
	infoUrl: string;
}

export interface ITelemetryClientConfig {
	url: string;
	key: string;
	proxy: string;
	sourceConfig: string;
}

export interface ITelemetrySettings {
	enabled: boolean;
	config?: ITelemetryClientConfig;
}

export const AuthenticationMethod = {
	Email: 'email',
	Ldap: 'ldap',
	Saml: 'saml',
	Oidc: 'oidc',
	TokenExchange: 'token-exchange',
} as const;

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

export interface IUserManagementSettings {
	quota: number;
	showSetupOnFirstLoad?: boolean;
	smtpSetup: boolean;
	authenticationMethod: AuthenticationMethod;
	passwordMinLength: number;
}

export interface IEnterpriseSettings {
	sharing: boolean;
	ldap: boolean;
	saml: boolean;
	oidc: boolean;
	mfaEnforcement: boolean;
	logStreaming: boolean;
	advancedExecutionFilters: boolean;
	variables: boolean;
	sourceControl: boolean;
	auditLogs: boolean;
	externalSecrets: boolean;
	showNonProdBanner: boolean;
	debugInEditor: boolean;
	binaryDataS3: boolean;
	workerView: boolean;
	advancedPermissions: boolean;
	workflowDiffs: boolean;
	namedVersions: boolean;
	provisioning: boolean;
	projects: {
		team: {
			limit: number;
		};
	};
	customRoles: boolean;
	personalSpacePolicy: boolean;
	dataRedaction: boolean;
	otelCustomSpanAttributes: boolean;
	workflowReviews: boolean;
}

export interface FrontendSettings {
	settingsMode?: 'public' | 'authenticated';
	inE2ETests: boolean;
	isDocker: boolean;
	databaseType: 'sqlite' | 'postgresdb';
	endpointForm: string;
	endpointFormTest: string;
	endpointFormWaiting: string;
	endpointMcp: string;
	endpointMcpTest: string;
	endpointWebhook: string;
	endpointWebhookTest: string;
	endpointWebhookWaiting: string;
	endpointHealth: string;
	saveDataErrorExecution: WorkflowSettings.SaveDataExecution;
	saveDataSuccessExecution: WorkflowSettings.SaveDataExecution;
	saveManualExecutions: boolean;
	saveExecutionProgress: boolean;
	executionTimeout: number;
	maxExecutionTimeout: number;
	workflowCallerPolicyDefaultOption: WorkflowSettings.CallerPolicy;
	excludeNodes: string[];
	oauthCallbackUrls: {
		oauth1: string;
		oauth2: string;
	};
	jwksUri: string;
	timezone: string;
	urlBaseWebhook: string;
	urlBaseEditor: string;
	urlBaseWebhookTest: string;
	versionCli: string;
	nodeJsVersion: string;
	nodeEnv: string | undefined;
	concurrency: number;
	evaluationConcurrencyLimit: number;
	authCookie: {
		secure: boolean;
	};
	binaryDataMode: 'default' | 'filesystem' | 's3' | 'azure' | 'database';
	releaseChannel: 'stable' | 'beta' | 'nightly' | 'dev' | 'rc';
	n8nMetadata?: {
		userId?: string;
		[key: string]: string | number | undefined;
	};
	versionNotifications: IVersionNotificationSettings;
	dynamicBanners: {
		endpoint: string;
		enabled: boolean;
		filters: {
			publishedWorkflowCount: number;
		};
	};
	instanceId: string;
	telemetry: ITelemetrySettings;
	posthog: {
		enabled: boolean;
		apiHost: string;
		apiKey: string;
		autocapture: boolean;
		disableSessionRecording: boolean;
		debug: boolean;
		proxy: string;
	};
	dataTables: {
		maxSize: number;
	};
	personalizationSurveyEnabled: boolean;
	defaultLocale: string;
	userManagement: IUserManagementSettings;
	sso: {
		managedByEnv: boolean;
		saml: {
			loginLabel: string;
			loginEnabled: boolean;
		};
		oidc: {
			loginEnabled: boolean;
			loginUrl: string;
			callbackUrl: string;
		};
		ldap: {
			loginLabel: string;
			loginEnabled: boolean;
		};
	};
	logStreaming: {
		managedByEnv: boolean;
	};
	publicApi: {
		enabled: boolean;
		latestVersion: number;
		path: string;
		swaggerUi: {
			enabled: boolean;
		};
	};
	workflowTagsDisabled: boolean;
	workflowsAutosaveDisabled: boolean;
	useWorkflowPublicationService: boolean;
	logLevel: LogLevel;
	hiringBannerEnabled: boolean;
	previewMode: boolean;
	templates: {
		enabled: boolean;
		host: string;
	};
	executionMode: 'regular' | 'queue';
	/** Whether multi-main mode is enabled and licensed for this main instance. */
	isMultiMain: boolean;
	pushBackend: 'sse' | 'websocket';
	communityNodesEnabled: boolean;
	unverifiedCommunityNodesEnabled: boolean;
	communityNodesManagedByEnv: boolean;
	aiAssistant: {
		enabled: boolean;
		setup: boolean;
	};
	/**
	 * @deprecated Gates the AI Transform node's code generation. No longer gates
	 * the Code node's "Ask AI" tab, which is hidden. Removed in v3.
	 */
	askAi: {
		enabled: boolean;
	};
	aiBuilder: {
		enabled: boolean;
		setup: boolean;
	};
	deployment: {
		type: string;
	};
	allowedModules: {
		builtIn?: string[];
		external?: string[];
	};
	enterprise: IEnterpriseSettings;
	hideUsagePage: boolean;
	license: {
		planName?: string;
		consumerId: string;
		environment: 'development' | 'production' | 'staging';
	};
	variables: {
		limit: number;
	};
	mfa: {
		enabled: boolean;
		enforced: boolean;
	};
	workflowReviews?: WorkflowReviewsPolicy;
	folders: {
		enabled: boolean;
	};
	workerPools: {
		enabled: boolean;
	};
	collaboration: {
		crdt: 'off' | 'local' | 'server';
	};
	banners: {
		dismissed: string[];
	};
	workflowHistory: {
		pruneTime: number;
		licensePruneTime: number;
	};
	aiCredits: {
		enabled: boolean;
		credits: number;
		setup: boolean;
	};
	aiGateway?: {
		enabled: boolean;
		budget: number;
		cloudUbbEnabled: boolean;
	};
	ai: {
		allowSendingParameterValues: boolean;
	};
	pruning?: {
		isEnabled: boolean;
		maxAge: number;
		maxCount: number;
	};
	security: {
		blockFileAccessToN8nFiles: boolean;
		/**
		 * Origins allowed to exchange `postMessage` commands with the editor iframe.
		 * Empty means no restriction (any origin is accepted).
		 */
		postMessageAllowedOrigins: string[];
	};
	chatTrigger?: {
		disablePublicChat: boolean;
	};
	easyAIWorkflowOnboarded: boolean;
	evaluation: {
		quota: number;
		/**
		 * Operator override (`N8N_EVAL_COLLECTIONS_ENABLED`) that force-enables the
		 * eval-collections surface. Surfaced here so the frontend gate works even
		 * when the in-browser PostHog client is disabled (telemetry off), where the
		 * `084_eval_collections` flag would otherwise never resolve.
		 */
		collectionsEnabled: boolean;
		/**
		 * Operator override (`N8N_CONFIG_EVALS_ENABLED`) that force-enables the
		 * config-based evals surface. Surfaced here so the in-editor gate works
		 * even when the browser PostHog client is disabled (telemetry off), where
		 * the `088_config_evaluations` flag would otherwise never resolve.
		 */
		configEvalsEnabled: boolean;
		/**
		 * Operator override (`N8N_AGENT_EVALS_ENABLED`) that force-enables the
		 * agent-evals surface. Surfaced here so the frontend gate works even when
		 * the in-browser PostHog client is disabled (telemetry off), where the
		 * `101_agent_evals` flag would otherwise never resolve.
		 */
		agentEvalsEnabled: boolean;
	};

	/** Backend modules that were initialized during startup. */
	activeModules: string[];
	canvasOnly: boolean;
	envFeatureFlags: N8nEnvFeatFlags;
}

export type FrontendModuleSettings = {
	/**
	 * Client settings for [insights](https://docs.n8n.io/insights/) module.
	 *
	 * - `summary`: Whether the summary banner should be shown.
	 * - `dashboard`: Whether the full dashboard should be shown.
	 * - `dateRanges`: Date range filters available to select.
	 */
	insights?: {
		summary: boolean;
		dashboard: boolean;
		dateRanges: InsightsDateRange[];
		earliestDataDate: string | null;
	};

	/**
	 * Client settings for MCP module.
	 */
	mcp?: {
		/** Whether MCP access is enabled in the instance. */
		mcpAccessEnabled: boolean;
		/** Whether MCP settings are managed via environment variables. */
		mcpManagedByEnv: boolean;
		/** Public URL of the instance MCP server endpoint. */
		serverUrl?: string;
		/** Whether newly created workflows are auto-exposed to MCP. */
		autoExposeNewWorkflows: boolean;
	};

	/**
	 * Client settings for the encryption-key-manager module.
	 */
	'encryption-key-manager'?: {
		/** Whether encryption-key rotation (and its management UI) is enabled. */
		rotationEnabled: boolean;
	};

	/**
	 * Client settings for Chat module.
	 */
	'chat-hub'?: {
		enabled: boolean;
		providers: Record<ChatHubLLMProvider, ChatProviderSettingsDto>;
		semanticSearch: ChatHubSemanticSearchSettings;
		agentUploadMaxSizeMb: number;
	};

	/**
	 * Client settings for instance AI module.
	 */
	'instance-ai'?: {
		enabled: boolean;
		localGatewayDisabled: boolean;
		browserUseEnabled: boolean;
		proxyEnabled: boolean;
		cloudManaged: boolean;
		/** Whether model, sandbox, and the explicit web-search decision are configured. */
		setupCompleted?: boolean;
		sandboxEnabled: boolean;
		workflowBuilderAvailable: boolean;
		sandboxUnavailableReason: string | null;
		/** When true, orchestrator LLM step / workflow code debug is captured (`N8N_INSTANCE_AI_RUN_DEBUG_ENABLED`). */
		runDebugEnabled: boolean;
		/** Whether this instance is in the activation-capped trial cohort (`N8N_INSTANCE_AI_ACTIVATION_CAPPED`). Optional. */
		activationCapped?: boolean;
		/** Whether the non-blocking setup panel replaces the suspending setup wizard (`N8N_INSTANCE_AI_SETUP_PANEL_ENABLED`). */
		instanceAiSetupPanelEnabled?: boolean;
	};

	/**
	 * Quick connect settings
	 */
	'quick-connect'?: {
		options: QuickConnectOption[];
	};

	/**
	 * Client settings for external secrets module.
	 */
	'external-secrets'?: {
		/** Whether multiple connections per vault type are enabled. */
		multipleConnections: boolean;
		/** Whether project-scoped external secrets are enabled. */
		forProjects: boolean;
		/** Whether role-based access control for external secrets is enabled. */
		roleBasedAccess: boolean;
		/** Whether system roles (admin, editor) have external secrets scopes. */
		systemRolesEnabled: boolean;
	};

	/**
	 * Client settings for the OpenTelemetry module.
	 */
	otel?: {
		/** Whether OpenTelemetry tracing is enabled on this instance. */
		enabled: boolean;
	};

	/**
	 * Client settings for the agents module.
	 */
	agents?: {
		/**
		 * Enabled agent sub-feature modules. Each token unlocks a specific
		 * capability inside the agents module (see the backend's
		 * `AGENTS_MODULE_NAMES` for the known set). Controlled via
		 * `N8N_AGENTS_MODULES`
		 */
		modules: string[];
		/**
		 * Whether the agent knowledge base is enabled by the backend's
		 * `N8N_AGENTS_AI_SANDBOX_ENABLED` opt-in.
		 */
		knowledgeBaseEnabled: boolean;
		/** Whether the AI Assistant proxy is available to the agents module. */
		proxyEnabled: boolean;
	};
};

export type N8nEnvFeatFlagValue = boolean | string | number | undefined;
export type N8nEnvFeatFlags = Record<`N8N_ENV_FEAT_${Uppercase<string>}`, N8nEnvFeatFlagValue>;
