import type { IPortProxySettings } from './classes.pp.interfaces.js';
import { NetworkProxyBridge } from './classes.pp.networkproxybridge.js';

/**
 * Manages ACME certificate operations
 */
export class AcmeManager {
  constructor(
    private settings: IPortProxySettings,
    private networkProxyBridge: NetworkProxyBridge
  ) {}
  
  /**
   * Get current ACME settings
   */
  public getAcmeSettings(): IPortProxySettings['acme'] {
    return this.settings.acme;
  }
  
  /**
   * Check if ACME is enabled
   */
  public isAcmeEnabled(): boolean {
    return !!this.settings.acme?.enabled;
  }
  
  /**
   * Update ACME certificate settings
   */
  public async updateAcmeSettings(acmeSettings: IPortProxySettings['acme']): Promise<void> {
    console.log('Updating ACME certificate settings');
    
    // Check if enabled state is changing
    const enabledChanging = this.settings.acme?.enabled !== acmeSettings.enabled;
    
    // Update settings
    this.settings.acme = {
      ...this.settings.acme,
      ...acmeSettings,
    };
    
    // Get NetworkProxy instance
    const networkProxy = this.networkProxyBridge.getNetworkProxy();
    
    if (!networkProxy) {
      console.log('Cannot update ACME settings - NetworkProxy not initialized');
      return;
    }
    
    try {
      // If enabled state changed, we need to restart NetworkProxy
      if (enabledChanging) {
        console.log(`ACME enabled state changed to: ${acmeSettings.enabled}`);
        
        // Stop the current NetworkProxy
        await this.networkProxyBridge.stop();
        
        // Reinitialize with new settings
        await this.networkProxyBridge.initialize();
        
        // Start NetworkProxy with new settings
        await this.networkProxyBridge.start();
      } else {
        // Just update the settings in the existing NetworkProxy
        console.log('Updating ACME settings in NetworkProxy without restart');
        
        // Update settings in NetworkProxy
        if (networkProxy.options && networkProxy.options.acme) {
          networkProxy.options.acme = { ...this.settings.acme };
          
          // For certificate renewals, we might want to trigger checks with the new settings
          if (acmeSettings.renewThresholdDays !== undefined) {
            console.log(`Setting new renewal threshold to ${acmeSettings.renewThresholdDays} days`);
            networkProxy.options.acme.renewThresholdDays = acmeSettings.renewThresholdDays;
          }
          
          // Update other settings that might affect certificate operations
          if (acmeSettings.useProduction !== undefined) {
            console.log(`Setting ACME to ${acmeSettings.useProduction ? 'production' : 'staging'} mode`);
          }
          
          if (acmeSettings.autoRenew !== undefined) {
            console.log(`Setting auto-renewal to ${acmeSettings.autoRenew ? 'enabled' : 'disabled'}`);
          }
        }
      }
    } catch (err) {
      console.log(`Error updating ACME settings: ${err}`);
    }
  }
  
  /**
   * Request a certificate for a specific domain
   */
  public async requestCertificate(domain: string): Promise<boolean> {
    // Validate domain format
    if (!this.isValidDomain(domain)) {
      console.log(`Invalid domain format: ${domain}`);
      return false;
    }
    
    // Delegate to NetworkProxyManager
    return this.networkProxyBridge.requestCertificate(domain);
  }
  
  /**
   * Basic domain validation
   */
  private isValidDomain(domain: string): boolean {
    // Very basic domain validation
    if (!domain || domain.length === 0) {
      return false;
    }
    
    // Check for wildcard domains (they can't get ACME certs)
    if (domain.includes('*')) {
      console.log(`Wildcard domains like "${domain}" are not supported for ACME certificates`);
      return false;
    }
    
    // Check if domain has at least one dot and no invalid characters
    const validDomainRegex = /^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
    if (!validDomainRegex.test(domain)) {
      console.log(`Domain "${domain}" has invalid format`);
      return false;
    }
    
    return true;
  }
  
  /**
   * Get eligible domains for ACME certificates
   */
  public getEligibleDomains(): string[] {
    // Collect all eligible domains from domain configs
    const domains: string[] = [];
    
    for (const config of this.settings.domainConfigs) {
      // Skip domains that can't be used with ACME
      const eligibleDomains = config.domains.filter(domain => 
        !domain.includes('*') && this.isValidDomain(domain)
      );
      
      domains.push(...eligibleDomains);
    }
    
    return domains;
  }
}