/**
 * SMTP Server Constants
 * This file contains all constants and enums used by the SMTP server
 */

import { SmtpState } from '../interfaces.js';

// Re-export SmtpState enum from the main interfaces file
export { SmtpState };

/**
 * SMTP Response Codes
 * Based on RFC 5321 and common SMTP practice
 */
export enum SmtpResponseCode {
  // Success codes (2xx)
  SUCCESS = 250,                    // Requested mail action okay, completed
  SYSTEM_STATUS = 211,              // System status, or system help reply
  HELP_MESSAGE = 214,               // Help message
  SERVICE_READY = 220,              // <domain> Service ready
  SERVICE_CLOSING = 221,            // <domain> Service closing transmission channel
  AUTHENTICATION_SUCCESSFUL = 235,  // Authentication successful
  OK = 250,                         // Requested mail action okay, completed
  FORWARD = 251,                    // User not local; will forward to <forward-path>
  CANNOT_VRFY = 252,                // Cannot VRFY user, but will accept message and attempt delivery
  
  // Intermediate codes (3xx)
  MORE_INFO_NEEDED = 334,           // Server challenge for authentication
  START_MAIL_INPUT = 354,           // Start mail input; end with <CRLF>.<CRLF>
  
  // Temporary error codes (4xx)
  SERVICE_NOT_AVAILABLE = 421,      // <domain> Service not available, closing transmission channel
  MAILBOX_TEMPORARILY_UNAVAILABLE = 450, // Requested mail action not taken: mailbox unavailable
  LOCAL_ERROR = 451,                // Requested action aborted: local error in processing
  INSUFFICIENT_STORAGE = 452,       // Requested action not taken: insufficient system storage
  TLS_UNAVAILABLE_TEMP = 454,       // TLS not available due to temporary reason
  
  // Permanent error codes (5xx)
  SYNTAX_ERROR = 500,               // Syntax error, command unrecognized
  SYNTAX_ERROR_PARAMETERS = 501,    // Syntax error in parameters or arguments
  COMMAND_NOT_IMPLEMENTED = 502,    // Command not implemented
  BAD_SEQUENCE = 503,               // Bad sequence of commands
  COMMAND_PARAMETER_NOT_IMPLEMENTED = 504, // Command parameter not implemented
  AUTH_REQUIRED = 530,              // Authentication required
  AUTH_FAILED = 535,                // Authentication credentials invalid
  MAILBOX_UNAVAILABLE = 550,        // Requested action not taken: mailbox unavailable
  USER_NOT_LOCAL = 551,             // User not local; please try <forward-path>
  EXCEEDED_STORAGE = 552,           // Requested mail action aborted: exceeded storage allocation
  MAILBOX_NAME_INVALID = 553,       // Requested action not taken: mailbox name not allowed
  TRANSACTION_FAILED = 554,         // Transaction failed
  MAIL_RCPT_PARAMETERS_INVALID = 555, // MAIL FROM/RCPT TO parameters not recognized or not implemented
}

/**
 * SMTP Command Types
 */
export enum SmtpCommand {
  HELO = 'HELO',
  EHLO = 'EHLO',
  MAIL_FROM = 'MAIL',
  RCPT_TO = 'RCPT',
  DATA = 'DATA',
  RSET = 'RSET',
  NOOP = 'NOOP',
  QUIT = 'QUIT',
  STARTTLS = 'STARTTLS',
  AUTH = 'AUTH',
  HELP = 'HELP',
  VRFY = 'VRFY',
  EXPN = 'EXPN',
}

/**
 * Security log event types
 */
export enum SecurityEventType {
  CONNECTION = 'connection',
  AUTHENTICATION = 'authentication',
  COMMAND = 'command',
  DATA = 'data',
  IP_REPUTATION = 'ip_reputation',
  TLS_NEGOTIATION = 'tls_negotiation',
  DKIM = 'dkim',
  SPF = 'spf',
  DMARC = 'dmarc',
  EMAIL_VALIDATION = 'email_validation',
  SPAM = 'spam',
  ACCESS_CONTROL = 'access_control',
}

/**
 * Security log levels
 */
export enum SecurityLogLevel {
  DEBUG = 'debug',
  INFO = 'info',
  WARN = 'warn',
  ERROR = 'error',
}

/**
 * SMTP Server Defaults
 */
export const SMTP_DEFAULTS = {
  // Default timeouts in milliseconds
  CONNECTION_TIMEOUT: 30000,       // 30 seconds
  SOCKET_TIMEOUT: 300000,          // 5 minutes
  DATA_TIMEOUT: 60000,             // 1 minute
  CLEANUP_INTERVAL: 5000,          // 5 seconds
  
  // Default limits
  MAX_CONNECTIONS: 100,
  MAX_RECIPIENTS: 100,
  MAX_MESSAGE_SIZE: 10485760,      // 10MB
  
  // Default ports
  SMTP_PORT: 25,
  SUBMISSION_PORT: 587,
  SECURE_PORT: 465,
  
  // Default hostname
  HOSTNAME: 'mail.lossless.one',
  
  // CRLF line ending required by SMTP protocol
  CRLF: '\r\n',
};

/**
 * SMTP Command Patterns
 * Regular expressions for parsing SMTP commands
 */
export const SMTP_PATTERNS = {
  // Match EHLO/HELO command: "EHLO example.com"
  // Made very permissive to handle various client implementations
  EHLO: /^(?:EHLO|HELO)\s+(.+)$/i,
  
  // Match MAIL FROM command: "MAIL FROM:<user@example.com> [PARAM=VALUE]"
  // Made more permissive with whitespace and parameter formats
  MAIL_FROM: /^MAIL\s+FROM\s*:\s*<([^>]*)>((?:\s+[a-zA-Z0-9][a-zA-Z0-9\-]*(?:=[^\s]+)?)*)$/i,
  
  // Match RCPT TO command: "RCPT TO:<user@example.com> [PARAM=VALUE]"
  // Made more permissive with whitespace and parameter formats
  RCPT_TO: /^RCPT\s+TO\s*:\s*<([^>]*)>((?:\s+[a-zA-Z0-9][a-zA-Z0-9\-]*(?:=[^\s]+)?)*)$/i,
  
  // Match parameter format: "PARAM=VALUE"
  PARAM: /\s+([A-Za-z0-9][A-Za-z0-9\-]*)(?:=([^\s]+))?/g,
  
  // Match email address format - basic validation
  // This pattern rejects common invalid formats while being permissive for edge cases
  // Checks: no spaces, has @, has domain with dot, no double dots, proper domain format
  EMAIL: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
  
  // Match end of DATA marker: \r\n.\r\n or just .\r\n at the start of a line (to handle various client implementations)
  END_DATA: /(\r\n\.\r\n$)|(\n\.\r\n$)|(\r\n\.\n$)|(\n\.\n$)|^\.(\r\n|\n)$/,
};

/**
 * SMTP Extension List
 * These extensions are advertised in the EHLO response
 */
export const SMTP_EXTENSIONS = {
  // Basic extensions (RFC 1869)
  PIPELINING: 'PIPELINING',
  SIZE: 'SIZE',
  EIGHTBITMIME: '8BITMIME',
  
  // Security extensions
  STARTTLS: 'STARTTLS',
  AUTH: 'AUTH',
  
  // Additional extensions
  ENHANCEDSTATUSCODES: 'ENHANCEDSTATUSCODES',
  HELP: 'HELP',
  CHUNKING: 'CHUNKING',
  DSN: 'DSN',
  
  // Format an extension with a parameter
  formatExtension(name: string, parameter?: string | number): string {
    return parameter !== undefined ? `${name} ${parameter}` : name;
  }
};