import type {
	AuthenticationMethod,
	ProjectRelation,
	RedactionEnforcementSettings,
} from '@n8n/api-types';
import type { AuthProviderType, User, IWorkflowDb } from '@n8n/db';
import type {
	CancellationReason,
	IPersonalizationSurveyAnswersV4,
	IRun,
	IWorkflowBase,
	IWorkflowExecutionDataProcess,
	JsonValue,
	WorkflowExecuteMode,
	WorkflowSettings,
} from 'n8n-workflow';

import type { ConcurrencyQueueType } from '@/concurrency/concurrency-control.service';
import type { TokenExchangeFailureReason } from '@/modules/token-exchange/token-exchange.types';

import type { AiEventMap } from './ai.event-map';

export type WorkflowActionSource = 'ui' | 'api' | 'n8n-mcp' | 'n8n-ai' | 'import';

export type UserLike = {
	id: string;
	email?: string;
	firstName?: string;
	lastName?: string;
	role?: {
		slug: string;
	};
};

export type ProjectSummary = {
	id: string;
	name: string;
};

export type RelayEventMap = {
	// #region Lifecycle

	'server-started': {};

	'session-started': {
		pushRef?: string;
	};

	'instance-stopped': {};

	'instance-owner-setup': {
		userId: string;
	};

	'first-production-workflow-succeeded': {
		projectId: string;
		workflowId: string;
		userId: string | null;
	};

	'instance-first-production-workflow-failed': {
		projectId: string;
		workflowId: string;
		workflowName: string;
		userId: string;
	};

	'first-workflow-data-loaded': {
		userId: string;
		workflowId: string;
		nodeType: string;
		nodeId: string;
		credentialType?: string;
		credentialId?: string;
	};

	// #endregion

	// #region Workflow

	'workflow-created': {
		user: UserLike;
		workflow: IWorkflowBase;
		publicApi: boolean;
		projectId: string;
		projectType: string;
		uiContext?: string;
		source?: WorkflowActionSource;
	};

	'workflows-imported': {
		user: UserLike;
		projectId: string;
		workflowIds: string[];
		packageSourceId: string;
		packageVersion: string;
	};

	'workflow-deleted': {
		user: UserLike;
		workflowId: string;
		publicApi: boolean;
	};

	'workflow-archived': {
		user: UserLike;
		workflowId: string;
		publicApi: boolean;
	};

	'workflow-unarchived': {
		user: UserLike;
		workflowId: string;
		publicApi: boolean;
	};

	'workflow-saved': {
		user: UserLike;
		workflow: IWorkflowDb;
		publicApi: boolean;
		previousWorkflow?: IWorkflowDb;
		aiBuilderAssisted?: boolean;
		settingsChanged?: Record<string, { from: JsonValue; to: JsonValue }>;
		source?: WorkflowActionSource;
	};

	'workflow-activated': {
		user: UserLike;
		workflowId: string;
		workflow: IWorkflowDb;
		publicApi: boolean;
		source?: WorkflowActionSource;
	};

	'workflow-deactivated': {
		user: UserLike;
		workflowId: string;
		workflow: IWorkflowDb;
		publicApi: boolean;
		deactivatedVersionId: string | null;
		source?: WorkflowActionSource;
	};

	'workflow-pre-execute': {
		executionId: string;
		data: IWorkflowExecutionDataProcess /* main process */ | IWorkflowBase /* worker */;
		mode: WorkflowExecuteMode;
		projectId?: string;
		projectName?: string;
	};

	'workflow-post-execute': {
		executionId: string;
		userId?: string;
		workflow: IWorkflowBase;
		runData?: IRun;
		projectId?: string;
		projectName?: string;
		telemetryMetadata?: IWorkflowExecutionDataProcess['telemetryMetadata'];
	};

	'workflow-sharing-updated': {
		workflowId: string;
		userIdSharer: string;
		userIdList: string[];
	};

	'workflow-executed': {
		user?: UserLike;
		workflowId: string;
		workflowName: string;
		executionId: string;
		source:
			| 'user-manual'
			| 'user-retry'
			| 'webhook'
			| 'trigger'
			| 'error'
			| 'cli'
			| 'integrated'
			| 'evaluation'
			| 'chat';
	};

	'workflow-version-updated': {
		user: UserLike;
		workflowId: string;
		workflowName: string;
		versionId: string;
		versionName?: string | null;
		versionDescription?: string | null;
	};

	// #endregion

	// #region Node

	'node-pre-execute': {
		executionId: string;
		workflow: IWorkflowBase;
		nodeId?: string;
		nodeName: string;
		nodeType?: string;
	};

	'node-post-execute': {
		executionId: string;
		workflow: IWorkflowBase;
		nodeId?: string;
		nodeName: string;
		nodeType?: string;
	};

	// #endregion

	// #region User

	'user-submitted-personalization-survey': {
		userId: string;
		answers: IPersonalizationSurveyAnswersV4;
	};

	'user-deleted': {
		user: UserLike;
		publicApi: boolean;
		targetUserOldStatus: 'active' | 'invited';
		migrationStrategy?: 'transfer_data' | 'delete_data';
		targetUserId?: string;
		migrationUserId?: string;
	};

	'user-invited': {
		user: UserLike;
		targetUserId: string[];
		publicApi: boolean;
		emailSent: boolean;
		inviteeRole: string;
	};

	'user-reinvited': {
		user: UserLike;
		targetUserId: string[];
	};

	'user-updated': {
		user: UserLike;
		fieldsChanged: string[];
	};

	'user-mfa-enabled': {
		user: UserLike;
	};

	'user-mfa-disabled': {
		user: UserLike;
		disableMethod: 'mfaCode' | 'recoveryCode';
	};

	'user-signed-up': {
		user: UserLike;
		userType: AuthProviderType;
		wasDisabledLdapUser: boolean;
	};

	'user-logged-in': {
		user: UserLike;
		authenticationMethod: AuthenticationMethod;
	};

	'user-login-failed': {
		userEmail: string;
		authenticationMethod: AuthenticationMethod;
		reason?: string;
	};

	'user-changed-role': {
		userId: string;
		targetUserId: string;
		publicApi: boolean;
		targetUserNewRole: string;
	};

	'user-retrieved-user': {
		userId: string;
		publicApi: boolean;
	};

	'user-retrieved-all-users': {
		userId: string;
		publicApi: boolean;
	};

	'user-retrieved-execution': {
		userId: string;
		publicApi: boolean;
	};

	'user-retrieved-all-executions': {
		userId: string;
		publicApi: boolean;
	};

	'user-retried-execution': {
		userId: string;
		publicApi: boolean;
	};

	'user-retrieved-workflow': {
		userId: string;
		publicApi: boolean;
	};

	'user-retrieved-workflow-version': {
		userId: string;
		publicApi: boolean;
	};

	'user-retrieved-all-workflows': {
		userId: string;
		publicApi: boolean;
	};

	// #endregion

	// #region Click

	'user-invite-email-click': {
		inviter: UserLike;
		invitee: UserLike;
	};

	'user-password-reset-email-click': {
		user: UserLike;
	};

	'user-password-reset-request-click': {
		user: UserLike;
	};

	'user-transactional-email-sent': {
		userId: string;
		messageType:
			| 'Reset password'
			| 'New user invite'
			| 'Resend invite'
			| 'Workflow auto-deactivated'
			| 'Workflow shared'
			| 'Credentials shared'
			| 'Project shared';
		publicApi: boolean;
	};

	// #endregion

	// #region Public API

	'public-api-key-created': {
		user: UserLike;
		publicApi: boolean;
	};

	'public-api-key-deleted': {
		user: UserLike;
		publicApi: boolean;
	};

	'public-api-invoked': {
		userId: string;
		path: string;
		method: string;
		apiVersion: string;
		userAgent?: string;
	};

	// #endregion

	// #region Email

	'email-failed': {
		user: UserLike;
		messageType:
			| 'Reset password'
			| 'New user invite'
			| 'Resend invite'
			| 'Workflow shared'
			| 'Workflow auto-deactivated'
			| 'Credentials shared'
			| 'Project shared';
		publicApi: boolean;
	};

	// #endregion

	// #region Credentials

	'credentials-created': {
		user: UserLike;
		credentialType: string;
		credentialId: string;
		publicApi: boolean;
		projectId?: string;
		projectType?: string;
		uiContext?: string;
		isDynamic?: boolean;
		usesExternalSecrets?: boolean;
		jweEnabled?: boolean;
	};

	'credentials-shared': {
		user: UserLike;
		credentialType: string;
		credentialId: string;
		userIdSharer: string;
		userIdsShareesAdded: string[];
		shareesRemoved: number | null;
	};

	'credentials-updated': {
		user: UserLike;
		credentialType: string;
		credentialId: string;
		isDynamic?: boolean;
		usesExternalSecrets?: boolean;
		jweEnabled?: boolean;
	};

	'credentials-deleted': {
		user: UserLike;
		credentialType: string;
		credentialId: string;
	};

	'credentials-user-disconnected': {
		user: UserLike;
		credentialType: string;
		credentialId: string;
	};

	// #endregion

	// #region Community package

	'community-package-installed': {
		user: UserLike;
		inputString: string;
		packageName: string;
		success: boolean;
		packageVersion?: string;
		packageNodeNames?: string[];
		packageAuthor?: string;
		packageAuthorEmail?: string;
		failureReason?: string;
	};

	'community-package-updated': {
		user: UserLike;
		packageName: string;
		packageVersionCurrent: string;
		packageVersionNew: string;
		packageNodeNames: string[];
		packageAuthor?: string;
		packageAuthorEmail?: string;
	};

	'community-package-deleted': {
		user: UserLike;
		packageName: string;
		packageVersion: string;
		packageNodeNames: string[];
		packageAuthor?: string;
		packageAuthorEmail?: string;
	};

	// #endregion

	// #region Execution

	'execution-throttled': {
		executionId: string;
		type: ConcurrencyQueueType;
	};

	'execution-started-during-bootup': {
		executionId: string;
	};

	'execution-cancelled': {
		executionId: string;
		workflowId?: string;
		workflowName?: string;
		reason: CancellationReason;
	};

	'execution-deleted': {
		user: UserLike;
		executionIds: string[];
		deleteBefore?: Date;
	};

	'execution-waiting': {
		executionId: string;
		workflowId: string;
	};

	'execution-resumed': {
		executionId: string;
		workflowId: string;
		resumeSource: 'webhook';
		responseAt: Date;
	};

	'execution-data-revealed': {
		user: UserLike;
		executionId: string;
		workflowId: string;
		ipAddress: string;
		userAgent: string;
		redactionPolicy: WorkflowSettings.RedactionPolicy;
	};

	'execution-data-reveal-failure': {
		user: UserLike;
		executionId: string;
		workflowId: string;
		ipAddress: string;
		userAgent: string;
		redactionPolicy: WorkflowSettings.RedactionPolicy;
		rejectionReason: string;
	};

	// #endregion

	// #region Project

	'team-project-updated': {
		userId: string;
		role: string;
		members: ProjectRelation[];
		projectId: string;
	};

	'team-project-deleted': {
		userId: string;
		role: string;
		projectId: string;
		removalType: 'transfer' | 'delete';
		targetProjectId?: string;
	};

	'team-project-created': {
		userId: string;
		role: string;
		uiContext?: string;
	};

	// #endregion

	// #region Source control

	'source-control-settings-updated': {
		branchName: string;
		readOnlyInstance: boolean;
		repoType: 'github' | 'gitlab' | 'other';
		connected: boolean;
		connectionType: 'ssh' | 'https';
	};

	'source-control-user-started-pull-ui': {
		userId?: string;
		workflowUpdates: number;
		workflowConflicts: number;
		credConflicts: number;
	};

	'source-control-user-finished-pull-ui': {
		userId?: string;
		workflowUpdates: number;
	};

	'source-control-user-pulled-api': {
		workflowUpdates: number;
		forced: boolean;
	};

	'source-control-user-started-push-ui': {
		userId?: string;
		workflowsEligible: number;
		workflowsEligibleWithConflicts: number;
		credsEligible: number;
		credsEligibleWithConflicts: number;
		variablesEligible: number;
	};

	'source-control-user-finished-push-ui': {
		userId: string;
		workflowsEligible: number;
		workflowsPushed: number;
		credsPushed: number;
		variablesPushed: number;
	};

	// #endregion

	// #region License

	'license-renewal-attempted': {
		success: boolean;
	};

	'license-community-plus-registered': {
		userId: User['id'];
		email: string;
		licenseKey: string;
	};

	// #endregion

	// #region Variable

	'variable-created': {
		user: UserLike;
		variableId: string;
		variableKey: string;
		projectId?: string;
	};

	'variable-updated': {
		user: UserLike;
		variableId: string;
		variableKey: string;
		projectId?: string;
	};

	'variable-deleted': {
		user: UserLike;
		variableId: string;
		variableKey: string;
		projectId?: string;
	};

	// #endregion

	// #region External secrets

	'external-secrets-provider-settings-saved': {
		userId?: string;
		vaultType: string;
		isValid: boolean;
		isNew: boolean;
		errorMessage?: string;
	};

	'external-secrets-provider-reloaded': {
		vaultType: string;
	};

	'external-secrets-connection-created': {
		userId: string;
		userRole?: string;
		providerKey: string;
		vaultType: string;
		projects: ProjectSummary[];
	};

	'external-secrets-connection-updated': {
		userId: string;
		userRole?: string;
		providerKey: string;
		vaultType: string;
		projects: ProjectSummary[];
	};

	'external-secrets-connection-deleted': {
		userId: string;
		userRole?: string;
		providerKey: string;
		vaultType: string;
		projects: ProjectSummary[];
	};

	'external-secrets-connection-tested': {
		userId: string;
		userRole?: string;
		providerKey: string;
		vaultType: string;
		projects: ProjectSummary[];
		isValid: boolean;
		errorMessage?: string;
	};

	'external-secrets-connection-reloaded': {
		userId: string;
		userRole?: string;
		providerKey: string;
		vaultType: string;
		projects: ProjectSummary[];
	};

	'external-secrets-system-roles-toggled': {
		userId: string;
		enabled: boolean;
	};

	// #endregion

	// #region LDAP

	'ldap-general-sync-finished': {
		type: string;
		succeeded: boolean;
		usersSynced: number;
		error: string;
	};

	'ldap-settings-updated': {
		userId: string;
		loginIdAttribute: string;
		firstNameAttribute: string;
		lastNameAttribute: string;
		emailAttribute: string;
		ldapIdAttribute: string;
		searchPageSize: number;
		searchTimeout: number;
		synchronizationEnabled: boolean;
		synchronizationInterval: number;
		loginLabel: string;
		loginEnabled: boolean;
	};

	'ldap-login-sync-failed': {
		error: string;
	};

	'login-failed-due-to-ldap-disabled': {
		userId: string;
	};

	// #endregion

	// #region SSO

	'sso-user-project-access-updated': {
		projectsRemoved: number;
		projectsAdded: number;
		userId: string;
	};

	'sso-user-instance-role-updated': {
		role: string;
		userId: string;
	};

	// #endregion

	// #region Role Mapping

	'expression-mapping-roles-resolved': {
		userId: string;
		userEmail: string;
		provider: 'oidc' | 'saml' | 'ldap';
		instanceRole: {
			role: string;
			previousRole: string;
			changed: boolean;
			matchedRuleId: string | null;
			expression: string | null;
			isFallback: boolean;
		};
		projectRoles: Array<{
			projectId: string;
			role: string;
			previousRole: string | null;
			changed: boolean;
			matchedRuleId: string;
			expression: string;
		}>;
		removedProjectIds: string[];
	};

	'role-mapping-rule-created': {
		user: UserLike;
		ruleId: string;
		ruleType: 'instance' | 'project';
		expression: string;
		role: string;
	};

	'role-mapping-rule-updated': {
		user: UserLike;
		ruleId: string;
		ruleType: 'instance' | 'project';
		patchedFields: string[];
	};

	'role-mapping-rule-deleted': {
		user: UserLike;
		ruleId: string;
		ruleType: 'instance' | 'project';
	};

	'role-mapping-rules-bulk-deleted': {
		ruleType: 'instance' | 'project';
		count: number;
		reason: 'strategy-switch';
	};

	// #endregion

	// #region Token exchange

	'token-exchange-succeeded': {
		subject: string;
		actor?: string;
		scopes?: string;
		resource?: string;
		grantType: string;
		kid?: string;
		issuer: string;
		tokenId?: string;
		clientIp: string;
	};

	'token-exchange-failed': {
		subject?: string;
		failureReason: TokenExchangeFailureReason;
		grantType: string;
		clientIp: string;
	};

	'embed-login': {
		subject: string;
		issuer: string;
		kid: string;
		clientIp: string;
	};

	'embed-login-failed': {
		failureReason: TokenExchangeFailureReason;
		clientIp: string;
	};

	'token-exchange-identity-linked': {
		userId: string;
		sub: string;
		email: string;
		kid: string;
		issuer: string;
	};

	'token-exchange-user-provisioned': {
		userId: string;
		sub: string;
		email: string;
		role: string;
		kid: string;
		issuer: string;
	};

	'token-exchange-role-updated': {
		userId: string;
		previousRole: string;
		newRole: string;
		kid: string;
		issuer: string;
	};

	// #endregion

	// #region runner

	'runner-task-requested': {
		taskId: string;
		nodeId: string;
		workflowId: string;
		executionId: string;
	};

	'runner-response-received': {
		taskId: string;
		nodeId: string;
		workflowId: string;
		executionId: string;
	};

	// #endregion

	// #region queue

	'job-enqueued': {
		executionId: string;
		workflowId: string;
		hostId: string;
		jobId: string;
	};

	'job-dequeued': {
		executionId: string;
		workflowId: string;
		hostId: string;
		jobId: string;
	};

	'job-stalled': {
		executionId: string;
		workflowId: string;
		hostId: string;
		jobId: string;
	};

	// #endregion

	// #region workflow history compaction
	'history-compacted': {
		workflowsProcessed: number;
		totalVersionsSeen: number;
		totalVersionsDeleted: number;
		errorCount: number;
		durationMs: number;
		windowStartIso: string;
		windowEndIso: string;
		compactionStartTime: Date;
	};
	// #endregion

	// #region Data Tables

	'data-table-deleted': {
		dataTableId: string;
		projectId: string;
	};

	// #endregion

	// #region Folders

	'folder-deleted': {
		folderId: string;
		projectId: string;
	};

	// #endregion

	// #region Instance Policies

	'instance-policies-updated': {
		user: UserLike;
		settingName: '2fa_enforcement' | 'workflow_publishing' | 'workflow_sharing';
		value: boolean;
	};

	'redaction-enforcement-updated': {
		user: UserLike;
		before: RedactionEnforcementSettings;
		after: RedactionEnforcementSettings;
	};

	// #endregion

	// #region Custom Roles

	'custom-role-created': {
		userId: string;
		roleSlug: string;
		scopes: string[];
	};

	'custom-role-updated': {
		userId: string;
		roleSlug: string;
		scopes: string[];
	};

	'custom-role-deleted': {
		userId: string;
		roleSlug: string;
	};

	// #endregion

	// #region Instance AI

	'instance-ai-settings-updated': {
		mcpSettingsChanged: boolean;
	};

	// #endregion
} & AiEventMap;
