import { tap, expect } from '@push.rocks/tapbundle';
import * as plugins from '../ts/plugins.js';
import type { IForwardConfig, TForwardingType } from '../ts/forwarding/config/forwarding-types.js';

// First, import the components directly to avoid issues with compiled modules
import { ForwardingHandlerFactory } from '../ts/forwarding/factory/forwarding-factory.js';
import { createDomainConfig } from '../ts/forwarding/config/domain-config.js';
import { DomainManager } from '../ts/forwarding/config/domain-manager.js';
import { httpOnly, tlsTerminateToHttp, tlsTerminateToHttps, httpsPassthrough } from '../ts/forwarding/config/forwarding-types.js';

const helpers = {
  httpOnly,
  tlsTerminateToHttp,
  tlsTerminateToHttps,
  httpsPassthrough
};

tap.test('ForwardingHandlerFactory - apply defaults based on type', async () => {
      // HTTP-only defaults
      const httpConfig: IForwardConfig = {
        type: 'http-only',
        target: { host: 'localhost', port: 3000 }
      };
      
      const expandedHttpConfig = ForwardingHandlerFactory.applyDefaults(httpConfig);
      expect(expandedHttpConfig.http?.enabled).toEqual(true);
      
      // HTTPS-passthrough defaults
      const passthroughConfig: IForwardConfig = {
        type: 'https-passthrough',
        target: { host: 'localhost', port: 443 }
      };
      
      const expandedPassthroughConfig = ForwardingHandlerFactory.applyDefaults(passthroughConfig);
      expect(expandedPassthroughConfig.https?.forwardSni).toEqual(true);
      expect(expandedPassthroughConfig.http?.enabled).toEqual(false);
      
      // HTTPS-terminate-to-http defaults
      const terminateToHttpConfig: IForwardConfig = {
        type: 'https-terminate-to-http',
        target: { host: 'localhost', port: 3000 }
      };
      
      const expandedTerminateToHttpConfig = ForwardingHandlerFactory.applyDefaults(terminateToHttpConfig);
      expect(expandedTerminateToHttpConfig.http?.enabled).toEqual(true);
      expect(expandedTerminateToHttpConfig.http?.redirectToHttps).toEqual(true);
      expect(expandedTerminateToHttpConfig.acme?.enabled).toEqual(true);
      expect(expandedTerminateToHttpConfig.acme?.maintenance).toEqual(true);
      
      // HTTPS-terminate-to-https defaults
      const terminateToHttpsConfig: IForwardConfig = {
        type: 'https-terminate-to-https',
        target: { host: 'localhost', port: 8443 }
      };
      
      const expandedTerminateToHttpsConfig = ForwardingHandlerFactory.applyDefaults(terminateToHttpsConfig);
      expect(expandedTerminateToHttpsConfig.http?.enabled).toEqual(true);
      expect(expandedTerminateToHttpsConfig.http?.redirectToHttps).toEqual(true);
      expect(expandedTerminateToHttpsConfig.acme?.enabled).toEqual(true);
      expect(expandedTerminateToHttpsConfig.acme?.maintenance).toEqual(true);
    });
    
tap.test('ForwardingHandlerFactory - validate configuration', async () => {
      // Valid configuration
      const validConfig: IForwardConfig = {
        type: 'http-only',
        target: { host: 'localhost', port: 3000 }
      };
      
      expect(() => ForwardingHandlerFactory.validateConfig(validConfig)).not.toThrow();
      
      // Invalid configuration - missing target
      const invalidConfig1: any = {
        type: 'http-only'
      };
      
      expect(() => ForwardingHandlerFactory.validateConfig(invalidConfig1)).toThrow();
      
      // Invalid configuration - invalid port
      const invalidConfig2: IForwardConfig = {
        type: 'http-only',
        target: { host: 'localhost', port: 0 }
      };
      
      expect(() => ForwardingHandlerFactory.validateConfig(invalidConfig2)).toThrow();
      
      // Invalid configuration - HTTP disabled for HTTP-only
      const invalidConfig3: IForwardConfig = {
        type: 'http-only',
        target: { host: 'localhost', port: 3000 },
        http: { enabled: false }
      };
      
      expect(() => ForwardingHandlerFactory.validateConfig(invalidConfig3)).toThrow();
      
      // Invalid configuration - HTTP enabled for HTTPS passthrough
      const invalidConfig4: IForwardConfig = {
        type: 'https-passthrough',
        target: { host: 'localhost', port: 443 },
        http: { enabled: true }
      };
      
      expect(() => ForwardingHandlerFactory.validateConfig(invalidConfig4)).toThrow();
    });
tap.test('DomainManager - manage domain configurations', async () => {
      const domainManager = new DomainManager();

      // Add a domain configuration
      await domainManager.addDomainConfig(
        createDomainConfig('example.com', helpers.httpOnly({
          target: { host: 'localhost', port: 3000 }
        }))
      );

      // Check that the configuration was added
      const configs = domainManager.getDomainConfigs();
      expect(configs.length).toEqual(1);
      expect(configs[0].domains[0]).toEqual('example.com');
      expect(configs[0].forwarding.type).toEqual('http-only');

      // Find a handler for a domain
      const handler = domainManager.findHandlerForDomain('example.com');
      expect(handler).toBeDefined();

      // Remove a domain configuration
      const removed = domainManager.removeDomainConfig('example.com');
      expect(removed).toBeTrue();

      // Check that the configuration was removed
      const configsAfterRemoval = domainManager.getDomainConfigs();
      expect(configsAfterRemoval.length).toEqual(0);

      // Check that no handler exists anymore
      const handlerAfterRemoval = domainManager.findHandlerForDomain('example.com');
      expect(handlerAfterRemoval).toBeUndefined();
    });

tap.test('DomainManager - support wildcard domains', async () => {
      const domainManager = new DomainManager();

      // Add a wildcard domain configuration
      await domainManager.addDomainConfig(
        createDomainConfig('*.example.com', helpers.httpOnly({
          target: { host: 'localhost', port: 3000 }
        }))
      );

      // Find a handler for a subdomain
      const handler = domainManager.findHandlerForDomain('test.example.com');
      expect(handler).toBeDefined();

      // Find a handler for a different domain (should not match)
      const noHandler = domainManager.findHandlerForDomain('example.org');
      expect(noHandler).toBeUndefined();
    });
tap.test('Helper Functions - create http-only forwarding config', async () => {
      const config = helpers.httpOnly({
        target: { host: 'localhost', port: 3000 }
      });
      expect(config.type).toEqual('http-only');
      expect(config.target.host).toEqual('localhost');
      expect(config.target.port).toEqual(3000);
      expect(config.http?.enabled).toBeTrue();
    });

tap.test('Helper Functions - create https-terminate-to-http config', async () => {
      const config = helpers.tlsTerminateToHttp({
        target: { host: 'localhost', port: 3000 }
      });
      expect(config.type).toEqual('https-terminate-to-http');
      expect(config.target.host).toEqual('localhost');
      expect(config.target.port).toEqual(3000);
      expect(config.http?.redirectToHttps).toBeTrue();
      expect(config.acme?.enabled).toBeTrue();
      expect(config.acme?.maintenance).toBeTrue();
    });

tap.test('Helper Functions - create https-terminate-to-https config', async () => {
      const config = helpers.tlsTerminateToHttps({
        target: { host: 'localhost', port: 8443 }
      });
      expect(config.type).toEqual('https-terminate-to-https');
      expect(config.target.host).toEqual('localhost');
      expect(config.target.port).toEqual(8443);
      expect(config.http?.redirectToHttps).toBeTrue();
      expect(config.acme?.enabled).toBeTrue();
      expect(config.acme?.maintenance).toBeTrue();
    });

tap.test('Helper Functions - create https-passthrough config', async () => {
      const config = helpers.httpsPassthrough({
        target: { host: 'localhost', port: 443 }
      });
      expect(config.type).toEqual('https-passthrough');
      expect(config.target.host).toEqual('localhost');
      expect(config.target.port).toEqual(443);
      expect(config.https?.forwardSni).toBeTrue();
    });
export default tap.start();