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

const resolveMx = promisify(dns.resolveMx);
const resolve4 = promisify(dns.resolve4);
const resolve6 = promisify(dns.resolve6);

let testServer: ITestServer;

tap.test('setup test SMTP server', async () => {
  testServer = await startTestServer({
    port: 2534,
    tlsEnabled: false,
    authRequired: false
  });
  expect(testServer).toBeTruthy();
  expect(testServer.port).toEqual(2534);
});

tap.test('CCM-08: DNS resolution and MX record lookup', async () => {
  // Test basic DNS resolution
  try {
    const ipv4Addresses = await resolve4('example.com');
    expect(ipv4Addresses).toBeArray();
    expect(ipv4Addresses.length).toBeGreaterThan(0);
    console.log('IPv4 addresses for example.com:', ipv4Addresses);
  } catch (error) {
    console.log('IPv4 resolution failed (may be expected in test environment):', error.message);
  }

  // Test IPv6 resolution
  try {
    const ipv6Addresses = await resolve6('example.com');
    expect(ipv6Addresses).toBeArray();
    console.log('IPv6 addresses for example.com:', ipv6Addresses);
  } catch (error) {
    console.log('IPv6 resolution failed (common for many domains):', error.message);
  }

  // Test MX record lookup
  try {
    const mxRecords = await resolveMx('example.com');
    expect(mxRecords).toBeArray();
    if (mxRecords.length > 0) {
      expect(mxRecords[0]).toHaveProperty('priority');
      expect(mxRecords[0]).toHaveProperty('exchange');
      console.log('MX records for example.com:', mxRecords);
    }
  } catch (error) {
    console.log('MX record lookup failed (may be expected in test environment):', error.message);
  }

  // Test local resolution (should work in test environment)
  try {
    const localhostIpv4 = await resolve4('localhost');
    expect(localhostIpv4).toContain('127.0.0.1');
  } catch (error) {
    // Fallback for environments where localhost doesn't resolve via DNS
    console.log('Localhost DNS resolution not available, using direct IP');
  }

  // Test invalid domain handling
  try {
    await resolve4('this-domain-definitely-does-not-exist-12345.com');
    expect(true).toBeFalsy(); // Should not reach here
  } catch (error) {
    expect(error.code).toMatch(/ENOTFOUND|ENODATA/);
  }

  // Test MX record priority sorting
  const mockMxRecords = [
    { priority: 20, exchange: 'mx2.example.com' },
    { priority: 10, exchange: 'mx1.example.com' },
    { priority: 30, exchange: 'mx3.example.com' }
  ];
  
  const sortedRecords = mockMxRecords.sort((a, b) => a.priority - b.priority);
  expect(sortedRecords[0].exchange).toEqual('mx1.example.com');
  expect(sortedRecords[1].exchange).toEqual('mx2.example.com');
  expect(sortedRecords[2].exchange).toEqual('mx3.example.com');
});

tap.test('CCM-08: DNS caching behavior', async () => {
  const startTime = Date.now();
  
  // First resolution (cold cache)
  try {
    await resolve4('example.com');
  } catch (error) {
    // Ignore errors, we're testing timing
  }
  
  const firstResolutionTime = Date.now() - startTime;
  
  // Second resolution (potentially cached)
  const secondStartTime = Date.now();
  try {
    await resolve4('example.com');
  } catch (error) {
    // Ignore errors, we're testing timing
  }
  
  const secondResolutionTime = Date.now() - secondStartTime;
  
  console.log(`First resolution: ${firstResolutionTime}ms, Second resolution: ${secondResolutionTime}ms`);
  
  // Note: We can't guarantee caching behavior in all environments
  // so we just log the times for manual inspection
});

tap.test('CCM-08: Multiple A record handling', async () => {
  // Test handling of domains with multiple A records
  try {
    const googleIps = await resolve4('google.com');
    if (googleIps.length > 1) {
      expect(googleIps).toBeArray();
      expect(googleIps.length).toBeGreaterThan(1);
      console.log('Multiple A records found for google.com:', googleIps);
      
      // Verify all are valid IPv4 addresses
      const ipv4Regex = /^(\d{1,3}\.){3}\d{1,3}$/;
      for (const ip of googleIps) {
        expect(ip).toMatch(ipv4Regex);
      }
    }
  } catch (error) {
    console.log('Could not resolve google.com:', error.message);
  }
});

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

export default tap.start();