import * as plugins from '../plugins.js';
import * as paths from '../paths.js';
import { MtaConnector } from './classes.connector.mta.js';
import { RuleManager } from './classes.rulemanager.js';
import { ApiManager } from './classes.apimanager.js';
import { TemplateManager } from './classes.templatemanager.js';
import { EmailValidator } from './classes.emailvalidator.js';
import { logger } from '../logger.js';
import type { SzPlatformService } from '../platformservice.js';

// Import MTA service
import { MtaService, type IMtaConfig } from '../mta/index.js';

export interface IEmailConstructorOptions {
  useMta?: boolean;
  mtaConfig?: IMtaConfig;
  templateConfig?: {
    from?: string;
    replyTo?: string;
    footerHtml?: string;
    footerText?: string;
  };
  loadTemplatesFromDir?: boolean;
}

/**
 * Email service with support for both Mailgun and local MTA
 */
export class EmailService {
  public platformServiceRef: SzPlatformService;

  // typedrouter
  public typedrouter = new plugins.typedrequest.TypedRouter();

  // connectors
  public mtaConnector: MtaConnector;
  public qenv = new plugins.qenv.Qenv('./', '.nogit/');

  // MTA service
  public mtaService: MtaService;

  // services
  public apiManager: ApiManager;
  public ruleManager: RuleManager;
  public templateManager: TemplateManager;
  public emailValidator: EmailValidator;

  // configuration
  private config: IEmailConstructorOptions;

  constructor(platformServiceRefArg: SzPlatformService, options: IEmailConstructorOptions = {}) {
    this.platformServiceRef = platformServiceRefArg;
    this.platformServiceRef.typedrouter.addTypedRouter(this.typedrouter);
    
    // Set default options
    this.config = {
      useMta: options.useMta ?? true,
      mtaConfig: options.mtaConfig || {},
      templateConfig: options.templateConfig || {},
      loadTemplatesFromDir: options.loadTemplatesFromDir ?? true
    };

    // Initialize validator
    this.emailValidator = new EmailValidator();

    // Initialize template manager
    this.templateManager = new TemplateManager(this.config.templateConfig);

    if (this.config.useMta) {
      // Initialize MTA service
      this.mtaService = new MtaService(platformServiceRefArg, this.config.mtaConfig);
      // Initialize MTA connector
      this.mtaConnector = new MtaConnector(this);
    }

    // Initialize API manager and rule manager
    this.apiManager = new ApiManager(this);
    this.ruleManager = new RuleManager(this);

    // Set up MTA SMTP server webhook if using MTA
    if (this.config.useMta) {
      // The MTA SMTP server will handle incoming emails directly
      // through its SMTP protocol. No additional webhook needed.
    }
  }

  /**
   * Start the email service
   */
  public async start() {
    // Initialize rule manager
    await this.ruleManager.init();
    
    // Load email templates if configured
    if (this.config.loadTemplatesFromDir) {
      try {
        await this.templateManager.loadTemplatesFromDirectory(paths.emailTemplatesDir);
      } catch (error) {
        logger.log('error', `Failed to load email templates: ${error.message}`);
      }
    }
    
    // Start MTA service if enabled
    if (this.config.useMta && this.mtaService) {
      await this.mtaService.start();
      logger.log('success', 'Started MTA service');
    }
    
    logger.log('success', `Started email service`);
  }

  /**
   * Stop the email service
   */
  public async stop() {
    // Stop MTA service if it's running
    if (this.config.useMta && this.mtaService) {
      await this.mtaService.stop();
      logger.log('info', 'Stopped MTA service');
    }
    
    logger.log('info', 'Stopped email service');
  }

  /**
   * Send an email using the configured provider (Mailgun or MTA)
   * @param email The email to send
   * @param to Recipient(s)
   * @param options Additional options
   */
  public async sendEmail(
    email: plugins.smartmail.Smartmail<any>,
    to: string | string[],
    options: any = {}
  ): Promise<string> {
    // Determine which connector to use
    if (this.config.useMta && this.mtaConnector) {
      return this.mtaConnector.sendEmail(email, to, options);
    } else {
      throw new Error('No email provider configured');
    }
  }
  
  /**
   * Send an email using a template
   * @param templateId The template ID
   * @param to Recipient email(s)
   * @param context The template context data
   * @param options Additional options
   */
  public async sendTemplateEmail(
    templateId: string,
    to: string | string[],
    context: any = {},
    options: any = {}
  ): Promise<string> {
    try {
      // Get email from template
      const smartmail = await this.templateManager.prepareEmail(templateId, context);
      
      // Send the email
      return this.sendEmail(smartmail, to, options);
    } catch (error) {
      logger.log('error', `Failed to send template email: ${error.message}`, {
        templateId,
        to,
        error: error.message
      });
      throw error;
    }
  }
  
  /**
   * Validate an email address
   * @param email The email address to validate
   * @param options Validation options
   * @returns Validation result
   */
  public async validateEmail(
    email: string,
    options: {
      checkMx?: boolean;
      checkDisposable?: boolean;
      checkRole?: boolean;
    } = {}
  ): Promise<any> {
    return this.emailValidator.validate(email, options);
  }

  /**
   * Get email service statistics
   */
  public getStats() {
    const stats: any = {
      activeProviders: []
    };

    if (this.config.useMta) {
      stats.activeProviders.push('mta');
      stats.mta = this.mtaService.getStats();
    }

    return stats;
  }
}