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

const TEST_PORT = 30050;

let testServer: ITestServer;

tap.test('setup - start test server', async () => {
  testServer = await startTestServer({ port: TEST_PORT, hostname: 'localhost' });
  expect(testServer).toBeDefined();
});

tap.test('Special Character Handling - Comprehensive Unicode test', 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';
      socket.write('RCPT TO:<recipient@example.com>\r\n');
      dataBuffer = '';
    } else if (step === 'rcpt' && 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: Special Character Test - Unicode & Symbols ñáéíóú`,
        `Date: ${new Date().toUTCString()}`,
        `Message-ID: <special-chars-${Date.now()}@example.com>`,
        `MIME-Version: 1.0`,
        `Content-Type: text/plain; charset=utf-8`,
        `Content-Transfer-Encoding: 8bit`,
        '',
        'This email tests special character handling:',
        '',
        '=== UNICODE CHARACTERS ===',
        'Accented letters: àáâãäåæçèéêëìíîïñòóôõöøùúûüý',
        'German umlauts: äöüÄÖÜß',
        'Scandinavian: åäöÅÄÖ',
        'French: àâéèêëïîôœùûüÿç',
        'Spanish: ñáéíóúü¿¡',
        'Polish: ąćęłńóśźż',
        'Russian: абвгдеёжзийклмнопрстуфхцчшщъыьэюя',
        'Greek: αβγδεζηθικλμνξοπρστυφχψω',
        'Arabic: العربية',
        'Hebrew: עברית',
        'Chinese: 中文测试',
        'Japanese: 日本語テスト',
        'Korean: 한국어 테스트',
        'Thai: ภาษาไทย',
        '',
        '=== MATHEMATICAL SYMBOLS ===',
        'Math: ∑∏∫∆∇∂∞±×÷≠≤≥≈∝∪∩⊂⊃∈∀∃',
        'Greek letters: αβγδεζηθικλμνξοπρστυφχψω',
        'Arrows: ←→↑↓↔↕⇐⇒⇑⇓⇔⇕',
        '',
        '=== CURRENCY & SYMBOLS ===',
        'Currency: $€£¥¢₹₽₩₪₫₨₦₡₵₴₸₼₲₱',
        'Symbols: ©®™§¶†‡•…‰‱°℃℉№',
        `Punctuation: «»""''‚„‹›–—―‖‗''""‚„…‰′″‴‵‶‷‸‹›※‼‽⁇⁈⁉⁏⁐⁑⁒⁓⁔⁕⁖⁗⁘⁙⁚⁛⁜⁝⁞`,
        '',
        '=== EMOJI & SYMBOLS ===',
        'Common: ☀☁☂☃☄★☆☇☈☉☊☋☌☍☎☏☐☑☒☓☔☕☖☗☘☙☚☛☜☝☞☟☠☡☢☣☤☥☦☧☨☩☪☫☬☭☮☯☰☱☲☳☴☵☶☷',
        'Smileys: ☺☻☹☿♀♁♂♃♄♅♆♇',
        'Hearts: ♡♢♣♤♥♦♧♨♩♪♫♬♭♮♯',
        '',
        '=== SPECIAL FORMATTING ===',
        'Zero-width chars: ​‌‍‎‏',
        'Combining: e̊åa̋o̧ç',
        'Ligatures: ﬀﬁﬂﬃﬄﬅﬆ',
        'Fractions: ½⅓⅔¼¾⅛⅜⅝⅞',
        'Superscript: ⁰¹²³⁴⁵⁶⁷⁸⁹',
        'Subscript: ₀₁₂₃₄₅₆₇₈₉',
        '',
        'End of special character test.',
        '.',
        ''
      ].join('\r\n');
      
      console.log('Sending email with comprehensive Unicode characters');
      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 special characters accepted successfully');
        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('Special Character Handling - Control characters', 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';
      socket.write('RCPT TO:<recipient@example.com>\r\n');
      dataBuffer = '';
    } else if (step === 'rcpt' && 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: Control Character Test`,
        `Date: ${new Date().toUTCString()}`,
        `Message-ID: <control-chars-${Date.now()}@example.com>`,
        `MIME-Version: 1.0`,
        `Content-Type: text/plain; charset=utf-8`,
        '',
        '=== CONTROL CHARACTERS TEST ===',
        'Tab character:	(between words)',
        'Non-breaking space: word word',
        'Soft hyphen: super­cali­fragi­listic­expi­ali­docious',
        'Vertical tab: word\x0Bword',
        'Form feed: word\x0Cword',
        'Backspace: word\x08word',
        '',
        '=== LINE ENDING TESTS ===',
        'Unix LF: Line1\nLine2',
        'Windows CRLF: Line3\r\nLine4',
        'Mac CR: Line5\rLine6',
        '',
        '=== BOUNDARY CHARACTERS ===',
        'SMTP boundary test: . (dot at start)',
        'Double dots: .. (escaped in SMTP)',
        'CRLF.CRLF sequence test',
        '.',
        ''
      ].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 control characters 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('Special Character Handling - Subject header encoding', 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';
      socket.write('RCPT TO:<recipient@example.com>\r\n');
      dataBuffer = '';
    } else if (step === 'rcpt' && 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: =?UTF-8?B?8J+YgCBFbW9qaSBpbiBTdWJqZWN0IOKcqCDwn4yI?=`,
        `Subject: =?UTF-8?Q?Quoted=2DPrintable=20Subject=20=C3=A1=C3=A9=C3=AD=C3=B3=C3=BA?=`,
        `Date: ${new Date().toUTCString()}`,
        `Message-ID: <encoded-subject-${Date.now()}@example.com>`,
        '',
        'Testing encoded subject headers with special characters.',
        '.',
        ''
      ].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 encoded subject headers 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('Special Character Handling - Address headers with special chars', 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';
      socket.write('RCPT TO:<recipient@example.com>\r\n');
      dataBuffer = '';
    } else if (step === 'rcpt' && dataBuffer.includes('250')) {
      step = 'data';
      socket.write('DATA\r\n');
      dataBuffer = '';
    } else if (step === 'data' && dataBuffer.includes('354')) {
      const email = [
        `From: "José García" <jose@example.com>`,
        `To: "François Müller" <francois@example.com>, "北京用户" <beijing@example.com>`,
        `Cc: =?UTF-8?B?IkFubmEgw4XDpMO2Ig==?= <anna@example.com>`,
        `Reply-To: "Søren Ñoño" <soren@example.com>`,
        `Subject: Special names in address headers`,
        `Date: ${new Date().toUTCString()}`,
        `Message-ID: <special-addrs-${Date.now()}@example.com>`,
        '',
        'Testing special characters in email addresses and display names.',
        '.',
        ''
      ].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 special characters in addresses 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('Special Character Handling - Mixed encodings', 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';
      socket.write('RCPT TO:<recipient@example.com>\r\n');
      dataBuffer = '';
    } else if (step === 'rcpt' && dataBuffer.includes('250')) {
      step = 'data';
      socket.write('DATA\r\n');
      dataBuffer = '';
    } else if (step === 'data' && dataBuffer.includes('354')) {
      const boundary = 'mixed-encoding-boundary';
      
      const email = [
        `From: sender@example.com`,
        `To: recipient@example.com`,
        `Subject: Mixed Encoding Test`,
        `Date: ${new Date().toUTCString()}`,
        `Message-ID: <mixed-enc-${Date.now()}@example.com>`,
        `MIME-Version: 1.0`,
        `Content-Type: multipart/mixed; boundary="${boundary}"`,
        '',
        `--${boundary}`,
        `Content-Type: text/plain; charset=utf-8`,
        `Content-Transfer-Encoding: 8bit`,
        '',
        'UTF-8 part: ñáéíóú 中文 日本語',
        '',
        `--${boundary}`,
        `Content-Type: text/plain; charset=iso-8859-1`,
        `Content-Transfer-Encoding: quoted-printable`,
        '',
        'ISO-8859-1 part: =F1=E1=E9=ED=F3=FA',
        '',
        `--${boundary}`,
        `Content-Type: text/plain; charset=windows-1252`,
        '',
        'Windows-1252 part: €‚ƒ„…†‡',
        '',
        `--${boundary}`,
        `Content-Type: text/plain; charset=utf-16`,
        `Content-Transfer-Encoding: base64`,
        '',
        Buffer.from('UTF-16 text: ñoño', 'utf16le').toString('base64'),
        '',
        `--${boundary}--`,
        '.',
        ''
      ].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 mixed character encodings 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('cleanup - stop test server', async () => {
  await stopTestServer(testServer);
  expect(true).toEqual(true);
});

export default tap.start();