/**
 * Typed error codes and status mapping for the EmDash REST API.
 *
 * All handler-level and route-level error codes are defined here.
 * Routes and handlers should import error codes from this module
 * instead of using ad-hoc strings.
 */

export const ErrorCode = {
	// Shared (used across domains)
	NOT_FOUND: "NOT_FOUND",
	VALIDATION_ERROR: "VALIDATION_ERROR",
	INVALID_INPUT: "INVALID_INPUT",
	INVALID_JSON: "INVALID_JSON",
	CONFLICT: "CONFLICT",
	NOT_CONFIGURED: "NOT_CONFIGURED",
	UNAUTHORIZED: "UNAUTHORIZED",
	FORBIDDEN: "FORBIDDEN",
	RATE_LIMITED: "RATE_LIMITED",
	NOT_AUTHENTICATED: "NOT_AUTHENTICATED",
	NOT_IMPLEMENTED: "NOT_IMPLEMENTED",
	NOT_SUPPORTED: "NOT_SUPPORTED",
	MISSING_PARAM: "MISSING_PARAM",
	CSRF_REJECTED: "CSRF_REJECTED",

	// Content
	CONTENT_CREATE_ERROR: "CONTENT_CREATE_ERROR",
	CONTENT_UPDATE_ERROR: "CONTENT_UPDATE_ERROR",
	CONTENT_DELETE_ERROR: "CONTENT_DELETE_ERROR",
	CONTENT_LIST_ERROR: "CONTENT_LIST_ERROR",
	CONTENT_GET_ERROR: "CONTENT_GET_ERROR",
	CONTENT_DUPLICATE_ERROR: "CONTENT_DUPLICATE_ERROR",
	CONTENT_RESTORE_ERROR: "CONTENT_RESTORE_ERROR",
	CONTENT_PUBLISH_ERROR: "CONTENT_PUBLISH_ERROR",
	CONTENT_UNPUBLISH_ERROR: "CONTENT_UNPUBLISH_ERROR",
	CONTENT_SCHEDULE_ERROR: "CONTENT_SCHEDULE_ERROR",
	CONTENT_UNSCHEDULE_ERROR: "CONTENT_UNSCHEDULE_ERROR",
	CONTENT_DISCARD_DRAFT_ERROR: "CONTENT_DISCARD_DRAFT_ERROR",
	CONTENT_COMPARE_ERROR: "CONTENT_COMPARE_ERROR",
	CONTENT_TRANSLATIONS_ERROR: "CONTENT_TRANSLATIONS_ERROR",
	CONTENT_COUNT_ERROR: "CONTENT_COUNT_ERROR",

	// Revisions
	REVISION_LIST_ERROR: "REVISION_LIST_ERROR",
	REVISION_GET_ERROR: "REVISION_GET_ERROR",
	REVISION_RESTORE_ERROR: "REVISION_RESTORE_ERROR",
	INVALID_REVISION: "INVALID_REVISION",

	// Schema
	SCHEMA_LIST_ERROR: "SCHEMA_LIST_ERROR",
	SCHEMA_GET_ERROR: "SCHEMA_GET_ERROR",
	SCHEMA_CREATE_ERROR: "SCHEMA_CREATE_ERROR",
	SCHEMA_UPDATE_ERROR: "SCHEMA_UPDATE_ERROR",
	SCHEMA_DELETE_ERROR: "SCHEMA_DELETE_ERROR",
	SCHEMA_EXPORT_ERROR: "SCHEMA_EXPORT_ERROR",
	SCHEMA_FIELD_LIST_ERROR: "SCHEMA_FIELD_LIST_ERROR",
	SCHEMA_FIELD_GET_ERROR: "SCHEMA_FIELD_GET_ERROR",
	SCHEMA_FIELD_CREATE_ERROR: "SCHEMA_FIELD_CREATE_ERROR",
	SCHEMA_FIELD_UPDATE_ERROR: "SCHEMA_FIELD_UPDATE_ERROR",
	SCHEMA_FIELD_DELETE_ERROR: "SCHEMA_FIELD_DELETE_ERROR",
	SCHEMA_FIELD_REORDER_ERROR: "SCHEMA_FIELD_REORDER_ERROR",
	ORPHAN_LIST_ERROR: "ORPHAN_LIST_ERROR",
	ORPHAN_REGISTER_ERROR: "ORPHAN_REGISTER_ERROR",
	COLLECTION_EXISTS: "COLLECTION_EXISTS",
	COLLECTION_NOT_FOUND: "COLLECTION_NOT_FOUND",
	TABLE_NOT_FOUND: "TABLE_NOT_FOUND",
	FIELD_EXISTS: "FIELD_EXISTS",
	RESERVED_SLUG: "RESERVED_SLUG",
	INVALID_SLUG: "INVALID_SLUG",
	CREATE_FAILED: "CREATE_FAILED",
	UPDATE_FAILED: "UPDATE_FAILED",
	REGISTER_FAILED: "REGISTER_FAILED",

	// Media
	MEDIA_LIST_ERROR: "MEDIA_LIST_ERROR",
	MEDIA_GET_ERROR: "MEDIA_GET_ERROR",
	MEDIA_CREATE_ERROR: "MEDIA_CREATE_ERROR",
	MEDIA_UPDATE_ERROR: "MEDIA_UPDATE_ERROR",
	MEDIA_DELETE_ERROR: "MEDIA_DELETE_ERROR",
	NO_STORAGE: "NO_STORAGE",
	NO_FILE: "NO_FILE",
	INVALID_TYPE: "INVALID_TYPE",
	UPLOAD_ERROR: "UPLOAD_ERROR",
	UPLOAD_URL_ERROR: "UPLOAD_URL_ERROR",
	CONFIRM_ERROR: "CONFIRM_ERROR",
	CONFIRM_FAILED: "CONFIRM_FAILED",
	FILE_NOT_FOUND: "FILE_NOT_FOUND",
	INVALID_STATE: "INVALID_STATE",
	FILE_SERVE_ERROR: "FILE_SERVE_ERROR",
	STORAGE_NOT_CONFIGURED: "STORAGE_NOT_CONFIGURED",
	PROVIDER_LIST_ERROR: "PROVIDER_LIST_ERROR",
	PROVIDER_UPLOAD_ERROR: "PROVIDER_UPLOAD_ERROR",
	PROVIDER_GET_ERROR: "PROVIDER_GET_ERROR",
	PROVIDER_DELETE_ERROR: "PROVIDER_DELETE_ERROR",

	// Comments
	COMMENT_LIST_ERROR: "COMMENT_LIST_ERROR",
	COMMENT_GET_ERROR: "COMMENT_GET_ERROR",
	COMMENT_STATUS_ERROR: "COMMENT_STATUS_ERROR",
	COMMENT_DELETE_ERROR: "COMMENT_DELETE_ERROR",
	COMMENT_BULK_ERROR: "COMMENT_BULK_ERROR",
	COMMENT_INBOX_ERROR: "COMMENT_INBOX_ERROR",
	COMMENT_COUNTS_ERROR: "COMMENT_COUNTS_ERROR",
	COMMENT_CREATE_ERROR: "COMMENT_CREATE_ERROR",
	COMMENTS_DISABLED: "COMMENTS_DISABLED",
	COMMENTS_CLOSED: "COMMENTS_CLOSED",
	COMMENT_REJECTED: "COMMENT_REJECTED",

	// Auth
	ACCOUNT_DISABLED: "ACCOUNT_DISABLED",
	ADMIN_EXISTS: "ADMIN_EXISTS",
	SETUP_COMPLETE: "SETUP_COMPLETE",
	CREDENTIAL_EXISTS: "CREDENTIAL_EXISTS",
	CHALLENGE_EXPIRED: "CHALLENGE_EXPIRED",
	PASSKEY_REGISTER_ERROR: "PASSKEY_REGISTER_ERROR",
	PASSKEY_REGISTER_OPTIONS_ERROR: "PASSKEY_REGISTER_OPTIONS_ERROR",
	PASSKEY_OPTIONS_ERROR: "PASSKEY_OPTIONS_ERROR",
	PASSKEY_VERIFY_ERROR: "PASSKEY_VERIFY_ERROR",
	PASSKEY_LIST_ERROR: "PASSKEY_LIST_ERROR",
	PASSKEY_RENAME_ERROR: "PASSKEY_RENAME_ERROR",
	PASSKEY_DELETE_ERROR: "PASSKEY_DELETE_ERROR",
	PASSKEY_LIMIT: "PASSKEY_LIMIT",
	LAST_PASSKEY: "LAST_PASSKEY",
	LOGOUT_ERROR: "LOGOUT_ERROR",
	SELF_ROLE_CHANGE: "SELF_ROLE_CHANGE",
	EMAIL_IN_USE: "EMAIL_IN_USE",
	EMAIL_NOT_CONFIGURED: "EMAIL_NOT_CONFIGURED",
	USER_EXISTS: "USER_EXISTS",
	INVALID_TOKEN: "INVALID_TOKEN",
	TOKEN_EXPIRED: "TOKEN_EXPIRED",
	DOMAIN_NOT_ALLOWED: "DOMAIN_NOT_ALLOWED",
	INVITE_CREATE_ERROR: "INVITE_CREATE_ERROR",
	INVITE_VALIDATE_ERROR: "INVITE_VALIDATE_ERROR",
	INVITE_COMPLETE_ERROR: "INVITE_COMPLETE_ERROR",
	SIGNUP_VERIFY_ERROR: "SIGNUP_VERIFY_ERROR",
	SIGNUP_COMPLETE_ERROR: "SIGNUP_COMPLETE_ERROR",
	RECOVERY_SEND_ERROR: "RECOVERY_SEND_ERROR",
	USER_LIST_ERROR: "USER_LIST_ERROR",
	USER_DETAIL_ERROR: "USER_DETAIL_ERROR",
	USER_UPDATE_ERROR: "USER_UPDATE_ERROR",
	USER_DISABLE_ERROR: "USER_DISABLE_ERROR",
	USER_ENABLE_ERROR: "USER_ENABLE_ERROR",

	// OAuth (internal codes -- distinct from RFC OAuthErrorCode)
	UNSUPPORTED_RESPONSE_TYPE: "UNSUPPORTED_RESPONSE_TYPE",
	INVALID_REDIRECT_URI: "INVALID_REDIRECT_URI",
	INVALID_CLIENT: "INVALID_CLIENT",
	INVALID_SCOPE: "INVALID_SCOPE",
	AUTHORIZATION_ERROR: "AUTHORIZATION_ERROR",
	INVALID_GRANT: "INVALID_GRANT",
	UNSUPPORTED_GRANT_TYPE: "UNSUPPORTED_GRANT_TYPE",
	INVALID_CODE: "INVALID_CODE",
	EXPIRED_CODE: "EXPIRED_CODE",
	INSUFFICIENT_ROLE: "INSUFFICIENT_ROLE",
	TOKEN_EXCHANGE_ERROR: "TOKEN_EXCHANGE_ERROR",
	TOKEN_REFRESH_ERROR: "TOKEN_REFRESH_ERROR",
	TOKEN_REVOKE_ERROR: "TOKEN_REVOKE_ERROR",
	TOKEN_CREATE_ERROR: "TOKEN_CREATE_ERROR",
	TOKEN_LIST_ERROR: "TOKEN_LIST_ERROR",
	TOKEN_ERROR: "TOKEN_ERROR",
	DEVICE_CODE_ERROR: "DEVICE_CODE_ERROR",
	AUTHORIZE_ERROR: "AUTHORIZE_ERROR",
	CLIENT_LIST_ERROR: "CLIENT_LIST_ERROR",
	CLIENT_GET_ERROR: "CLIENT_GET_ERROR",
	CLIENT_CREATE_ERROR: "CLIENT_CREATE_ERROR",
	CLIENT_UPDATE_ERROR: "CLIENT_UPDATE_ERROR",
	CLIENT_DELETE_ERROR: "CLIENT_DELETE_ERROR",

	// Allowed domains
	DOMAIN_LIST_ERROR: "DOMAIN_LIST_ERROR",
	DOMAIN_CREATE_ERROR: "DOMAIN_CREATE_ERROR",
	DOMAIN_UPDATE_ERROR: "DOMAIN_UPDATE_ERROR",
	DOMAIN_DELETE_ERROR: "DOMAIN_DELETE_ERROR",

	// Plugins / Marketplace
	PLUGIN_LIST_ERROR: "PLUGIN_LIST_ERROR",
	PLUGIN_GET_ERROR: "PLUGIN_GET_ERROR",
	PLUGIN_ENABLE_ERROR: "PLUGIN_ENABLE_ERROR",
	PLUGIN_DISABLE_ERROR: "PLUGIN_DISABLE_ERROR",
	PLUGIN_ID_CONFLICT: "PLUGIN_ID_CONFLICT",
	MARKETPLACE_NOT_CONFIGURED: "MARKETPLACE_NOT_CONFIGURED",
	MARKETPLACE_UNAVAILABLE: "MARKETPLACE_UNAVAILABLE",
	MARKETPLACE_ERROR: "MARKETPLACE_ERROR",
	SANDBOX_NOT_AVAILABLE: "SANDBOX_NOT_AVAILABLE",
	ALREADY_INSTALLED: "ALREADY_INSTALLED",
	ALREADY_UP_TO_DATE: "ALREADY_UP_TO_DATE",
	NO_VERSION: "NO_VERSION",
	MANIFEST_MISMATCH: "MANIFEST_MISMATCH",
	MANIFEST_VERSION_MISMATCH: "MANIFEST_VERSION_MISMATCH",
	AUDIT_FAILED: "AUDIT_FAILED",
	CHECKSUM_MISMATCH: "CHECKSUM_MISMATCH",
	INVALID_BUNDLE: "INVALID_BUNDLE",
	BUNDLE_EXTRACT_FAILED: "BUNDLE_EXTRACT_FAILED",
	BUNDLE_DOWNLOAD_FAILED: "BUNDLE_DOWNLOAD_FAILED",
	CAPABILITY_ESCALATION: "CAPABILITY_ESCALATION",
	ROUTE_VISIBILITY_ESCALATION: "ROUTE_VISIBILITY_ESCALATION",
	INSTALL_FAILED: "INSTALL_FAILED",
	UNINSTALL_FAILED: "UNINSTALL_FAILED",
	SEARCH_FAILED: "SEARCH_FAILED",
	GET_PLUGIN_FAILED: "GET_PLUGIN_FAILED",
	GET_THEME_FAILED: "GET_THEME_FAILED",
	THEME_SEARCH_FAILED: "THEME_SEARCH_FAILED",
	UPDATE_CHECK_FAILED: "UPDATE_CHECK_FAILED",
	EXCLUSIVE_HOOKS_LIST_ERROR: "EXCLUSIVE_HOOKS_LIST_ERROR",
	EXCLUSIVE_HOOK_SET_ERROR: "EXCLUSIVE_HOOK_SET_ERROR",

	// Menus
	MENU_LIST_ERROR: "MENU_LIST_ERROR",
	MENU_CREATE_ERROR: "MENU_CREATE_ERROR",
	MENU_GET_ERROR: "MENU_GET_ERROR",
	MENU_UPDATE_ERROR: "MENU_UPDATE_ERROR",
	MENU_DELETE_ERROR: "MENU_DELETE_ERROR",
	MENU_ITEM_CREATE_ERROR: "MENU_ITEM_CREATE_ERROR",
	MENU_ITEM_UPDATE_ERROR: "MENU_ITEM_UPDATE_ERROR",
	MENU_ITEM_DELETE_ERROR: "MENU_ITEM_DELETE_ERROR",
	MENU_REORDER_ERROR: "MENU_REORDER_ERROR",

	// Taxonomies
	TAXONOMY_LIST_ERROR: "TAXONOMY_LIST_ERROR",
	TAXONOMY_CREATE_ERROR: "TAXONOMY_CREATE_ERROR",
	TERM_LIST_ERROR: "TERM_LIST_ERROR",
	TERM_CREATE_ERROR: "TERM_CREATE_ERROR",
	TERM_GET_ERROR: "TERM_GET_ERROR",
	TERM_UPDATE_ERROR: "TERM_UPDATE_ERROR",
	TERM_DELETE_ERROR: "TERM_DELETE_ERROR",
	TERMS_GET_ERROR: "TERMS_GET_ERROR",
	TERMS_SET_ERROR: "TERMS_SET_ERROR",

	// Sections
	SECTION_LIST_ERROR: "SECTION_LIST_ERROR",
	SECTION_CREATE_ERROR: "SECTION_CREATE_ERROR",
	SECTION_GET_ERROR: "SECTION_GET_ERROR",
	SECTION_UPDATE_ERROR: "SECTION_UPDATE_ERROR",
	SECTION_DELETE_ERROR: "SECTION_DELETE_ERROR",

	// Redirects
	REDIRECT_LIST_ERROR: "REDIRECT_LIST_ERROR",
	REDIRECT_CREATE_ERROR: "REDIRECT_CREATE_ERROR",
	REDIRECT_GET_ERROR: "REDIRECT_GET_ERROR",
	REDIRECT_UPDATE_ERROR: "REDIRECT_UPDATE_ERROR",
	REDIRECT_DELETE_ERROR: "REDIRECT_DELETE_ERROR",
	NOT_FOUND_LIST_ERROR: "NOT_FOUND_LIST_ERROR",
	NOT_FOUND_SUMMARY_ERROR: "NOT_FOUND_SUMMARY_ERROR",
	NOT_FOUND_CLEAR_ERROR: "NOT_FOUND_CLEAR_ERROR",
	NOT_FOUND_PRUNE_ERROR: "NOT_FOUND_PRUNE_ERROR",

	// Widgets
	WIDGET_AREA_LIST_ERROR: "WIDGET_AREA_LIST_ERROR",
	WIDGET_AREA_CREATE_ERROR: "WIDGET_AREA_CREATE_ERROR",
	WIDGET_AREA_GET_ERROR: "WIDGET_AREA_GET_ERROR",
	WIDGET_AREA_DELETE_ERROR: "WIDGET_AREA_DELETE_ERROR",
	WIDGET_CREATE_ERROR: "WIDGET_CREATE_ERROR",
	WIDGET_UPDATE_ERROR: "WIDGET_UPDATE_ERROR",
	WIDGET_DELETE_ERROR: "WIDGET_DELETE_ERROR",
	WIDGET_REORDER_ERROR: "WIDGET_REORDER_ERROR",
	WIDGET_COMPONENTS_ERROR: "WIDGET_COMPONENTS_ERROR",

	// Setup
	ALREADY_CONFIGURED: "ALREADY_CONFIGURED",
	INVALID_SEED: "INVALID_SEED",
	INVALID_REDIRECT: "INVALID_REDIRECT",
	SETUP_ERROR: "SETUP_ERROR",
	SETUP_STATUS_ERROR: "SETUP_STATUS_ERROR",
	SETUP_ADMIN_ERROR: "SETUP_ADMIN_ERROR",
	SETUP_VERIFY_ERROR: "SETUP_VERIFY_ERROR",
	DEV_BYPASS_ERROR: "DEV_BYPASS_ERROR",
	DEV_RESET_ERROR: "DEV_RESET_ERROR",
	MIGRATION_ERROR: "MIGRATION_ERROR",
	SEED_ERROR: "SEED_ERROR",

	// Settings
	SETTINGS_READ_ERROR: "SETTINGS_READ_ERROR",
	SETTINGS_UPDATE_ERROR: "SETTINGS_UPDATE_ERROR",
	EMAIL_SETTINGS_READ_ERROR: "EMAIL_SETTINGS_READ_ERROR",
	EMAIL_TEST_ERROR: "EMAIL_TEST_ERROR",

	// Search
	SEARCH_ERROR: "SEARCH_ERROR",
	STATS_ERROR: "STATS_ERROR",
	SUGGESTION_ERROR: "SUGGESTION_ERROR",
	REBUILD_ERROR: "REBUILD_ERROR",

	// Import
	WXR_ANALYZE_ERROR: "WXR_ANALYZE_ERROR",
	WXR_PREPARE_ERROR: "WXR_PREPARE_ERROR",
	WXR_IMPORT_ERROR: "WXR_IMPORT_ERROR",
	IMPORT_ERROR: "IMPORT_ERROR",
	REWRITE_ERROR: "REWRITE_ERROR",
	WP_PLUGIN_ANALYZE_ERROR: "WP_PLUGIN_ANALYZE_ERROR",
	WP_PLUGIN_IMPORT_ERROR: "WP_PLUGIN_IMPORT_ERROR",
	SSRF_BLOCKED: "SSRF_BLOCKED",
	PROBE_ERROR: "PROBE_ERROR",

	// Dashboard
	DASHBOARD_ERROR: "DASHBOARD_ERROR",
	DASHBOARD_STATS_ERROR: "DASHBOARD_STATS_ERROR",

	// Misc
	SNAPSHOT_ERROR: "SNAPSHOT_ERROR",
	TYPEGEN_ERROR: "TYPEGEN_ERROR",
	SITEMAP_ERROR: "SITEMAP_ERROR",
	NO_DB: "NO_DB",
	INVALID_REQUEST: "INVALID_REQUEST",
	UNKNOWN_ACTION: "UNKNOWN_ACTION",
} as const;

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

/**
 * OAuth RFC 6749 error codes.
 *
 * These MUST be lowercase per the RFC spec. Used only by OAuth token endpoints.
 * Separate from ErrorCode to prevent mixing conventions.
 */
export const OAuthErrorCode = {
	INVALID_GRANT: "invalid_grant",
	UNSUPPORTED_GRANT_TYPE: "unsupported_grant_type",
	EXPIRED_TOKEN: "expired_token",
	ACCESS_DENIED: "access_denied",
	AUTHORIZATION_PENDING: "authorization_pending",
} as const;

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

/**
 * Map a handler error code to an HTTP status code.
 *
 * Shared codes have explicit mappings. Domain-specific `*_ERROR` codes
 * (used in catch blocks via handleError) default to 500. Everything else
 * defaults to 400 (client error).
 */
export function mapErrorStatus(code: string | undefined): number {
	switch (code) {
		// 400 Bad Request
		case ErrorCode.VALIDATION_ERROR:
		case ErrorCode.INVALID_INPUT:
		case ErrorCode.INVALID_JSON:
		case ErrorCode.MISSING_PARAM:
		case ErrorCode.INVALID_REQUEST:
		case ErrorCode.NOT_SUPPORTED:
		case ErrorCode.INVALID_SLUG:
		case ErrorCode.RESERVED_SLUG:
		case ErrorCode.INVALID_TYPE:
		case ErrorCode.NO_FILE:
		case ErrorCode.INVALID_STATE:
		case ErrorCode.INVALID_SEED:
		case ErrorCode.INVALID_REDIRECT:
		case ErrorCode.INVALID_TOKEN:
		case ErrorCode.INVALID_REVISION:
		case ErrorCode.INVALID_CODE:
		case ErrorCode.CHALLENGE_EXPIRED:
		case ErrorCode.EXPIRED_CODE:
		case ErrorCode.LAST_PASSKEY:
		case ErrorCode.PASSKEY_LIMIT:
		case ErrorCode.ADMIN_EXISTS:
		case ErrorCode.SETUP_COMPLETE:
		case ErrorCode.SELF_ROLE_CHANGE:
		case ErrorCode.SSRF_BLOCKED:
		case ErrorCode.UNKNOWN_ACTION:
			return 400;

		// 401 Unauthorized
		case ErrorCode.UNAUTHORIZED:
		case ErrorCode.NOT_AUTHENTICATED:
			return 401;

		// 403 Forbidden
		case ErrorCode.FORBIDDEN:
		case ErrorCode.CSRF_REJECTED:
		case ErrorCode.ACCOUNT_DISABLED:
		case ErrorCode.COMMENTS_DISABLED:
		case ErrorCode.COMMENTS_CLOSED:
		case ErrorCode.COMMENT_REJECTED:
		case ErrorCode.DOMAIN_NOT_ALLOWED:
		case ErrorCode.INSUFFICIENT_ROLE:
		case ErrorCode.CAPABILITY_ESCALATION:
		case ErrorCode.ROUTE_VISIBILITY_ESCALATION:
		case ErrorCode.AUDIT_FAILED:
			return 403;

		// 404 Not Found
		case ErrorCode.NOT_FOUND:
		case ErrorCode.TABLE_NOT_FOUND:
		case ErrorCode.COLLECTION_NOT_FOUND:
		case ErrorCode.FILE_NOT_FOUND:
		case ErrorCode.NO_VERSION:
			return 404;

		// 409 Conflict
		case ErrorCode.CONFLICT:
		case ErrorCode.COLLECTION_EXISTS:
		case ErrorCode.FIELD_EXISTS:
		case ErrorCode.CREDENTIAL_EXISTS:
		case ErrorCode.EMAIL_IN_USE:
		case ErrorCode.USER_EXISTS:
		case ErrorCode.PLUGIN_ID_CONFLICT:
		case ErrorCode.ALREADY_INSTALLED:
		case ErrorCode.ALREADY_CONFIGURED:
		case ErrorCode.ALREADY_UP_TO_DATE:
			return 409;

		// 410 Gone
		case ErrorCode.TOKEN_EXPIRED:
			return 410;

		// 422 Unprocessable Entity
		case ErrorCode.CHECKSUM_MISMATCH:
		case ErrorCode.INVALID_BUNDLE:
		case ErrorCode.BUNDLE_EXTRACT_FAILED:
			return 422;

		// 429 Too Many Requests
		case ErrorCode.RATE_LIMITED:
			return 429;

		// 500 Internal Server Error
		case ErrorCode.NOT_CONFIGURED:
		case ErrorCode.NO_STORAGE:
		case ErrorCode.NO_DB:
		case ErrorCode.STORAGE_NOT_CONFIGURED:
		case ErrorCode.EMAIL_NOT_CONFIGURED:
			return 500;

		// 501 Not Implemented
		case ErrorCode.NOT_IMPLEMENTED:
			return 501;

		// 502 Bad Gateway
		case ErrorCode.BUNDLE_DOWNLOAD_FAILED:
			return 502;

		// 503 Service Unavailable
		case ErrorCode.MARKETPLACE_UNAVAILABLE:
		case ErrorCode.MARKETPLACE_NOT_CONFIGURED:
		case ErrorCode.SANDBOX_NOT_AVAILABLE:
			return 503;

		// Domain-specific *_ERROR codes are catch-block codes -- always 500.
		// WARNING: If adding a new code that ends in _ERROR but represents a
		// client error (4xx), add it to an explicit case above or it will
		// be incorrectly mapped to 500.
		default:
			return code?.endsWith("_ERROR") ? 500 : 400;
	}
}
