/**
 * SMTP Server Interfaces
 * Defines all the interfaces used by the SMTP server implementation
 */

import * as plugins from '../../../plugins.js';
import type { Email } from '../../core/classes.email.js';
import type { UnifiedEmailServer } from '../../routing/classes.unified.email.server.js';

// Re-export types from other modules  
import { SmtpState } from '../interfaces.js';
import { SmtpCommand } from './constants.js';
export { SmtpState, SmtpCommand };
export type { IEnvelopeRecipient } from '../interfaces.js';

/**
 * Interface for components that need cleanup
 */
export interface IDestroyable {
  /**
   * Clean up all resources (timers, listeners, etc)
   */
  destroy(): void | Promise<void>;
}

/**
 * SMTP authentication credentials
 */
export interface ISmtpAuth {
  /**
   * Username for authentication
   */
  username: string;
  
  /**
   * Password for authentication
   */
  password: string;
}

/**
 * SMTP envelope (sender and recipients)
 */
export interface ISmtpEnvelope {
  /**
   * Mail from address
   */
  mailFrom: {
    address: string;
    args?: Record<string, string>;
  };
  
  /**
   * Recipients list
   */
  rcptTo: Array<{
    address: string;
    args?: Record<string, string>;
  }>;
}

/**
 * SMTP session representing a client connection
 */
export interface ISmtpSession {
  /**
   * Unique session identifier
   */
  id: string;
  
  /**
   * Current state of the SMTP session
   */
  state: SmtpState;
  
  /**
   * Client's hostname from EHLO/HELO
   */
  clientHostname: string | null;
  
  /**
   * Whether TLS is active for this session
   */
  secure: boolean;
  
  /**
   * Authentication status
   */
  authenticated: boolean;
  
  /**
   * Authentication username if authenticated
   */
  username?: string;
  
  /**
   * Transaction envelope
   */
  envelope: ISmtpEnvelope;
  
  /**
   * When the session was created
   */
  createdAt: Date;
  
  /**
   * Last activity timestamp
   */
  lastActivity: number;
  
  /**
   * Client's IP address
   */
  remoteAddress: string;
  
  /**
   * Client's port
   */
  remotePort: number;
  
  /**
   * Additional session data
   */
  data?: Record<string, any>;
  
  /**
   * Message size if SIZE extension is used
   */
  messageSize?: number;
  
  /**
   * Server capabilities advertised to client
   */
  capabilities?: string[];
  
  /**
   * Buffer for incomplete data
   */
  dataBuffer?: string;
  
  /**
   * Flag to track if we're currently receiving DATA
   */
  receivingData?: boolean;
  
  /**
   * The raw email data being received
   */
  rawData?: string;
  
  /**
   * Greeting sent to client
   */
  greeting?: string;
  
  /**
   * Whether EHLO has been sent
   */
  ehloSent?: boolean;
  
  /**
   * Whether HELO has been sent
   */
  heloSent?: boolean;
  
  /**
   * TLS options for this session
   */
  tlsOptions?: any;
  
  /**
   * Whether TLS is being used
   */
  useTLS?: boolean;
  
  /**
   * Mail from address for this transaction
   */
  mailFrom?: string;
  
  /**
   * Recipients for this transaction
   */
  rcptTo?: string[];
  
  /**
   * Email data being received
   */
  emailData?: string;
  
  /**
   * Chunks of email data
   */
  emailDataChunks?: string[];
  
  /**
   * Timeout ID for data reception
   */
  dataTimeoutId?: NodeJS.Timeout;
  
  /**
   * Whether connection has ended
   */
  connectionEnded?: boolean;
  
  /**
   * Size of email data being received
   */
  emailDataSize?: number;
  
  /**
   * Processing mode for this session
   */
  processingMode?: string;
}

/**
 * Session manager interface
 */
export interface ISessionManager extends IDestroyable {
  /**
   * Create a new session for a socket
   */
  createSession(socket: plugins.net.Socket | plugins.tls.TLSSocket, secure?: boolean): ISmtpSession;
  
  /**
   * Get session by socket
   */
  getSession(socket: plugins.net.Socket | plugins.tls.TLSSocket): ISmtpSession | undefined;
  
  /**
   * Update session state
   */
  updateSessionState(session: ISmtpSession, newState: SmtpState): void;
  
  /**
   * Remove a session
   */
  removeSession(socket: plugins.net.Socket | plugins.tls.TLSSocket): void;
  
  /**
   * Clear all sessions
   */
  clearAllSessions(): void;
  
  /**
   * Get all active sessions
   */
  getAllSessions(): ISmtpSession[];
  
  /**
   * Get session count
   */
  getSessionCount(): number;
  
  /**
   * Update last activity for a session
   */
  updateLastActivity(socket: plugins.net.Socket | plugins.tls.TLSSocket): void;
  
  /**
   * Check for timed out sessions
   */
  checkTimeouts(timeoutMs: number): ISmtpSession[];
  
  /**
   * Update session activity timestamp
   */
  updateSessionActivity(session: ISmtpSession): void;
  
  /**
   * Replace socket in session (for TLS upgrade)
   */
  replaceSocket(oldSocket: plugins.net.Socket | plugins.tls.TLSSocket, newSocket: plugins.net.Socket | plugins.tls.TLSSocket): boolean;
}

/**
 * Connection manager interface
 */
export interface IConnectionManager extends IDestroyable {
  /**
   * Handle a new connection
   */
  handleConnection(socket: plugins.net.Socket | plugins.tls.TLSSocket, secure: boolean): Promise<void>;
  
  /**
   * Close all active connections
   */
  closeAllConnections(): void;
  
  /**
   * Get active connection count
   */
  getConnectionCount(): number;
  
  /**
   * Check if accepting new connections
   */
  canAcceptConnection(): boolean;
  
  /**
   * Handle new connection (legacy method name)
   */
  handleNewConnection(socket: plugins.net.Socket): Promise<void>;
  
  /**
   * Handle new secure connection (legacy method name)
   */
  handleNewSecureConnection(socket: plugins.tls.TLSSocket): Promise<void>;
  
  /**
   * Setup socket event handlers
   */
  setupSocketEventHandlers(socket: plugins.net.Socket | plugins.tls.TLSSocket): void;
}

/**
 * Command handler interface
 */
export interface ICommandHandler extends IDestroyable {
  /**
   * Handle an SMTP command
   */
  handleCommand(
    socket: plugins.net.Socket | plugins.tls.TLSSocket,
    command: SmtpCommand,
    args: string,
    session: ISmtpSession
  ): Promise<void>;
  
  /**
   * Get supported commands for current session state
   */
  getSupportedCommands(session: ISmtpSession): SmtpCommand[];
  
  /**
   * Process command (legacy method name)
   */
  processCommand(socket: plugins.net.Socket | plugins.tls.TLSSocket, command: string): Promise<void>;
}

/**
 * Data handler interface
 */
export interface IDataHandler extends IDestroyable {
  /**
   * Handle email data
   */
  handleData(
    socket: plugins.net.Socket | plugins.tls.TLSSocket,
    data: string,
    session: ISmtpSession
  ): Promise<void>;
  
  /**
   * Process a complete email
   */
  processEmail(
    rawData: string,
    session: ISmtpSession
  ): Promise<Email>;
  
  /**
   * Handle data received (legacy method name)
   */
  handleDataReceived(socket: plugins.net.Socket | plugins.tls.TLSSocket, data: string): Promise<void>;
  
  /**
   * Process email data (legacy method name)
   */
  processEmailData(socket: plugins.net.Socket | plugins.tls.TLSSocket, data: string): Promise<void>;
}

/**
 * TLS handler interface
 */
export interface ITlsHandler extends IDestroyable {
  /**
   * Handle STARTTLS command
   */
  handleStartTls(
    socket: plugins.net.Socket,
    session: ISmtpSession
  ): Promise<plugins.tls.TLSSocket | null>;
  
  /**
   * Check if TLS is available
   */
  isTlsAvailable(): boolean;
  
  /**
   * Get TLS options
   */
  getTlsOptions(): plugins.tls.TlsOptions;
  
  /**
   * Check if TLS is enabled
   */
  isTlsEnabled(): boolean;
}

/**
 * Security handler interface
 */
export interface ISecurityHandler extends IDestroyable {
  /**
   * Check IP reputation
   */
  checkIpReputation(socket: plugins.net.Socket | plugins.tls.TLSSocket): Promise<boolean>;
  
  /**
   * Validate email address
   */
  isValidEmail(email: string): boolean;
  
  /**
   * Authenticate user
   */
  authenticate(auth: ISmtpAuth): Promise<boolean>;
}

/**
 * SMTP server options
 */
export interface ISmtpServerOptions {
  /**
   * Port to listen on
   */
  port: number;
  
  /**
   * Hostname of the server
   */
  hostname: string;
  
  /**
   * Host to bind to (optional, defaults to 0.0.0.0)
   */
  host?: string;
  
  /**
   * Secure port for TLS connections
   */
  securePort?: number;
  
  /**
   * TLS/SSL private key (PEM format)
   */
  key?: string;
  
  /**
   * TLS/SSL certificate (PEM format)
   */
  cert?: string;
  
  /**
   * CA certificates for TLS (PEM format)
   */
  ca?: string;
  
  /**
   * Maximum size of messages in bytes
   */
  maxSize?: number;
  
  /**
   * Maximum number of concurrent connections
   */
  maxConnections?: number;
  
  /**
   * Authentication options
   */
  auth?: {
    /**
     * Whether authentication is required
     */
    required: boolean;
    
    /**
     * Allowed authentication methods
     */
    methods: ('PLAIN' | 'LOGIN' | 'OAUTH2')[];
  };
  
  /**
   * Socket timeout in milliseconds (default: 5 minutes / 300000ms)
   */
  socketTimeout?: number;
  
  /**
   * Initial connection timeout in milliseconds (default: 30 seconds / 30000ms)
   */
  connectionTimeout?: number;
  
  /**
   * Interval for checking idle sessions in milliseconds (default: 5 seconds / 5000ms)
   * For testing, can be set lower (e.g. 1000ms) to detect timeouts more quickly
   */
  cleanupInterval?: number;
  
  /**
   * Maximum number of recipients allowed per message (default: 100)
   */
  maxRecipients?: number;
  
  /**
   * Maximum message size in bytes (default: 10MB / 10485760 bytes)
   * This is advertised in the EHLO SIZE extension
   */
  size?: number;
  
  /**
   * Timeout for the DATA command in milliseconds (default: 60000ms / 1 minute)
   * This controls how long to wait for the complete email data
   */
  dataTimeout?: number;
}

/**
 * Result of SMTP transaction
 */
export interface ISmtpTransactionResult {
  /**
   * Whether the transaction was successful
   */
  success: boolean;
  
  /**
   * Error message if failed
   */
  error?: string;
  
  /**
   * Message ID if successful
   */
  messageId?: string;
  
  /**
   * Resulting email if successful
   */
  email?: Email;
}

/**
 * Interface for SMTP session events
 * These events are emitted by the session manager
 */
export interface ISessionEvents {
  created: (session: ISmtpSession, socket: plugins.net.Socket | plugins.tls.TLSSocket) => void;
  stateChanged: (session: ISmtpSession, previousState: SmtpState, newState: SmtpState) => void;
  timeout: (session: ISmtpSession, socket: plugins.net.Socket | plugins.tls.TLSSocket) => void;
  completed: (session: ISmtpSession, socket: plugins.net.Socket | plugins.tls.TLSSocket) => void;
  error: (session: ISmtpSession, error: Error) => void;
}

/**
 * SMTP Server interface
 */
export interface ISmtpServer extends IDestroyable {
  /**
   * Start the SMTP server
   */
  listen(): Promise<void>;
  
  /**
   * Stop the SMTP server
   */
  close(): Promise<void>;
  
  /**
   * Get the session manager
   */
  getSessionManager(): ISessionManager;
  
  /**
   * Get the connection manager
   */
  getConnectionManager(): IConnectionManager;
  
  /**
   * Get the command handler
   */
  getCommandHandler(): ICommandHandler;
  
  /**
   * Get the data handler
   */
  getDataHandler(): IDataHandler;
  
  /**
   * Get the TLS handler
   */
  getTlsHandler(): ITlsHandler;
  
  /**
   * Get the security handler
   */
  getSecurityHandler(): ISecurityHandler;
  
  /**
   * Get the server options
   */
  getOptions(): ISmtpServerOptions;
  
  /**
   * Get the email server reference
   */
  getEmailServer(): UnifiedEmailServer;
}

/**
 * Configuration for creating SMTP server
 */
export interface ISmtpServerConfig {
  /**
   * Email server instance
   */
  emailServer: UnifiedEmailServer;
  
  /**
   * Server options
   */
  options: ISmtpServerOptions;
  
  /**
   * Optional custom session manager
   */
  sessionManager?: ISessionManager;
  
  /**
   * Optional custom connection manager
   */
  connectionManager?: IConnectionManager;
  
  /**
   * Optional custom command handler
   */
  commandHandler?: ICommandHandler;
  
  /**
   * Optional custom data handler
   */
  dataHandler?: IDataHandler;
  
  /**
   * Optional custom TLS handler
   */
  tlsHandler?: ITlsHandler;
  
  /**
   * Optional custom security handler
   */
  securityHandler?: ISecurityHandler;
}