import { tap, expect } from '@push.rocks/tapbundle';
import * as plugins from '../ts/plugins.js';
import { 
  DcRouter,
  type IDcRouterOptions,
  type IEmailConfig,
  type EmailProcessingMode,
  type IDomainRule
} from '../ts/classes.dcrouter.js';

tap.test('DcRouter class - basic functionality', async () => {
  // Create a simple DcRouter instance
  const options: IDcRouterOptions = {
    tls: {
      contactEmail: 'test@example.com'
    }
  };

  const router = new DcRouter(options);
  expect(router).toBeTruthy();
  expect(router instanceof DcRouter).toEqual(true);
  expect(router.options.tls.contactEmail).toEqual('test@example.com');
});

tap.test('DcRouter class - SmartProxy configuration', async () => {
  // Create SmartProxy configuration
  const smartProxyConfig: plugins.smartproxy.ISmartProxyOptions = {
    fromPort: 443,
    toPort: 8080,
    targetIP: '10.0.0.10',
    sniEnabled: true,
    acme: {
      port: 80,
      enabled: true,
      autoRenew: true,
      useProduction: false,
      renewThresholdDays: 30,
      accountEmail: 'admin@example.com'
    },
    globalPortRanges: [
      { from: 80, to: 80 },
      { from: 443, to: 443 }
    ],
    domainConfigs: [
      {
        domains: ['example.com', 'www.example.com'],
        allowedIPs: ['0.0.0.0/0'],
        targetIPs: ['10.0.0.10'],
        portRanges: [
          { from: 80, to: 80 },
          { from: 443, to: 443 }
        ]
      }
    ]
  };

  const options: IDcRouterOptions = {
    smartProxyConfig,
    tls: {
      contactEmail: 'test@example.com'
    }
  };

  const router = new DcRouter(options);
  expect(router.options.smartProxyConfig).toBeTruthy();
  expect(router.options.smartProxyConfig.domainConfigs.length).toEqual(1);
  expect(router.options.smartProxyConfig.domainConfigs[0].domains[0]).toEqual('example.com');
});

tap.test('DcRouter class - Email configuration', async () => {
  // Create consolidated email configuration
  const emailConfig: IEmailConfig = {
    ports: [25, 587, 465],
    hostname: 'mail.example.com',
    maxMessageSize: 50 * 1024 * 1024, // 50MB
    
    defaultMode: 'forward' as EmailProcessingMode,
    defaultServer: 'fallback-mail.example.com',
    defaultPort: 25,
    defaultTls: true,
    
    domainRules: [
      {
        pattern: '*@example.com',
        mode: 'forward' as EmailProcessingMode,
        target: {
          server: 'mail1.example.com',
          port: 25,
          useTls: true
        }
      },
      {
        pattern: '*@example.org',
        mode: 'mta' as EmailProcessingMode,
        mtaOptions: {
          domain: 'example.org',
          allowLocalDelivery: true
        }
      }
    ]
  };

  const options: IDcRouterOptions = {
    emailConfig,
    tls: {
      contactEmail: 'test@example.com'
    }
  };

  const router = new DcRouter(options);
  expect(router.options.emailConfig).toBeTruthy();
  expect(router.options.emailConfig.ports.length).toEqual(3);
  expect(router.options.emailConfig.domainRules.length).toEqual(2);
  expect(router.options.emailConfig.domainRules[0].pattern).toEqual('*@example.com');
  expect(router.options.emailConfig.domainRules[1].pattern).toEqual('*@example.org');
});

tap.test('DcRouter class - Domain pattern matching', async () => {
  const router = new DcRouter({});
  
  // Use the internal method for testing if accessible
  // This requires knowledge of the implementation, so it's a bit brittle
  if (typeof router['isDomainMatch'] === 'function') {
    // Test exact match
    expect(router['isDomainMatch']('example.com', 'example.com')).toEqual(true);
    expect(router['isDomainMatch']('example.com', 'example.org')).toEqual(false);
    
    // Test wildcard match
    expect(router['isDomainMatch']('sub.example.com', '*.example.com')).toEqual(true);
    expect(router['isDomainMatch']('sub.sub.example.com', '*.example.com')).toEqual(true);
    expect(router['isDomainMatch']('example.com', '*.example.com')).toEqual(false);
    expect(router['isDomainMatch']('sub.example.org', '*.example.com')).toEqual(false);
  }
});

// Final clean-up test
tap.test('clean up after tests', async () => {
  // No-op - just to make sure everything is cleaned up properly
});

tap.test('stop', async () => {
  await tap.stopForcefully();
});

// Export a function to run all tests
export default tap.start();