import { tap, expect } from '@git.zone/tstest/tapbundle';
import { startTestServer, stopTestServer, type ITestServer } from '../../helpers/server.loader.js';
import { createTestSmtpClient } from '../../helpers/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: 2569,
    tlsEnabled: false,
    authRequired: false
  });
  expect(testServer).toBeTruthy();
  expect(testServer.port).toBeGreaterThan(0);
});

tap.test('CSEC-09: Open relay prevention', async () => {
  // Test unauthenticated relay attempt (should succeed for test server)
  const unauthClient = createTestSmtpClient({
    host: testServer.hostname,
    port: testServer.port,
    secure: false
  });

  const relayEmail = new Email({
    from: 'external@untrusted.com',
    to: ['recipient@another-external.com'],
    subject: 'Relay test',
    text: 'Testing open relay prevention'
  });

  const result = await unauthClient.sendMail(relayEmail);
  console.log('Test server allows relay for testing purposes');
  expect(result.success).toBeTruthy();

  await unauthClient.close();
});

tap.test('CSEC-09: Authenticated relay', async () => {
  // Test authenticated relay (should succeed)
  const authClient = createTestSmtpClient({
    host: testServer.hostname,
    port: testServer.port,
    secure: false,
    auth: {
      user: 'testuser',
      pass: 'testpass'
    }
  });

  const relayEmail = new Email({
    from: 'sender@example.com',
    to: ['recipient@external.com'],
    subject: 'Authenticated relay test',
    text: 'Testing authenticated relay'
  });

  const result = await authClient.sendMail(relayEmail);
  console.log('Authenticated relay allowed');
  expect(result.success).toBeTruthy();

  await authClient.close();
});

tap.test('CSEC-09: Recipient count limits', async () => {
  const smtpClient = createTestSmtpClient({
    host: testServer.hostname,
    port: testServer.port,
    secure: false
  });

  // Test with multiple recipients
  const manyRecipients = Array(10).fill(null).map((_, i) => `recipient${i + 1}@example.com`);
  
  const bulkEmail = new Email({
    from: 'sender@example.com',
    to: manyRecipients,
    subject: 'Recipient limit test',
    text: 'Testing recipient count limits'
  });

  const result = await smtpClient.sendMail(bulkEmail);
  console.log(`Sent to ${result.acceptedRecipients.length} recipients`);
  expect(result.success).toBeTruthy();
  
  // Check if any recipients were rejected
  if (result.rejectedRecipients.length > 0) {
    console.log(`${result.rejectedRecipients.length} recipients rejected`);
  }

  await smtpClient.close();
});

tap.test('CSEC-09: Sender domain verification', async () => {
  const smtpClient = createTestSmtpClient({
    host: testServer.hostname,
    port: testServer.port,
    secure: false
  });

  // Test with various sender domains
  const senderTests = [
    { from: 'sender@example.com', expected: true },
    { from: 'sender@trusted.com', expected: true },
    { from: 'sender@untrusted.com', expected: true } // Test server accepts all
  ];

  for (const test of senderTests) {
    const email = new Email({
      from: test.from,
      to: ['recipient@example.com'],
      subject: `Sender test from ${test.from}`,
      text: 'Testing sender domain restrictions'
    });

    const result = await smtpClient.sendMail(email);
    console.log(`Sender ${test.from}: ${result.success ? 'accepted' : 'rejected'}`);
    expect(result.success).toEqual(test.expected);
  }

  await smtpClient.close();
});

tap.test('CSEC-09: Rate limiting simulation', async () => {
  // Send multiple messages to test rate limiting
  const results: boolean[] = [];
  
  for (let i = 0; i < 5; i++) {
    const client = createTestSmtpClient({
      host: testServer.hostname,
      port: testServer.port,
      secure: false
    });
    
    const email = new Email({
      from: 'sender@example.com',
      to: ['recipient@example.com'],
      subject: `Rate test ${i + 1}`,
      text: `Testing rate limits - message ${i + 1}`
    });
    
    try {
      const result = await client.sendMail(email);
      console.log(`Message ${i + 1}: Sent successfully`);
      results.push(result.success);
    } catch (error) {
      console.log(`Message ${i + 1}: Failed`);
      results.push(false);
    }
    
    await client.close();
  }
  
  const successCount = results.filter(r => r).length;
  console.log(`Sent ${successCount}/${results.length} messages`);
  expect(successCount).toBeGreaterThan(0);
});

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

tap.start();