import * as plugins from '../plugins.js';
import { EmailService } from './classes.emailservice.js';
import { logger } from '../logger.js';

// Import MTA classes
import { 
  MtaService, 
  Email as MtaEmail, 
  type IEmailOptions, 
  DeliveryStatus,
  type IAttachment
} from '../mta/index.js';

export class MtaConnector {
  public emailRef: EmailService;
  private mtaService: MtaService;

  constructor(emailRefArg: EmailService, mtaService?: MtaService) {
    this.emailRef = emailRefArg;
    this.mtaService = mtaService || this.emailRef.mtaService;
  }

  /**
   * Send an email using the MTA service
   * @param smartmail The email to send
   * @param toAddresses Recipients (comma-separated or array)
   * @param options Additional options
   */
  public async sendEmail(
    smartmail: plugins.smartmail.Smartmail<>,
    toAddresses: string | string[],
    options: any = {}
  ): Promise<string> {
    try {
      // Process recipients
      const toArray = Array.isArray(toAddresses) 
        ? toAddresses 
        : toAddresses.split(',').map(addr => addr.trim());
      
      // Map SmartMail attachments to MTA attachments
      const attachments: IAttachment[] = smartmail.attachments.map(attachment => {
        return {
          filename: attachment.parsedPath.base,
          content: Buffer.from(attachment.contentBuffer),
          contentType: (attachment as any)?.getContentType?.() || 'application/octet-stream' // TODO: revisit after smartfile has been updated
        };
      });

      // Create MTA Email
      const mtaEmail = new MtaEmail({
        from: smartmail.options.from,
        to: toArray,
        subject: smartmail.getSubject(),
        text: smartmail.getBody(false), // Plain text version
        html: smartmail.getBody(true),  // HTML version
        attachments
      });

      // Send using MTA
      const emailId = await this.mtaService.send(mtaEmail);
      
      logger.log('info', `Email sent via MTA to ${toAddresses}`, {
        eventType: 'sentEmail',
        provider: 'mta',
        emailId,
        to: toAddresses
      });

      return emailId;
    } catch (error) {
      logger.log('error', `Failed to send email via MTA: ${error.message}`, {
        eventType: 'emailError',
        provider: 'mta',
        error: error.message
      });
      throw error;
    }
  }

  /**
   * Retrieve and process an incoming email
   * For MTA, this would handle an email already received by the SMTP server
   * @param emailData The raw email data or identifier
   */
  public async receiveEmail(emailData: string): Promise<plugins.smartmail.Smartmail<>> {
    try {
      // In a real implementation, this would retrieve an email from the MTA storage
      // For now, we can use a simplified approach:
      
      // Parse the email (assuming emailData is a raw email or a file path)
      const parsedEmail = await plugins.mailparser.simpleParser(emailData);
      
      // Create a Smartmail from the parsed email
      const smartmail = new plugins.smartmail.Smartmail({
        from: parsedEmail.from?.text || '',
        subject: parsedEmail.subject || '',
        body: parsedEmail.html || parsedEmail.text || '',
        creationObjectRef: {
          From: parsedEmail.from?.text || '',
          To: parsedEmail.to?.text || '',
          Subject: parsedEmail.subject || ''
        }
      });

      // Add attachments if present
      if (parsedEmail.attachments && parsedEmail.attachments.length > 0) {
        for (const attachment of parsedEmail.attachments) {
          smartmail.addAttachment(
            await plugins.smartfile.SmartFile.fromBuffer(
              attachment.filename || 'attachment',
              attachment.content
            )
          );
        }
      }

      return smartmail;
    } catch (error) {
      logger.log('error', `Failed to receive email via MTA: ${error.message}`, {
        eventType: 'emailError',
        provider: 'mta',
        error: error.message
      });
      throw error;
    }
  }

  /**
   * Check the status of a sent email
   * @param emailId The email ID to check
   */
  public async checkEmailStatus(emailId: string): Promise<{
    status: string;
    details?: any;
  }> {
    try {
      const status = this.mtaService.getEmailStatus(emailId);
      
      if (!status) {
        return {
          status: 'unknown',
          details: { message: 'Email not found' }
        };
      }

      return {
        status: status.status,
        details: {
          attempts: status.attempts,
          lastAttempt: status.lastAttempt,
          nextAttempt: status.nextAttempt,
          error: status.error?.message
        }
      };
    } catch (error) {
      logger.log('error', `Failed to check email status: ${error.message}`, {
        eventType: 'emailError',
        provider: 'mta',
        emailId,
        error: error.message
      });
      
      return {
        status: 'error',
        details: { message: error.message }
      };
    }
  }
}