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;
let smtpClient: SmtpClient;

tap.test('setup - start SMTP server for MIME tests', async () => {
  testServer = await startTestServer({
    port: 2571,
    tlsEnabled: false,
    authRequired: false,
    size: 25 * 1024 * 1024 // 25MB for attachment tests
  });
  
  expect(testServer.port).toEqual(2571);
});

tap.test('setup - create SMTP client', async () => {
  smtpClient = createSmtpClient({
    host: testServer.hostname,
    port: testServer.port,
    secure: false,
    connectionTimeout: 5000,
    socketTimeout: 60000, // Longer timeout for large attachments
    debug: true
  });
  
  const isConnected = await smtpClient.verify();
  expect(isConnected).toBeTrue();
});

tap.test('CEP-02: MIME Multipart - should send multipart/alternative (text + HTML)', async () => {
  const email = new Email({
    from: 'sender@example.com',
    to: 'recipient@example.com',
    subject: 'Multipart Alternative Test',
    text: 'This is the plain text version of the email.',
    html: '<html><body><h1>HTML Version</h1><p>This is the <strong>HTML version</strong> of the email.</p></body></html>'
  });
  
  const result = await smtpClient.sendMail(email);
  
  expect(result.success).toBeTrue();
  console.log('✅ Multipart/alternative email sent successfully');
});

tap.test('CEP-02: MIME Multipart - should send multipart/mixed with attachments', async () => {
  const textAttachment = Buffer.from('This is a text file attachment content.');
  const csvData = 'Name,Email,Score\nJohn Doe,john@example.com,95\nJane Smith,jane@example.com,87';
  
  const email = new Email({
    from: 'sender@example.com',
    to: 'recipient@example.com',
    subject: 'Multipart Mixed with Attachments',
    text: 'This email contains attachments.',
    html: '<p>This email contains <strong>attachments</strong>.</p>',
    attachments: [
      {
        filename: 'document.txt',
        content: textAttachment,
        contentType: 'text/plain'
      },
      {
        filename: 'data.csv',
        content: Buffer.from(csvData),
        contentType: 'text/csv'
      }
    ]
  });
  
  const result = await smtpClient.sendMail(email);
  
  expect(result.success).toBeTrue();
  console.log('✅ Multipart/mixed with attachments sent successfully');
});

tap.test('CEP-02: MIME Multipart - should handle inline images', async () => {
  // Create a small test image (1x1 red pixel PNG)
  const redPixelPng = Buffer.from(
    'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==',
    'base64'
  );
  
  const email = new Email({
    from: 'sender@example.com',
    to: 'recipient@example.com',
    subject: 'Inline Image Test',
    text: 'This email contains an inline image.',
    html: '<p>Here is an inline image: <img src="cid:red-pixel" alt="Red Pixel"></p>',
    attachments: [
      {
        filename: 'red-pixel.png',
        content: redPixelPng,
        contentType: 'image/png',
        contentId: 'red-pixel' // Content-ID for inline reference
      }
    ]
  });
  
  const result = await smtpClient.sendMail(email);
  
  expect(result.success).toBeTrue();
  console.log('✅ Email with inline image sent successfully');
});

tap.test('CEP-02: MIME Multipart - should handle multiple attachment types', async () => {
  const attachments = [
    {
      filename: 'text.txt',
      content: Buffer.from('Plain text file'),
      contentType: 'text/plain'
    },
    {
      filename: 'data.json',
      content: Buffer.from(JSON.stringify({ test: 'data', value: 123 })),
      contentType: 'application/json'
    },
    {
      filename: 'binary.bin',
      content: Buffer.from([0x00, 0x01, 0x02, 0x03, 0xFF, 0xFE, 0xFD]),
      contentType: 'application/octet-stream'
    },
    {
      filename: 'document.pdf',
      content: Buffer.from('%PDF-1.4\n%fake pdf content for testing'),
      contentType: 'application/pdf'
    }
  ];
  
  const email = new Email({
    from: 'sender@example.com',
    to: 'recipient@example.com',
    subject: 'Multiple Attachment Types',
    text: 'Testing various attachment types',
    attachments
  });
  
  const result = await smtpClient.sendMail(email);
  
  expect(result.success).toBeTrue();
  console.log('✅ Multiple attachment types handled correctly');
});

tap.test('CEP-02: MIME Multipart - should encode binary attachments with base64', async () => {
  // Create binary data with all byte values
  const binaryData = Buffer.alloc(256);
  for (let i = 0; i < 256; i++) {
    binaryData[i] = i;
  }
  
  const email = new Email({
    from: 'sender@example.com',
    to: 'recipient@example.com',
    subject: 'Binary Attachment Encoding Test',
    text: 'This email contains binary data that must be base64 encoded',
    attachments: [
      {
        filename: 'binary-data.bin',
        content: binaryData,
        contentType: 'application/octet-stream',
        encoding: 'base64' // Explicitly specify encoding
      }
    ]
  });
  
  const result = await smtpClient.sendMail(email);
  
  expect(result.success).toBeTrue();
  console.log('✅ Binary attachment base64 encoded correctly');
});

tap.test('CEP-02: MIME Multipart - should handle large attachments', async () => {
  // Create a 5MB attachment
  const largeData = Buffer.alloc(5 * 1024 * 1024);
  for (let i = 0; i < largeData.length; i++) {
    largeData[i] = i % 256;
  }
  
  const email = new Email({
    from: 'sender@example.com',
    to: 'recipient@example.com',
    subject: 'Large Attachment Test',
    text: 'This email contains a large attachment',
    attachments: [
      {
        filename: 'large-file.dat',
        content: largeData,
        contentType: 'application/octet-stream'
      }
    ]
  });
  
  const startTime = Date.now();
  const result = await smtpClient.sendMail(email);
  const duration = Date.now() - startTime;
  
  expect(result.success).toBeTrue();
  console.log(`✅ Large attachment (5MB) sent in ${duration}ms`);
});

tap.test('CEP-02: MIME Multipart - should handle nested multipart structures', async () => {
  const email = new Email({
    from: 'sender@example.com',
    to: 'recipient@example.com',
    subject: 'Complex Multipart Structure',
    text: 'Plain text version',
    html: '<p>HTML version with <img src="cid:logo" alt="Logo"></p>',
    attachments: [
      {
        filename: 'logo.png',
        content: Buffer.from('fake png data'),
        contentType: 'image/png',
        contentId: 'logo' // Inline image
      },
      {
        filename: 'attachment.txt',
        content: Buffer.from('Regular attachment'),
        contentType: 'text/plain'
      }
    ]
  });
  
  const result = await smtpClient.sendMail(email);
  
  expect(result.success).toBeTrue();
  console.log('✅ Nested multipart structure (mixed + related + alternative) handled');
});

tap.test('CEP-02: MIME Multipart - should handle attachment filenames with special characters', async () => {
  const email = new Email({
    from: 'sender@example.com',
    to: 'recipient@example.com',
    subject: 'Special Filename Test',
    text: 'Testing attachments with special filenames',
    attachments: [
      {
        filename: 'file with spaces.txt',
        content: Buffer.from('Content 1'),
        contentType: 'text/plain'
      },
      {
        filename: 'файл.txt', // Cyrillic
        content: Buffer.from('Content 2'),
        contentType: 'text/plain'
      },
      {
        filename: '文件.txt', // Chinese
        content: Buffer.from('Content 3'),
        contentType: 'text/plain'
      }
    ]
  });
  
  const result = await smtpClient.sendMail(email);
  
  expect(result.success).toBeTrue();
  console.log('✅ Special characters in filenames handled correctly');
});

tap.test('CEP-02: MIME Multipart - should handle empty attachments', async () => {
  const email = new Email({
    from: 'sender@example.com',
    to: 'recipient@example.com',
    subject: 'Empty Attachment Test',
    text: 'This email has an empty attachment',
    attachments: [
      {
        filename: 'empty.txt',
        content: Buffer.from(''), // Empty content
        contentType: 'text/plain'
      }
    ]
  });
  
  const result = await smtpClient.sendMail(email);
  
  expect(result.success).toBeTrue();
  console.log('✅ Empty attachment handled correctly');
});

tap.test('CEP-02: MIME Multipart - should respect content-type parameters', async () => {
  const email = new Email({
    from: 'sender@example.com',
    to: 'recipient@example.com',
    subject: 'Content-Type Parameters Test',
    text: 'Testing content-type with charset',
    html: '<p>HTML with specific charset</p>',
    attachments: [
      {
        filename: 'utf8-text.txt',
        content: Buffer.from('UTF-8 text: 你好世界'),
        contentType: 'text/plain; charset=utf-8'
      },
      {
        filename: 'data.xml',
        content: Buffer.from('<?xml version="1.0" encoding="UTF-8"?><root>Test</root>'),
        contentType: 'application/xml; charset=utf-8'
      }
    ]
  });
  
  const result = await smtpClient.sendMail(email);
  
  expect(result.success).toBeTrue();
  console.log('✅ Content-type parameters preserved correctly');
});

tap.test('cleanup - close SMTP client', async () => {
  if (smtpClient && smtpClient.isConnected()) {
    await smtpClient.close();
  }
});

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

export default tap.start();