/**
 * Dynamic Route Helper Functions
 *
 * This module provides utility functions for creating dynamic routes
 * with context-based host and port mapping.
 */

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

/**
 * Create a helper function that applies a port offset
 * @param offset The offset to apply to the matched port
 * @returns A function that adds the offset to the matched port
 */
export function createPortOffset(offset: number): (context: IRouteContext) => number {
  return (context: IRouteContext) => context.port + offset;
}

/**
 * Create a port mapping route with context-based port function
 * @param options Port mapping route options
 * @returns Route configuration object
 */
export function createPortMappingRoute(options: {
  sourcePortRange: TPortRange;
  targetHost: string | string[] | ((context: IRouteContext) => string | string[]);
  portMapper: (context: IRouteContext) => number;
  name?: string;
  domains?: string | string[];
  priority?: number;
  [key: string]: any;
}): IRouteConfig {
  // Create route match
  const match: IRouteMatch = {
    ports: options.sourcePortRange,
    domains: options.domains
  };

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

  // Create the route config
  return {
    match,
    action,
    name: options.name || `Port Mapping Route for ${options.domains || 'all domains'}`,
    priority: options.priority,
    ...options
  };
}

/**
 * Create a simple offset port mapping route
 * @param options Offset port mapping route options
 * @returns Route configuration object
 */
export function createOffsetPortMappingRoute(options: {
  ports: TPortRange;
  targetHost: string | string[];
  offset: number;
  name?: string;
  domains?: string | string[];
  priority?: number;
  [key: string]: any;
}): IRouteConfig {
  return createPortMappingRoute({
    sourcePortRange: options.ports,
    targetHost: options.targetHost,
    portMapper: (context) => context.port + options.offset,
    name: options.name || `Offset Mapping (${options.offset > 0 ? '+' : ''}${options.offset}) for ${options.domains || 'all domains'}`,
    domains: options.domains,
    priority: options.priority,
    ...options
  });
}

/**
 * Create a dynamic route with context-based host and port mapping
 * @param options Dynamic route options
 * @returns Route configuration object
 */
export function createDynamicRoute(options: {
  ports: TPortRange;
  targetHost: (context: IRouteContext) => string | string[];
  portMapper: (context: IRouteContext) => number;
  name?: string;
  domains?: string | string[];
  path?: string;
  clientIp?: string[];
  priority?: number;
  [key: string]: any;
}): IRouteConfig {
  // Create route match
  const match: IRouteMatch = {
    ports: options.ports,
    domains: options.domains,
    path: options.path,
    clientIp: options.clientIp
  };

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

  // Create the route config
  return {
    match,
    action,
    name: options.name || `Dynamic Route for ${options.domains || 'all domains'}`,
    priority: options.priority,
    ...options
  };
}
