/**
 * Enhanced payload masking with config-driven rules
 * Enterprise-grade security for audit log payloads
 */
export class AuditPayloadMasker {
	private static MAX_PAYLOAD_SIZE = 64 * 1024; // 64KB

	private static MASKING_RULES = {
		// Exact field matches
		exact: [
			'password',
			'password_hash',
			'token',
			'refresh_token',
			'access_token',
			'secret',
			'api_key',
			'otp',
			'cccd',
			'id_card',
			'ssn',
			'credit_card',
			'bank_account',
			'pin',
			'cvv',
		],
		// Regex patterns - more specific to avoid false positives
		regex: [
			/pwd/i,
			/auth_token/i,
			/auth_secret/i,
			/auth_key/i,
			/api_secret/i,
			/access_key/i,
			/secret_key/i,
			/private_key/i,
			/bearer_token/i,
			/session_token/i,
		],
		// JSON paths (using dot notation)
		paths: ['user.password', 'auth.token', 'payment.card_number'],
	};

	/**
	 * Mask sensitive data in audit payloads
	 */
	static mask(payload: any): any {
		if (!payload || typeof payload !== 'object') {
			return payload;
		}

		const masked = { ...payload };

		for (const key in masked) {
			const lowerKey = key.toLowerCase();

			// Check exact matches
			if (this.MASKING_RULES.exact.some((field) => lowerKey.includes(field))) {
				masked[key] = '***MASKED***';
				continue;
			}

			// Check regex patterns
			if (this.MASKING_RULES.regex.some((pattern) => pattern.test(key))) {
				masked[key] = '***MASKED***';
				continue;
			}

			// Recursively mask nested objects
			if (typeof masked[key] === 'object' && masked[key] !== null) {
				masked[key] = this.mask(masked[key]);
			}
		}

		return masked;
	}

	/**
	 * Validate and truncate payload to safe size
	 * Returns structured object instead of malformed JSON
	 */
	static validateAndTruncate(payload: any): any {
		const payloadStr = JSON.stringify(payload);

		if (payloadStr.length > this.MAX_PAYLOAD_SIZE) {
			// Safe truncation: return structured object instead of malformed JSON
			return {
				truncated: true,
				original_size: payloadStr.length,
				max_size: this.MAX_PAYLOAD_SIZE,
				preview: payloadStr.substring(0, this.MAX_PAYLOAD_SIZE - 200),
				message: 'Payload truncated due to size limit',
			};
		}

		return payload;
	}

	/**
	 * Calculate payload size in bytes
	 */
	static calculateSize(payload: any): number {
		return JSON.stringify(payload).length;
	}
}
