/**
 * SMTP Client Validation Utilities
 * Input validation functions for SMTP client operations
 */

import { REGEX_PATTERNS } from '../constants.js';
import type { ISmtpClientOptions, ISmtpAuthOptions } from '../interfaces.js';

/**
 * Validate email address format
 * Supports RFC-compliant addresses including empty return paths for bounces
 */
export function validateEmailAddress(email: string): boolean {
  if (typeof email !== 'string') {
    return false;
  }
  
  const trimmed = email.trim();
  
  // Handle empty return path for bounce messages (RFC 5321)
  if (trimmed === '' || trimmed === '<>') {
    return true;
  }
  
  // Handle display name formats
  const angleMatch = trimmed.match(/<([^>]+)>/);
  if (angleMatch) {
    return REGEX_PATTERNS.EMAIL_ADDRESS.test(angleMatch[1]);
  }
  
  // Regular email validation
  return REGEX_PATTERNS.EMAIL_ADDRESS.test(trimmed);
}

/**
 * Validate SMTP client options
 */
export function validateClientOptions(options: ISmtpClientOptions): string[] {
  const errors: string[] = [];
  
  // Required fields
  if (!options.host || typeof options.host !== 'string') {
    errors.push('Host is required and must be a string');
  }
  
  if (!options.port || typeof options.port !== 'number' || options.port < 1 || options.port > 65535) {
    errors.push('Port must be a number between 1 and 65535');
  }
  
  // Optional field validation
  if (options.connectionTimeout !== undefined) {
    if (typeof options.connectionTimeout !== 'number' || options.connectionTimeout < 1000) {
      errors.push('Connection timeout must be a number >= 1000ms');
    }
  }
  
  if (options.socketTimeout !== undefined) {
    if (typeof options.socketTimeout !== 'number' || options.socketTimeout < 1000) {
      errors.push('Socket timeout must be a number >= 1000ms');
    }
  }
  
  if (options.maxConnections !== undefined) {
    if (typeof options.maxConnections !== 'number' || options.maxConnections < 1) {
      errors.push('Max connections must be a positive number');
    }
  }
  
  if (options.maxMessages !== undefined) {
    if (typeof options.maxMessages !== 'number' || options.maxMessages < 1) {
      errors.push('Max messages must be a positive number');
    }
  }
  
  // Validate authentication options
  if (options.auth) {
    errors.push(...validateAuthOptions(options.auth));
  }
  
  return errors;
}

/**
 * Validate authentication options
 */
export function validateAuthOptions(auth: ISmtpAuthOptions): string[] {
  const errors: string[] = [];
  
  if (auth.method && !['PLAIN', 'LOGIN', 'OAUTH2', 'AUTO'].includes(auth.method)) {
    errors.push('Invalid authentication method');
  }
  
  // For basic auth, require user and pass
  if ((auth.user || auth.pass) && (!auth.user || !auth.pass)) {
    errors.push('Both user and pass are required for basic authentication');
  }
  
  // For OAuth2, validate required fields
  if (auth.oauth2) {
    const oauth = auth.oauth2;
    if (!oauth.user || !oauth.clientId || !oauth.clientSecret || !oauth.refreshToken) {
      errors.push('OAuth2 requires user, clientId, clientSecret, and refreshToken');
    }
    
    if (oauth.user && !validateEmailAddress(oauth.user)) {
      errors.push('OAuth2 user must be a valid email address');
    }
  }
  
  return errors;
}

/**
 * Validate hostname format
 */
export function validateHostname(hostname: string): boolean {
  if (!hostname || typeof hostname !== 'string') {
    return false;
  }
  
  // Basic hostname validation (allow IP addresses and domain names)
  const hostnameRegex = /^(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)*[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$|^(?:\d{1,3}\.){3}\d{1,3}$|^\[(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}\]$/;
  return hostnameRegex.test(hostname);
}

/**
 * Validate port number
 */
export function validatePort(port: number): boolean {
  return typeof port === 'number' && port >= 1 && port <= 65535;
}

/**
 * Sanitize and validate domain name for EHLO
 */
export function validateAndSanitizeDomain(domain: string): string {
  if (!domain || typeof domain !== 'string') {
    return 'localhost';
  }
  
  const sanitized = domain.trim().toLowerCase();
  if (validateHostname(sanitized)) {
    return sanitized;
  }
  
  return 'localhost';
}

/**
 * Validate recipient list
 */
export function validateRecipients(recipients: string | string[]): string[] {
  const errors: string[] = [];
  const recipientList = Array.isArray(recipients) ? recipients : [recipients];
  
  for (const recipient of recipientList) {
    if (!validateEmailAddress(recipient)) {
      errors.push(`Invalid email address: ${recipient}`);
    }
  }
  
  return errors;
}

/**
 * Validate sender address
 */
export function validateSender(sender: string): boolean {
  return validateEmailAddress(sender);
}