import nodemailer from 'nodemailer';
import handlebars from 'handlebars';
import { readFileSync } from 'fs';
import { join, dirname } from 'path';
import { fileURLToPath } from 'url';
import type { SMTPConfig } from '~/utils/types';

// ES modules compatibility for __dirname
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

export interface EmailData {
  to: string;
  subject: string;
  html: string;
  text?: string;
}

export interface WelcomeEmailData {
  firstName: string;
  lastName: string;
  verificationLink: string;
  memberId: string;
  registrationDate?: string;
  logoUrl?: string;
  email?: string;
}

export interface VerificationEmailData {
  firstName: string;
  verificationLink: string;
  logoUrl?: string;
}

export interface PasswordResetEmailData {
  firstName: string;
  resetLink: string;
  logoUrl?: string;
}

export interface DuesReminderEmailData {
  firstName: string;
  lastName: string;
  amount: number;
  dueDate: string;
  iban?: string;
  accountHolder?: string;
  logoUrl?: string;
}

export class EmailService {
  private transporter: nodemailer.Transporter | null = null;
  private templates: Map<string, handlebars.TemplateDelegate> = new Map();

  constructor(private config: SMTPConfig) {
    this.initializeTransporter();
    this.preloadTemplates();
  }

  /**
   * Initialize the nodemailer transporter
   */
  private initializeTransporter(): void {
    if (!this.config.host || !this.config.port) {
      console.warn('[EmailService] SMTP configuration incomplete, emails will not be sent');
      return;
    }

    try {
      // Determine security settings based on port
      let useSecure = this.config.secure;
      let requireTLS = false;
      
      // Auto-configure based on standard ports if not explicitly set
      if (this.config.port === 587) {
        // Port 587 typically uses STARTTLS
        useSecure = false;
        requireTLS = true;
      } else if (this.config.port === 465) {
        // Port 465 typically uses SSL/TLS
        useSecure = true;
        requireTLS = false;
      } else if (this.config.port === 25) {
        // Port 25 typically unencrypted (not recommended)
        useSecure = false;
        requireTLS = false;
      }

      // Build transporter options
      const transporterOptions: any = {
        host: this.config.host,
        port: this.config.port,
        secure: useSecure,
        // Increased timeout settings to handle slow servers
        connectionTimeout: 60000, // 60 seconds
        greetingTimeout: 60000,
        socketTimeout: 60000,
        // Pool configuration for better connection management
        pool: false,
        maxConnections: 1,
        // Debug logging (can be enabled for troubleshooting)
        logger: false,
        debug: false
      };

      // Add requireTLS if needed (for STARTTLS)
      if (requireTLS && !useSecure) {
        transporterOptions.requireTLS = true;
        transporterOptions.opportunisticTLS = true;
      }

      // Configure TLS options
      transporterOptions.tls = {
        rejectUnauthorized: false, // Accept self-signed certificates
        // Allow various TLS versions for compatibility
        minVersion: 'TLSv1',
        // Don't specify ciphers to allow auto-negotiation
      };

      // Add authentication only if credentials are provided
      if (this.config.username && this.config.password) {
        transporterOptions.auth = {
          user: this.config.username,
          pass: this.config.password,
          // Try different auth methods for compatibility
          type: 'login' // Can be 'oauth2', 'login', or omitted for auto-detection
        };
        
        // For some servers, disabling STARTTLS can help
        if (this.config.port === 587) {
          transporterOptions.ignoreTLS = false;
          transporterOptions.secure = false;
          transporterOptions.requireTLS = true;
        }
      }

      this.transporter = nodemailer.createTransport(transporterOptions);

      console.log('[EmailService] ✅ SMTP transporter initialized with options:', {
        host: this.config.host,
        port: this.config.port,
        secure: transporterOptions.secure,
        requireTLS: transporterOptions.requireTLS,
        auth: !!transporterOptions.auth
      });
    } catch (error) {
      console.error('[EmailService] ❌ Failed to initialize SMTP transporter:', error);
    }
  }

  /**
   * Preload and compile email templates
   */
  private preloadTemplates(): void {
    const templateNames = ['welcome', 'welcome-board', 'verification', 'password-reset', 'dues-reminder', 'dues-due-soon', 'dues-overdue', 'test'];
    
    templateNames.forEach(templateName => {
      try {
        // Try multiple possible paths for template files
        const possiblePaths = [
          join(process.cwd(), 'server/templates', `${templateName}.hbs`),
          join(process.cwd(), '.output/server/templates', `${templateName}.hbs`),
          join(__dirname, '..', 'templates', `${templateName}.hbs`),
          join(__dirname, '..', '..', 'server/templates', `${templateName}.hbs`),
          // Docker container path
          `/app/server/templates/${templateName}.hbs`
        ];
        
        let templateContent: string | null = null;
        let usedPath = '';
        
        for (const templatePath of possiblePaths) {
          try {
            templateContent = readFileSync(templatePath, 'utf-8');
            usedPath = templatePath;
            break;
          } catch (pathError) {
            // Continue to next path
          }
        }
        
        if (!templateContent) {
          console.warn(`[EmailService] ⚠️ Template '${templateName}' not found in any of the expected paths`);
          return;
        }
        
        const compiledTemplate = handlebars.compile(templateContent);
        this.templates.set(templateName, compiledTemplate);
        console.log(`[EmailService] ✅ Template '${templateName}' loaded from: ${usedPath}`);
      } catch (error) {
        console.warn(`[EmailService] ⚠️ Template '${templateName}' failed to compile:`, error);
      }
    });
  }

  /**
   * Get a compiled template by name
   */
  private getTemplate(templateName: string): handlebars.TemplateDelegate | null {
    return this.templates.get(templateName) || null;
  }

  /**
   * Send a generic email
   */
  private async sendEmail(emailData: EmailData): Promise<void> {
    if (!this.transporter) {
      throw new Error('SMTP transporter not initialized');
    }

    const mailOptions = {
      from: `${this.config.fromName} <${this.config.fromAddress}>`,
      to: emailData.to,
      subject: emailData.subject,
      html: emailData.html,
      text: emailData.text || undefined,
      // Explicitly set content type to ensure HTML rendering
      headers: {
        'Content-Type': 'text/html; charset=utf-8',
        'MIME-Version': '1.0'
      }
    };

    try {
      const info = await this.transporter.sendMail(mailOptions);
      console.log(`[EmailService] ✅ Email sent successfully to ${emailData.to}:`, info.messageId);
    } catch (error) {
      console.error(`[EmailService] ❌ Failed to send email to ${emailData.to}:`, error);
      throw error;
    }
  }

  /**
   * Send welcome/verification email to new members
   */
  async sendWelcomeEmail(to: string, data: WelcomeEmailData): Promise<void> {
    const template = this.getTemplate('welcome');
    if (!template) {
      console.error('[EmailService] ❌ Welcome email template not found! Available templates:', Array.from(this.templates.keys()));
      throw new Error('Welcome email template not found');
    }

    const config = useRuntimeConfig();
    const templateData = {
      ...data,
      logoUrl: data.logoUrl || 'https://portal.monacousa.org/MONACOUSA-Flags_376x376.png',
      baseUrl: config.public.domain || 'https://portal.monacousa.org',
      email: data.email || to
    };

    console.log('[EmailService] Template data:', templateData);
    
    const html = template(templateData);
    console.log('[EmailService] Generated HTML length:', html.length);
    console.log('[EmailService] HTML preview (first 200 chars):', html.substring(0, 200));
    
    await this.sendEmail({
      to,
      subject: 'Welcome to MonacoUSA - Please Verify Your Email',
      html
    });

    console.log(`[EmailService] ✅ Welcome email sent to ${to}`);
  }

  /**
   * Send welcome/verification email to new board members
   */
  async sendWelcomeBoardEmail(to: string, data: WelcomeEmailData): Promise<void> {
    const template = this.getTemplate('welcome-board');
    if (!template) {
      console.error('[EmailService] ❌ Board welcome email template not found! Available templates:', Array.from(this.templates.keys()));
      throw new Error('Board welcome email template not found');
    }

    const config = useRuntimeConfig();
    const templateData = {
      ...data,
      logoUrl: data.logoUrl || 'https://portal.monacousa.org/MONACOUSA-Flags_376x376.png',
      baseUrl: config.public.domain || 'https://portal.monacousa.org',
      email: data.email || to
    };

    console.log('[EmailService] Board template data:', templateData);
    
    const html = template(templateData);
    console.log('[EmailService] Generated board HTML length:', html.length);
    console.log('[EmailService] Board HTML preview (first 200 chars):', html.substring(0, 200));
    
    await this.sendEmail({
      to,
      subject: 'Welcome to the MonacoUSA Board Portal - Please Verify Your Email',
      html
    });

    console.log(`[EmailService] ✅ Board welcome email sent to ${to}`);
  }

  /**
   * Send email verification email
   */
  async sendVerificationEmail(to: string, data: VerificationEmailData): Promise<void> {
    const template = this.getTemplate('verification');
    if (!template) {
      throw new Error('Verification email template not found');
    }

    const templateData = {
      ...data,
      logoUrl: data.logoUrl || 'https://portal.monacousa.org/MONACOUSA-Flags_376x376.png'
    };

    const html = template(templateData);
    
    await this.sendEmail({
      to,
      subject: 'Verify Your Email - MonacoUSA Portal',
      html
    });

    console.log(`[EmailService] ✅ Verification email sent to ${to}`);
  }

  /**
   * Send password reset email
   */
  async sendPasswordResetEmail(to: string, data: PasswordResetEmailData): Promise<void> {
    const template = this.getTemplate('password-reset');
    if (!template) {
      throw new Error('Password reset email template not found');
    }

    const templateData = {
      ...data,
      logoUrl: data.logoUrl || 'https://portal.monacousa.org/MONACOUSA-Flags_376x376.png'
    };

    const html = template(templateData);
    
    await this.sendEmail({
      to,
      subject: 'Reset Your Password - MonacoUSA Portal',
      html
    });

    console.log(`[EmailService] ✅ Password reset email sent to ${to}`);
  }

  /**
   * Send membership dues reminder email
   */
  async sendDuesReminderEmail(to: string, data: DuesReminderEmailData): Promise<void> {
    const template = this.getTemplate('dues-reminder');
    if (!template) {
      throw new Error('Dues reminder email template not found');
    }

    const templateData = {
      ...data,
      logoUrl: data.logoUrl || 'https://portal.monacousa.org/MONACOUSA-Flags_376x376.png'
    };

    const html = template(templateData);
    
    await this.sendEmail({
      to,
      subject: `MonacoUSA Membership Dues Reminder - €${data.amount} Due`,
      html
    });

    console.log(`[EmailService] ✅ Dues reminder email sent to ${to}`);
  }

  /**
   * Send test email to verify SMTP configuration
   */
  async sendTestEmail(to: string): Promise<void> {
    const template = this.getTemplate('test');
    
    const templateData = {
      testTime: new Date().toISOString(),
      logoUrl: 'https://portal.monacousa.org/MONACOUSA-Flags_376x376.png',
      smtpHost: this.config.host,
      fromAddress: this.config.fromAddress
    };

    let html: string;
    if (template) {
      html = template(templateData);
    } else {
      // Fallback HTML if template is not available
      html = `
        <!DOCTYPE html>
        <html>
        <head><title>SMTP Test Email</title></head>
        <body style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; padding: 20px;">
          <div style="text-align: center; margin-bottom: 30px;">
            <img src="${templateData.logoUrl}" alt="MonacoUSA" style="width: 100px;">
            <h1 style="color: #a31515;">SMTP Test Email</h1>
          </div>
          
          <p>This is a test email from the MonacoUSA Portal email system.</p>
          
          <div style="background: #f5f5f5; padding: 15px; border-radius: 8px; margin: 20px 0;">
            <p><strong>Test Details:</strong></p>
            <ul>
              <li>Sent at: ${templateData.testTime}</li>
              <li>SMTP Host: ${templateData.smtpHost}</li>
              <li>From Address: ${templateData.fromAddress}</li>
            </ul>
          </div>
          
          <p>If you received this email, your SMTP configuration is working correctly!</p>
          
          <hr style="margin: 30px 0;">
          <p style="color: #666; font-size: 14px; text-align: center;">
            MonacoUSA Portal Email System
          </p>
        </body>
        </html>
      `;
    }
    
    await this.sendEmail({
      to,
      subject: 'SMTP Configuration Test - MonacoUSA Portal',
      html,
      text: `This is a test email from MonacoUSA Portal. Sent at: ${templateData.testTime}`
    });

    console.log(`[EmailService] ✅ Test email sent to ${to}`);
  }

  /**
   * Verify SMTP connection
   */
  async verifyConnection(): Promise<boolean> {
    if (!this.transporter) {
      throw new Error('SMTP transporter not initialized');
    }

    try {
      await this.transporter.verify();
      console.log('[EmailService] ✅ SMTP connection verified');
      return true;
    } catch (error) {
      console.error('[EmailService] ❌ SMTP connection verification failed:', error);
      return false;
    }
  }

  /**
   * Update SMTP configuration and reinitialize transporter
   */
  updateConfig(newConfig: SMTPConfig): void {
    this.config = newConfig;
    this.initializeTransporter();
  }

  /**
   * Close the transporter connection
   */
  close(): void {
    if (this.transporter) {
      this.transporter.close();
      this.transporter = null;
      console.log('[EmailService] SMTP connection closed');
    }
  }
}

// Singleton instance for reuse across the application
let emailServiceInstance: EmailService | null = null;

/**
 * Get or create EmailService instance with current SMTP config
 */
export async function getEmailService(): Promise<EmailService> {
  const { getSMTPConfig, reloadAdminConfig } = await import('./admin-config');
  
  // Force reload configuration to ensure we have the latest settings
  try {
    await reloadAdminConfig();
  } catch (error) {
    console.warn('[EmailService] Failed to reload admin config, using cached version:', error);
  }
  
  const config = getSMTPConfig();
  
  console.log('[EmailService] Current SMTP config:', {
    host: config.host || 'not set',
    port: config.port || 'not set',
    secure: config.secure,
    hasUsername: !!config.username,
    hasPassword: !!config.password,
    fromAddress: config.fromAddress || 'not set',
    fromName: config.fromName || 'not set'
  });
  
  if (!emailServiceInstance) {
    emailServiceInstance = new EmailService(config);
  } else {
    // Always update config in case it changed
    emailServiceInstance.updateConfig(config);
  }
  
  return emailServiceInstance;
}

/**
 * Create a new EmailService instance with custom config
 */
export function createEmailService(config: SMTPConfig): EmailService {
  return new EmailService(config);
}

/**
 * Generic send email function for custom templates
 */
export async function sendEmail(options: {
  to: string;
  subject: string;
  template: string;
  data: any;
}): Promise<void> {
  try {
    const emailService = await getEmailService();
    
    // Get the template
    const templateFunction = (emailService as any).getTemplate(options.template);
    if (!templateFunction) {
      throw new Error(`Email template '${options.template}' not found`);
    }
    
    // Add common template data
    const templateData = {
      ...options.data,
      logoUrl: options.data.logoUrl || 'https://portal.monacousa.org/MONACOUSA-Flags_376x376.png',
      baseUrl: process.env.NUXT_PUBLIC_DOMAIN || 'https://portal.monacousa.org'
    };
    
    // Compile template with data
    const html = templateFunction(templateData);
    
    // Send email using the private sendEmail method
    await (emailService as any).sendEmail({
      to: options.to,
      subject: options.subject,
      html
    });
    
    console.log(`[sendEmail] ✅ Email sent successfully to ${options.to} using template '${options.template}'`);
  } catch (error) {
    console.error(`[sendEmail] ❌ Failed to send email to ${options.to}:`, error);
    throw error;
  }
}
