import { requireAuth } from '~/server/utils/auth';
import nodemailer from 'nodemailer';
import Imap from 'imap';
import { encryptCredentials, storeCredentialsInSession } from '~/server/utils/encryption';

export default defineEventHandler(async (event) => {
  // Check authentication (x-tag header OR Keycloak session)
  await requireAuth(event);

  try {
    const body = await readBody(event);
    const { email, password, imapHost, smtpHost, sessionId } = body;

    console.log('[test-connection] Testing email connection for:', email);

    if (!email || !password || !sessionId) {
      throw createError({ 
        statusCode: 400, 
        statusMessage: "Email, password, and sessionId are required" 
      });
    }

    // Use provided hosts or defaults from environment
    const imapHostToUse = imapHost || process.env.NUXT_EMAIL_IMAP_HOST || 'mail.portnimara.com';
    const smtpHostToUse = smtpHost || process.env.NUXT_EMAIL_SMTP_HOST || 'mail.portnimara.com';
    const imapPort = parseInt(process.env.NUXT_EMAIL_IMAP_PORT || '993');
    const smtpPort = parseInt(process.env.NUXT_EMAIL_SMTP_PORT || '587');

    console.log('[test-connection] Using IMAP:', imapHostToUse, ':', imapPort);
    console.log('[test-connection] Using SMTP:', smtpHostToUse, ':', smtpPort);

    // Test SMTP connection
    console.log('[test-connection] Testing SMTP connection...');
    const transporter = nodemailer.createTransport({
      host: smtpHostToUse,
      port: smtpPort,
      secure: false, // false for STARTTLS
      auth: {
        user: email,
        pass: password
      },
      tls: {
        rejectUnauthorized: false // Allow self-signed certificates
      }
    });

    try {
      await transporter.verify();
      console.log('[test-connection] SMTP connection successful');
    } catch (smtpError: any) {
      console.error('[test-connection] SMTP connection failed:', smtpError);
      throw new Error(`SMTP connection failed: ${smtpError.message || smtpError}`);
    }
    
    // Test IMAP connection
    const imapConfig = {
      user: email,
      password: password,
      host: imapHostToUse,
      port: imapPort,
      tls: true,
      tlsOptions: { 
        rejectUnauthorized: false // Allow self-signed certificates
      }
    };

    const testImapConnection = (retryCount = 0): Promise<boolean> => {
      return new Promise((resolve, reject) => {
        console.log(`[test-connection] Testing IMAP connection... (Attempt ${retryCount + 1}/3)`);
        const imap = new Imap(imapConfig);
        
        // Add a timeout to prevent hanging
        const timeout = setTimeout(() => {
          console.error('[test-connection] IMAP connection timeout');
          imap.end();
          
          // Retry on timeout if we haven't exceeded max retries
          if (retryCount < 2) {
            console.log('[test-connection] Retrying IMAP connection after timeout...');
            setTimeout(() => {
              testImapConnection(retryCount + 1)
                .then(resolve)
                .catch(reject);
            }, (retryCount + 1) * 1000); // Exponential backoff
          } else {
            reject(new Error('IMAP connection timeout after 15 seconds and 3 attempts'));
          }
        }, 15000); // 15 second timeout per attempt
        
        imap.once('ready', () => {
          console.log('[test-connection] IMAP connection successful');
          clearTimeout(timeout);
          imap.end();
          resolve(true);
        });
        
        imap.once('error', (err: Error) => {
          console.error('[test-connection] IMAP connection error:', err);
          clearTimeout(timeout);
          
          // Retry on certain errors if we haven't exceeded max retries
          const shouldRetry = retryCount < 2 && (
            err.message.includes('ECONNRESET') ||
            err.message.includes('ETIMEDOUT') ||
            err.message.includes('ENOTFOUND') ||
            err.message.includes('socket hang up')
          );
          
          if (shouldRetry) {
            console.log(`[test-connection] Retrying IMAP connection after error: ${err.message}`);
            setTimeout(() => {
              testImapConnection(retryCount + 1)
                .then(resolve)
                .catch(reject);
            }, (retryCount + 1) * 1000); // Exponential backoff
          } else {
            reject(err);
          }
        });
        
        imap.connect();
      });
    };

    try {
      await testImapConnection();
    } catch (imapError: any) {
      console.error('[test-connection] IMAP connection failed after all retries:', imapError);
      throw new Error(`IMAP connection failed: ${imapError.message || imapError}`);
    }

    // If both connections successful, encrypt and store credentials
    console.log('[test-connection] Both connections successful, storing credentials');
    const encryptedCredentials = encryptCredentials(email, password);
    storeCredentialsInSession(sessionId, encryptedCredentials);

    return { 
      success: true, 
      message: "Email connection tested successfully",
      email: email
    };
  } catch (error) {
    console.error('Email connection test failed:', error);
    if (error instanceof Error) {
      // Check for common authentication errors
      if (error.message.includes('Authentication') || error.message.includes('AUTHENTICATIONFAILED')) {
        throw createError({ 
          statusCode: 401, 
          statusMessage: "Invalid email or password" 
        });
      }
      throw createError({ 
        statusCode: 500, 
        statusMessage: `Connection failed: ${error.message}` 
      });
    } else {
      throw createError({
        statusCode: 500,
        statusMessage: "An unexpected error occurred",
      });
    }
  }
});
