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: 2568,
    tlsEnabled: false,
    authRequired: true
  });
  expect(testServer).toBeTruthy();
  expect(testServer.port).toBeGreaterThan(0);
});

tap.test('CSEC-08: Multiple authentication methods', async () => {
  const smtpClient = createTestSmtpClient({
    host: testServer.hostname,
    port: testServer.port,
    secure: false,
    auth: {
      user: 'testuser',
      pass: 'testpass'
    }
  });

  const email = new Email({
    from: 'sender@example.com',
    to: ['recipient@example.com'],
    subject: 'Multi-auth test',
    text: 'Testing multiple authentication methods'
  });

  const result = await smtpClient.sendMail(email);
  console.log('Authentication successful');
  expect(result.success).toBeTruthy();

  await smtpClient.close();
});

tap.test('CSEC-08: OAuth2 fallback to password auth', async () => {
  // Test with OAuth2 token (will fail and fallback)
  const oauthClient = createTestSmtpClient({
    host: testServer.hostname,
    port: testServer.port,
    secure: false,
    auth: {
      oauth2: {
        user: 'user@example.com',
        clientId: 'test-client',
        clientSecret: 'test-secret',
        refreshToken: 'refresh-token',
        accessToken: 'invalid-token'
      }
    }
  });

  const email = new Email({
    from: 'sender@example.com',
    to: ['recipient@example.com'],
    subject: 'OAuth2 fallback test',
    text: 'Testing OAuth2 authentication fallback'
  });

  try {
    await oauthClient.sendMail(email);
    console.log('OAuth2 authentication attempted');
  } catch (error) {
    console.log(`OAuth2 failed as expected: ${error.message}`);
  }

  await oauthClient.close();

  // Test fallback to password auth
  const fallbackClient = createTestSmtpClient({
    host: testServer.hostname,
    port: testServer.port,
    secure: false,
    auth: {
      user: 'testuser',
      pass: 'testpass'
    }
  });
  
  const result = await fallbackClient.sendMail(email);
  console.log('Fallback authentication successful');
  expect(result.success).toBeTruthy();

  await fallbackClient.close();
});

tap.test('CSEC-08: Auth method preference', async () => {
  // Test with specific auth method preference
  const smtpClient = createTestSmtpClient({
    host: testServer.hostname,
    port: testServer.port,
    secure: false,
    auth: {
      user: 'testuser',
      pass: 'testpass',
      method: 'PLAIN'  // Prefer PLAIN auth
    }
  });

  const email = new Email({
    from: 'sender@example.com',
    to: ['recipient@example.com'],
    subject: 'Auth preference test',
    text: 'Testing authentication method preference'
  });

  const result = await smtpClient.sendMail(email);
  console.log('Authentication with preferred method successful');
  expect(result.success).toBeTruthy();

  await smtpClient.close();
});

tap.test('CSEC-08: Secure auth requirements', async () => {
  // Test authentication behavior with security requirements
  const smtpClient = createTestSmtpClient({
    host: testServer.hostname,
    port: testServer.port,
    secure: false,
    auth: {
      user: 'testuser',
      pass: 'testpass'
    },
    requireTLS: false  // Allow auth over plain connection for test
  });

  const email = new Email({
    from: 'sender@example.com',
    to: ['recipient@example.com'],
    subject: 'Secure auth test',
    text: 'Testing secure authentication requirements'
  });

  const result = await smtpClient.sendMail(email);
  console.log('Authentication completed');
  expect(result.success).toBeTruthy();

  await smtpClient.close();
});

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

tap.start();