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';
import { Email } from '../../../ts/mail/core/classes.email.js';

let testServer: ITestServer;

tap.test('setup test SMTP server', async () => {
  testServer = await startTestServer({
    port: 2547,
    tlsEnabled: false,
    authRequired: false
  });
  expect(testServer).toBeTruthy();
  expect(testServer.port).toBeGreaterThan(0);
});

tap.test('CCMD-07: Parse successful send responses', async () => {
  const smtpClient = createSmtpClient({
    host: testServer.hostname,
    port: testServer.port,
    secure: false,
    connectionTimeout: 5000,
    debug: true
  });

  const email = new Email({
    from: 'sender@example.com',
    to: 'recipient@example.com',
    subject: 'Response Test',
    text: 'Testing response parsing'
  });

  const result = await smtpClient.sendMail(email);
  
  // Verify successful response parsing
  expect(result.success).toBeTrue();
  expect(result.response).toBeTruthy();
  expect(result.messageId).toBeTruthy();
  
  // The response should contain queue ID
  expect(result.response).toInclude('queued');
  console.log(`✅ Parsed success response: ${result.response}`);
  
  await smtpClient.close();
});

tap.test('CCMD-07: Parse multiple recipient responses', async () => {
  const smtpClient = createSmtpClient({
    host: testServer.hostname,
    port: testServer.port,
    secure: false,
    connectionTimeout: 5000,
    debug: true
  });

  // Send to multiple recipients
  const email = new Email({
    from: 'sender@example.com',
    to: ['recipient1@example.com', 'recipient2@example.com', 'recipient3@example.com'],
    subject: 'Multi-recipient Test',
    text: 'Testing multiple recipient response parsing'
  });

  const result = await smtpClient.sendMail(email);
  
  // Verify parsing of multiple recipient responses
  expect(result.success).toBeTrue();
  expect(result.acceptedRecipients.length).toEqual(3);
  expect(result.rejectedRecipients.length).toEqual(0);
  
  console.log(`✅ Accepted ${result.acceptedRecipients.length} recipients`);
  console.log('Multiple RCPT TO responses parsed correctly');
  
  await smtpClient.close();
});

tap.test('CCMD-07: Parse error response codes', async () => {
  const smtpClient = createSmtpClient({
    host: testServer.hostname,
    port: testServer.port,
    secure: false,
    connectionTimeout: 5000,
    debug: true
  });

  // Test with invalid email to trigger error
  try {
    const email = new Email({
      from: '',  // Empty from should trigger error
      to: 'recipient@example.com',
      subject: 'Error Test',
      text: 'Testing error response'
    });
    
    await smtpClient.sendMail(email);
    expect(false).toBeTrue(); // Should not reach here
  } catch (error: any) {
    expect(error).toBeInstanceOf(Error);
    expect(error.message).toBeTruthy();
    console.log(`✅ Error response parsed: ${error.message}`);
  }
  
  await smtpClient.close();
});

tap.test('CCMD-07: Parse enhanced status codes', async () => {
  const smtpClient = createSmtpClient({
    host: testServer.hostname,
    port: testServer.port,
    secure: false,
    connectionTimeout: 5000,
    debug: true
  });

  // Normal send - server advertises ENHANCEDSTATUSCODES
  const email = new Email({
    from: 'sender@example.com',
    to: 'recipient@example.com',
    subject: 'Enhanced Status Test',
    text: 'Testing enhanced status code parsing'
  });

  const result = await smtpClient.sendMail(email);
  
  expect(result.success).toBeTrue();
  // Server logs show it advertises ENHANCEDSTATUSCODES in EHLO
  console.log('✅ Server advertises ENHANCEDSTATUSCODES capability');
  console.log('Enhanced status codes are parsed automatically');
  
  await smtpClient.close();
});

tap.test('CCMD-07: Parse response timing and delays', async () => {
  const smtpClient = createSmtpClient({
    host: testServer.hostname,
    port: testServer.port,
    secure: false,
    connectionTimeout: 5000,
    debug: true
  });

  // Measure response time
  const email = new Email({
    from: 'sender@example.com',
    to: 'recipient@example.com',
    subject: 'Timing Test',
    text: 'Testing response timing'
  });

  const startTime = Date.now();
  const result = await smtpClient.sendMail(email);
  const elapsed = Date.now() - startTime;
  
  expect(result.success).toBeTrue();
  expect(elapsed).toBeGreaterThan(0);
  expect(elapsed).toBeLessThan(5000); // Should complete within 5 seconds
  
  console.log(`✅ Response received and parsed in ${elapsed}ms`);
  console.log('Client handles response timing appropriately');
  
  await smtpClient.close();
});

tap.test('CCMD-07: Parse envelope information', async () => {
  const smtpClient = createSmtpClient({
    host: testServer.hostname,
    port: testServer.port,
    secure: false,
    connectionTimeout: 5000,
    debug: true
  });

  const from = 'sender@example.com';
  const to = ['recipient1@example.com', 'recipient2@example.com'];
  const cc = ['cc@example.com'];
  const bcc = ['bcc@example.com'];
  
  const email = new Email({
    from,
    to,
    cc,
    bcc,
    subject: 'Envelope Test',
    text: 'Testing envelope parsing'
  });

  const result = await smtpClient.sendMail(email);
  
  expect(result.success).toBeTrue();
  expect(result.envelope).toBeTruthy();
  expect(result.envelope.from).toEqual(from);
  expect(result.envelope.to).toBeArray();
  
  // Envelope should include all recipients (to, cc, bcc)
  const totalRecipients = to.length + cc.length + bcc.length;
  expect(result.envelope.to.length).toEqual(totalRecipients);
  
  console.log(`✅ Envelope parsed with ${result.envelope.to.length} recipients`);
  console.log('Envelope information correctly extracted from responses');
  
  await smtpClient.close();
});

tap.test('CCMD-07: Parse connection state responses', async () => {
  const smtpClient = createSmtpClient({
    host: testServer.hostname,
    port: testServer.port,
    secure: false,
    connectionTimeout: 5000,
    debug: true
  });

  // Test verify() which checks connection state
  const isConnected = await smtpClient.verify();
  expect(isConnected).toBeTrue();
  
  console.log('✅ Connection verified through greeting and EHLO responses');
  
  // Send email to test active connection
  const email = new Email({
    from: 'sender@example.com',
    to: 'recipient@example.com',
    subject: 'State Test',
    text: 'Testing connection state'
  });

  const result = await smtpClient.sendMail(email);
  expect(result.success).toBeTrue();
  
  console.log('✅ Connection state maintained throughout session');
  console.log('Response parsing handles connection state correctly');
  
  await smtpClient.close();
});

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

export default tap.start();