import { tap, expect } from '@git.zone/tstest/tapbundle';
import { startTestServer, stopTestServer, type ITestServer } from '../../helpers/server.loader.js';
import { createSmtpClient } from '../../../ts/mail/delivery/smtpclient/index.js';
import type { SmtpClient } from '../../../ts/mail/delivery/smtpclient/smtp-client.js';

let testServer: ITestServer;
let smtpClient: SmtpClient;

tap.test('setup - start SMTP server for basic connection test', async () => {
  testServer = await startTestServer({
    port: 2525,
    tlsEnabled: false,
    authRequired: false
  });
  
  expect(testServer.port).toEqual(2525);
});

tap.test('CCM-01: Basic TCP Connection - should connect to SMTP server', async () => {
  const startTime = Date.now();
  
  try {
    // Create SMTP client
    smtpClient = createSmtpClient({
      host: testServer.hostname,
      port: testServer.port,
      secure: false,
      connectionTimeout: 5000,
      debug: true
    });
    
    // Verify connection
    const isConnected = await smtpClient.verify();
    expect(isConnected).toBeTrue();
    
    const duration = Date.now() - startTime;
    console.log(`✅ Basic TCP connection established in ${duration}ms`);
    
  } catch (error) {
    const duration = Date.now() - startTime;
    console.error(`❌ Basic TCP connection failed after ${duration}ms:`, error);
    throw error;
  }
});

tap.test('CCM-01: Basic TCP Connection - should report connection status', async () => {
  // After verify(), connection is closed, so isConnected should be false
  expect(smtpClient.isConnected()).toBeFalse();
  
  const poolStatus = smtpClient.getPoolStatus();
  console.log('📊 Connection pool status:', poolStatus);
  
  // After verify(), pool should be empty
  expect(poolStatus.total).toEqual(0);
  expect(poolStatus.active).toEqual(0);
  
  // Test that connection status is correct during actual email send
  const email = new (await import('../../../ts/mail/core/classes.email.js')).Email({
    from: 'sender@example.com',
    to: ['recipient@example.com'],
    subject: 'Connection status test',
    text: 'Testing connection status'
  });
  
  // During sendMail, connection should be established
  const sendPromise = smtpClient.sendMail(email);
  
  // Check status while sending (might be too fast to catch)
  const duringStatus = smtpClient.getPoolStatus();
  console.log('📊 Pool status during send:', duringStatus);
  
  await sendPromise;
  
  // After send, connection might be pooled or closed
  const afterStatus = smtpClient.getPoolStatus();
  console.log('📊 Pool status after send:', afterStatus);
});

tap.test('CCM-01: Basic TCP Connection - should handle multiple connect/disconnect cycles', async () => {
  // Close existing connection
  await smtpClient.close();
  expect(smtpClient.isConnected()).toBeFalse();
  
  // Create new client and test reconnection
  for (let i = 0; i < 3; i++) {
    const cycleClient = createSmtpClient({
      host: testServer.hostname,
      port: testServer.port,
      secure: false,
      connectionTimeout: 5000
    });
    
    const isConnected = await cycleClient.verify();
    expect(isConnected).toBeTrue();
    
    await cycleClient.close();
    expect(cycleClient.isConnected()).toBeFalse();
    
    console.log(`✅ Connection cycle ${i + 1} completed`);
  }
});

tap.test('CCM-01: Basic TCP Connection - should fail with invalid host', async () => {
  const invalidClient = createSmtpClient({
    host: 'invalid.host.that.does.not.exist',
    port: 2525,
    secure: false,
    connectionTimeout: 3000
  });
  
  // verify() returns false on connection failure, doesn't throw
  const result = await invalidClient.verify();
  expect(result).toBeFalse();
  console.log('✅ Correctly failed to connect to invalid host');
  
  await invalidClient.close();
});

tap.test('CCM-01: Basic TCP Connection - should timeout on unresponsive port', async () => {
  const startTime = Date.now();
  
  const timeoutClient = createSmtpClient({
    host: testServer.hostname,
    port: 9999, // Port that's not listening
    secure: false,
    connectionTimeout: 2000
  });
  
  // verify() returns false on connection failure, doesn't throw
  const result = await timeoutClient.verify();
  expect(result).toBeFalse();
  
  const duration = Date.now() - startTime;
  expect(duration).toBeLessThan(3000); // Should timeout within 3 seconds
  console.log(`✅ Connection timeout working correctly (${duration}ms)`);
  
  await timeoutClient.close();
});

tap.test('cleanup - close SMTP client', async () => {
  if (smtpClient && smtpClient.isConnected()) {
    await smtpClient.close();
  }
});

tap.test('cleanup - stop SMTP server', async () => {
  await stopTestServer(testServer);
});

export default tap.start();