import { tap, expect } from '@git.zone/tstest/tapbundle';
import * as net from 'net';
import { startTestServer, stopTestServer } from '../../helpers/server.loader.ts'
import type { ITestServer } from '../../helpers/server.loader.js';
const TEST_PORT = 2525;

let testServer: ITestServer;

tap.test('setup - start test server', async () => {
  testServer = await startTestServer({ port: TEST_PORT });
  await new Promise(resolve => setTimeout(resolve, 1000));
});

tap.test('DSN - Extension advertised in EHLO', async (tools) => {
  const done = tools.defer();
  
  const socket = net.createConnection({
    host: 'localhost',
    port: TEST_PORT,
    timeout: 30000
  });
  
  let dataBuffer = '';
  
  socket.on('data', (data) => {
    dataBuffer += data.toString();
    console.log('Server response:', data.toString());
    
    if (dataBuffer.includes('220 ') && !dataBuffer.includes('EHLO')) {
      socket.write('EHLO testclient\r\n');
      dataBuffer = '';
    } else if (dataBuffer.includes('250')) {
      // Check if DSN extension is advertised
      const dsnSupported = dataBuffer.toLowerCase().includes('dsn');
      console.log('DSN extension advertised:', dsnSupported);
      
      // Parse extensions
      const lines = dataBuffer.split('\r\n');
      const extensions = lines
        .filter(line => line.startsWith('250-') || (line.startsWith('250 ') && lines.indexOf(line) > 0))
        .map(line => line.substring(4).split(' ')[0].toUpperCase());
      
      console.log('Server extensions:', extensions);
      
      socket.write('QUIT\r\n');
      socket.end();
      done.resolve();
    }
  });
  
  socket.on('error', (err) => {
    console.error('Socket error:', err);
    done.reject(err);
  });
  
  await done.promise;
});

tap.test('DSN - Success notification request', async (tools) => {
  const done = tools.defer();
  
  const socket = net.createConnection({
    host: 'localhost',
    port: TEST_PORT,
    timeout: 30000
  });
  
  let dataBuffer = '';
  let step = 'greeting';
  let completed = false;
  
  socket.on('data', (data) => {
    dataBuffer += data.toString();
    console.log('Server response:', data.toString());
    
    if (step === 'greeting' && dataBuffer.includes('220 ')) {
      step = 'ehlo';
      socket.write('EHLO testclient\r\n');
      dataBuffer = '';
    } else if (step === 'ehlo' && dataBuffer.includes('250')) {
      step = 'mail';
      // MAIL FROM with DSN parameters
      const envId = `dsn-success-${Date.now()}`;
      socket.write(`MAIL FROM:<sender@example.com> RET=FULL ENVID=${envId}\r\n`);
      dataBuffer = '';
    } else if (step === 'mail') {
      const accepted = dataBuffer.includes('250');
      const notSupported = dataBuffer.includes('501') || dataBuffer.includes('555');
      
      console.log(`MAIL FROM with DSN: ${accepted ? 'accepted' : notSupported ? 'not supported' : 'error'}`);
      
      if (accepted || notSupported) {
        step = 'rcpt';
        // Plain MAIL FROM if DSN not supported
        if (notSupported) {
          socket.write('MAIL FROM:<sender@example.com>\r\n');
          dataBuffer = '';
        } else {
          // RCPT TO with NOTIFY parameter
          socket.write('RCPT TO:<recipient@example.com> NOTIFY=SUCCESS\r\n');
          dataBuffer = '';
        }
      }
    } else if (step === 'rcpt') {
      const accepted = dataBuffer.includes('250');
      const notSupported = dataBuffer.includes('501') || dataBuffer.includes('555');
      
      if (notSupported) {
        // DSN not supported, try plain RCPT TO
        socket.write('RCPT TO:<recipient@example.com>\r\n');
        step = 'rcpt_plain';
        dataBuffer = '';
      } else if (accepted) {
        step = 'data';
        socket.write('DATA\r\n');
        dataBuffer = '';
      }
    } else if (step === 'rcpt_plain' && dataBuffer.includes('250')) {
      step = 'data';
      socket.write('DATA\r\n');
      dataBuffer = '';
    } else if (step === 'data' && dataBuffer.includes('354')) {
      const email = [
        `From: sender@example.com`,
        `To: recipient@example.com`,
        `Subject: DSN Test - Success Notification`,
        `Date: ${new Date().toUTCString()}`,
        `Message-ID: <dsn-success-${Date.now()}@example.com>`,
        '',
        'This email tests DSN success notification.',
        'The server should send a success DSN if supported.',
        '.',
        ''
      ].join('\r\n');
      
      socket.write(email);
      step = 'sent';
      dataBuffer = '';
    } else if (step === 'sent' && dataBuffer.includes('250 ') && dataBuffer.includes('message queued')) {
      if (!completed) {
        completed = true;
        console.log('Email with DSN success request accepted');
        expect(true).toEqual(true);
        
        socket.write('QUIT\r\n');
        socket.end();
        done.resolve();
      }
    }
  });
  
  socket.on('error', (err) => {
    console.error('Socket error:', err);
    done.reject(err);
  });
  
  await done.promise;
});

tap.test('DSN - Multiple notification types', async (tools) => {
  const done = tools.defer();
  
  const socket = net.createConnection({
    host: 'localhost',
    port: TEST_PORT,
    timeout: 30000
  });
  
  let dataBuffer = '';
  let step = 'greeting';
  let completed = false;
  
  socket.on('data', (data) => {
    dataBuffer += data.toString();
    console.log('Server response:', data.toString());
    
    if (step === 'greeting' && dataBuffer.includes('220 ')) {
      step = 'ehlo';
      socket.write('EHLO testclient\r\n');
      dataBuffer = '';
    } else if (step === 'ehlo' && dataBuffer.includes('250')) {
      step = 'mail';
      socket.write('MAIL FROM:<sender@example.com>\r\n');
      dataBuffer = '';
    } else if (step === 'mail' && dataBuffer.includes('250')) {
      step = 'rcpt';
      // Request multiple notification types
      socket.write('RCPT TO:<recipient@example.com> NOTIFY=SUCCESS,FAILURE,DELAY\r\n');
      dataBuffer = '';
    } else if (step === 'rcpt') {
      const accepted = dataBuffer.includes('250');
      const notSupported = dataBuffer.includes('501') || dataBuffer.includes('555');
      
      console.log(`Multiple NOTIFY types: ${accepted ? 'accepted' : notSupported ? 'not supported' : 'error'}`);
      
      if (notSupported) {
        // Try plain RCPT TO
        socket.write('RCPT TO:<recipient@example.com>\r\n');
        step = 'rcpt_plain';
        dataBuffer = '';
      } else if (accepted) {
        step = 'data';
        socket.write('DATA\r\n');
        dataBuffer = '';
      }
    } else if (step === 'rcpt_plain' && dataBuffer.includes('250')) {
      step = 'data';
      socket.write('DATA\r\n');
      dataBuffer = '';
    } else if (step === 'data' && dataBuffer.includes('354')) {
      const email = [
        `From: sender@example.com`,
        `To: recipient@example.com`,
        `Subject: DSN Test - Multiple Notifications`,
        `Date: ${new Date().toUTCString()}`,
        `Message-ID: <dsn-multi-${Date.now()}@example.com>`,
        '',
        'Testing multiple DSN notification types.',
        '.',
        ''
      ].join('\r\n');
      
      socket.write(email);
      step = 'sent';
      dataBuffer = '';
    } else if (step === 'sent' && dataBuffer.includes('250 ') && dataBuffer.includes('message queued')) {
      if (!completed) {
        completed = true;
        console.log('Email with multiple DSN types accepted');
        expect(true).toEqual(true);
        
        socket.write('QUIT\r\n');
        socket.end();
        done.resolve();
      }
    }
  });
  
  socket.on('error', (err) => {
    console.error('Socket error:', err);
    done.reject(err);
  });
  
  await done.promise;
});

tap.test('DSN - Never notify', async (tools) => {
  const done = tools.defer();
  
  const socket = net.createConnection({
    host: 'localhost',
    port: TEST_PORT,
    timeout: 30000
  });
  
  let dataBuffer = '';
  let step = 'greeting';
  let completed = false;
  
  socket.on('data', (data) => {
    dataBuffer += data.toString();
    console.log('Server response:', data.toString());
    
    if (step === 'greeting' && dataBuffer.includes('220 ')) {
      step = 'ehlo';
      socket.write('EHLO testclient\r\n');
      dataBuffer = '';
    } else if (step === 'ehlo' && dataBuffer.includes('250')) {
      step = 'mail';
      socket.write('MAIL FROM:<sender@example.com>\r\n');
      dataBuffer = '';
    } else if (step === 'mail' && dataBuffer.includes('250')) {
      step = 'rcpt';
      // Request no notifications
      socket.write('RCPT TO:<recipient@example.com> NOTIFY=NEVER\r\n');
      dataBuffer = '';
    } else if (step === 'rcpt') {
      const accepted = dataBuffer.includes('250');
      const notSupported = dataBuffer.includes('501') || dataBuffer.includes('555');
      
      console.log(`NOTIFY=NEVER: ${accepted ? 'accepted' : notSupported ? 'not supported' : 'error'}`);
      expect(accepted || notSupported).toEqual(true);
      
      if (notSupported) {
        socket.write('RCPT TO:<recipient@example.com>\r\n');
        step = 'rcpt_plain';
        dataBuffer = '';
      } else if (accepted) {
        step = 'data';
        socket.write('DATA\r\n');
        dataBuffer = '';
      }
    } else if (step === 'rcpt_plain' && dataBuffer.includes('250')) {
      step = 'data';
      socket.write('DATA\r\n');
      dataBuffer = '';
    } else if (step === 'data' && dataBuffer.includes('354')) {
      const email = [
        `From: sender@example.com`,
        `To: recipient@example.com`,
        `Subject: DSN Test - Never Notify`,
        `Date: ${new Date().toUTCString()}`,
        `Message-ID: <dsn-never-${Date.now()}@example.com>`,
        '',
        'This email should not generate any DSN.',
        '.',
        ''
      ].join('\r\n');
      
      socket.write(email);
      step = 'sent';
      dataBuffer = '';
    } else if (step === 'sent' && dataBuffer.includes('250 ') && dataBuffer.includes('message queued')) {
      if (!completed) {
        completed = true;
        console.log('Email with NOTIFY=NEVER accepted');
        expect(true).toEqual(true);
        
        socket.write('QUIT\r\n');
        socket.end();
        done.resolve();
      }
    }
  });
  
  socket.on('error', (err) => {
    console.error('Socket error:', err);
    done.reject(err);
  });
  
  await done.promise;
});

tap.test('DSN - Original recipient tracking', async (tools) => {
  const done = tools.defer();
  
  const socket = net.createConnection({
    host: 'localhost',
    port: TEST_PORT,
    timeout: 30000
  });
  
  let dataBuffer = '';
  let step = 'greeting';
  let completed = false;
  
  socket.on('data', (data) => {
    dataBuffer += data.toString();
    console.log('Server response:', data.toString());
    
    if (step === 'greeting' && dataBuffer.includes('220 ')) {
      step = 'ehlo';
      socket.write('EHLO testclient\r\n');
      dataBuffer = '';
    } else if (step === 'ehlo' && dataBuffer.includes('250')) {
      step = 'mail';
      socket.write('MAIL FROM:<sender@example.com>\r\n');
      dataBuffer = '';
    } else if (step === 'mail' && dataBuffer.includes('250')) {
      step = 'rcpt';
      // Include original recipient for tracking
      socket.write('RCPT TO:<recipient@example.com> NOTIFY=FAILURE ORCPT=rfc822;original@example.com\r\n');
      dataBuffer = '';
    } else if (step === 'rcpt') {
      const accepted = dataBuffer.includes('250');
      const notSupported = dataBuffer.includes('501') || dataBuffer.includes('555');
      
      console.log(`ORCPT parameter: ${accepted ? 'accepted' : notSupported ? 'not supported' : 'error'}`);
      
      if (notSupported) {
        socket.write('RCPT TO:<recipient@example.com>\r\n');
        step = 'rcpt_plain';
        dataBuffer = '';
      } else if (accepted) {
        step = 'data';
        socket.write('DATA\r\n');
        dataBuffer = '';
      }
    } else if (step === 'rcpt_plain' && dataBuffer.includes('250')) {
      step = 'data';
      socket.write('DATA\r\n');
      dataBuffer = '';
    } else if (step === 'data' && dataBuffer.includes('354')) {
      const email = [
        `From: sender@example.com`,
        `To: recipient@example.com`,
        `Subject: DSN Test - Original Recipient`,
        `Date: ${new Date().toUTCString()}`,
        `Message-ID: <dsn-orcpt-${Date.now()}@example.com>`,
        '',
        'This email tests ORCPT parameter for tracking.',
        '.',
        ''
      ].join('\r\n');
      
      socket.write(email);
      step = 'sent';
      dataBuffer = '';
    } else if (step === 'sent' && dataBuffer.includes('250 ') && dataBuffer.includes('message queued')) {
      if (!completed) {
        completed = true;
        console.log('Email with ORCPT tracking accepted');
        expect(true).toEqual(true);
        
        socket.write('QUIT\r\n');
        socket.end();
        done.resolve();
      }
    }
  });
  
  socket.on('error', (err) => {
    console.error('Socket error:', err);
    done.reject(err);
  });
  
  await done.promise;
});

tap.test('DSN - Return parameter handling', async (tools) => {
  const done = tools.defer();
  
  const socket = net.createConnection({
    host: 'localhost',
    port: TEST_PORT,
    timeout: 30000
  });
  
  let dataBuffer = '';
  let step = 'greeting';
  
  socket.on('data', (data) => {
    dataBuffer += data.toString();
    console.log('Server response:', data.toString());
    
    if (step === 'greeting' && dataBuffer.includes('220 ')) {
      step = 'ehlo';
      socket.write('EHLO testclient\r\n');
      dataBuffer = '';
    } else if (step === 'ehlo' && dataBuffer.includes('250')) {
      step = 'mail_hdrs';
      // Test RET=HDRS
      socket.write('MAIL FROM:<sender@example.com> RET=HDRS\r\n');
      dataBuffer = '';
    } else if (step === 'mail_hdrs') {
      const accepted = dataBuffer.includes('250');
      const notSupported = dataBuffer.includes('501') || dataBuffer.includes('555');
      
      console.log(`RET=HDRS: ${accepted ? 'accepted' : notSupported ? 'not supported' : 'error'}`);
      
      if (accepted || notSupported) {
        // Reset and test RET=FULL
        socket.write('RSET\r\n');
        step = 'reset';
        dataBuffer = '';
      }
    } else if (step === 'reset' && dataBuffer.includes('250')) {
      step = 'mail_full';
      socket.write('MAIL FROM:<sender@example.com> RET=FULL\r\n');
      dataBuffer = '';
    } else if (step === 'mail_full') {
      const accepted = dataBuffer.includes('250');
      const notSupported = dataBuffer.includes('501') || dataBuffer.includes('555');
      
      console.log(`RET=FULL: ${accepted ? 'accepted' : notSupported ? 'not supported' : 'error'}`);
      expect(accepted || notSupported).toEqual(true);
      
      socket.write('QUIT\r\n');
      socket.end();
      done.resolve();
    }
  });
  
  socket.on('error', (err) => {
    console.error('Socket error:', err);
    done.reject(err);
  });
  
  await done.promise;
});

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

export default tap.start();