/**
 * Load Balancer Route Helper Functions
 *
 * This module provides utility functions for creating load balancer route configurations.
 */

import type { IRouteConfig, IRouteMatch, IRouteAction, IRouteTarget, TPortRange, IRouteContext } from '../../models/route-types.js';

/**
 * Create a load balancer route (round-robin between multiple backend hosts)
 * @param domains Domain(s) to match
 * @param backendsOrHosts Array of backend servers OR array of host strings (legacy)
 * @param portOrOptions Port number (legacy) OR options object
 * @param options Additional route options (legacy)
 * @returns Route configuration object
 */
export function createLoadBalancerRoute(
  domains: string | string[],
  backendsOrHosts: Array<{ host: string; port: number }> | string[],
  portOrOptions?: number | {
    tls?: {
      mode: 'passthrough' | 'terminate' | 'terminate-and-reencrypt';
      certificate?: 'auto' | { key: string; cert: string };
    };
    useTls?: boolean;
    certificate?: 'auto' | { key: string; cert: string };
    algorithm?: 'round-robin' | 'least-connections' | 'ip-hash';
    healthCheck?: {
      path: string;
      interval: number;
      timeout: number;
      unhealthyThreshold: number;
      healthyThreshold: number;
    };
    [key: string]: any;
  },
  options?: {
    tls?: {
      mode: 'passthrough' | 'terminate' | 'terminate-and-reencrypt';
      certificate?: 'auto' | { key: string; cert: string };
    };
    [key: string]: any;
  }
): IRouteConfig {
  // Handle legacy signature: (domains, hosts[], port, options)
  let backends: Array<{ host: string; port: number }>;
  let finalOptions: any;

  if (Array.isArray(backendsOrHosts) && backendsOrHosts.length > 0 && typeof backendsOrHosts[0] === 'string') {
    // Legacy signature
    const hosts = backendsOrHosts as string[];
    const port = portOrOptions as number;
    backends = hosts.map(host => ({ host, port }));
    finalOptions = options || {};
  } else {
    // New signature
    backends = backendsOrHosts as Array<{ host: string; port: number }>;
    finalOptions = (portOrOptions as any) || {};
  }

  // Extract hosts and ensure all backends use the same port
  const port = backends[0].port;
  const hosts = backends.map(backend => backend.host);

  // Create route match
  const match: IRouteMatch = {
    ports: finalOptions.match?.ports || (finalOptions.tls || finalOptions.useTls ? 443 : 80),
    domains
  };

  // Create route target
  const target: IRouteTarget = {
    host: hosts,
    port
  };

  // Create route action
  const action: IRouteAction = {
    type: 'forward',
    targets: [target]
  };

  // Add TLS configuration if provided
  if (finalOptions.tls || finalOptions.useTls) {
    action.tls = {
      mode: finalOptions.tls?.mode || 'terminate',
      certificate: finalOptions.tls?.certificate || finalOptions.certificate || 'auto'
    };
  }

  // Add load balancing options
  if (finalOptions.algorithm || finalOptions.healthCheck) {
    action.loadBalancing = {
      algorithm: finalOptions.algorithm || 'round-robin',
      healthCheck: finalOptions.healthCheck
    };
  }

  // Create the route config
  return {
    match,
    action,
    name: finalOptions.name || `Load Balancer for ${Array.isArray(domains) ? domains.join(', ') : domains}`,
    ...finalOptions
  };
}

/**
 * Create a smart load balancer with dynamic domain-based backend selection
 * @param options Smart load balancer options
 * @returns Route configuration object
 */
export function createSmartLoadBalancer(options: {
  ports: TPortRange;
  domainTargets: Record<string, string | string[]>;
  portMapper: (context: IRouteContext) => number;
  name?: string;
  defaultTarget?: string | string[];
  priority?: number;
  [key: string]: any;
}): IRouteConfig {
  // Extract all domain keys to create the match criteria
  const domains = Object.keys(options.domainTargets);

  // Create the smart host selector function
  const hostSelector = (context: IRouteContext) => {
    const domain = context.domain || '';
    return options.domainTargets[domain] || options.defaultTarget || 'localhost';
  };

  // Create route match
  const match: IRouteMatch = {
    ports: options.ports,
    domains
  };

  // Create route action
  const action: IRouteAction = {
    type: 'forward',
    targets: [{
      host: hostSelector,
      port: options.portMapper
    }]
  };

  // Create the route config
  return {
    match,
    action,
    name: options.name || `Smart Load Balancer for ${domains.join(', ')}`,
    priority: options.priority,
    ...options
  };
}
