/**
 * HTTPS Route Helper Functions
 *
 * This module provides utility functions for creating HTTPS route configurations
 * including TLS termination and passthrough routes.
 */

import type { IRouteConfig, IRouteMatch, IRouteAction } from '../../models/route-types.js';
import { SocketHandlers } from './socket-handlers.js';

/**
 * Create an HTTPS route with TLS termination
 * @param domains Domain(s) to match
 * @param target Target host and port
 * @param options Additional route options
 * @returns Route configuration object
 */
export function createHttpsTerminateRoute(
  domains: string | string[],
  target: { host: string | string[]; port: number },
  options: {
    certificate?: 'auto' | { key: string; cert: string };
    httpPort?: number | number[];
    httpsPort?: number | number[];
    reencrypt?: boolean;
    name?: string;
    [key: string]: any;
  } = {}
): IRouteConfig {
  // Create route match
  const match: IRouteMatch = {
    ports: options.httpsPort || 443,
    domains
  };

  // Create route action
  const action: IRouteAction = {
    type: 'forward',
    targets: [target],
    tls: {
      mode: options.reencrypt ? 'terminate-and-reencrypt' : 'terminate',
      certificate: options.certificate || 'auto'
    }
  };

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

/**
 * Create an HTTP to HTTPS redirect route
 * @param domains Domain(s) to match
 * @param httpsPort HTTPS port to redirect to (default: 443)
 * @param options Additional route options
 * @returns Route configuration object
 */
export function createHttpToHttpsRedirect(
  domains: string | string[],
  httpsPort: number = 443,
  options: Partial<IRouteConfig> = {}
): IRouteConfig {
  // Create route match
  const match: IRouteMatch = {
    ports: options.match?.ports || 80,
    domains
  };

  // Create route action
  const action: IRouteAction = {
    type: 'socket-handler',
    socketHandler: SocketHandlers.httpRedirect(`https://{domain}:${httpsPort}{path}`, 301)
  };

  // Create the route config
  return {
    match,
    action,
    name: options.name || `HTTP to HTTPS Redirect for ${Array.isArray(domains) ? domains.join(', ') : domains}`,
    ...options
  };
}

/**
 * Create an HTTPS passthrough route (SNI-based forwarding without TLS termination)
 * @param domains Domain(s) to match
 * @param target Target host and port
 * @param options Additional route options
 * @returns Route configuration object
 */
export function createHttpsPassthroughRoute(
  domains: string | string[],
  target: { host: string | string[]; port: number },
  options: Partial<IRouteConfig> = {}
): IRouteConfig {
  // Create route match
  const match: IRouteMatch = {
    ports: options.match?.ports || 443,
    domains
  };

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

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

/**
 * Create a complete HTTPS server with HTTP to HTTPS redirects
 * @param domains Domain(s) to match
 * @param target Target host and port
 * @param options Additional configuration options
 * @returns Array of two route configurations (HTTPS and HTTP redirect)
 */
export function createCompleteHttpsServer(
  domains: string | string[],
  target: { host: string | string[]; port: number },
  options: {
    certificate?: 'auto' | { key: string; cert: string };
    httpPort?: number | number[];
    httpsPort?: number | number[];
    reencrypt?: boolean;
    name?: string;
    [key: string]: any;
  } = {}
): IRouteConfig[] {
  // Create the HTTPS route
  const httpsRoute = createHttpsTerminateRoute(domains, target, options);

  // Create the HTTP redirect route
  const httpRedirectRoute = createHttpToHttpsRedirect(
    domains,
    // Extract the HTTPS port from the HTTPS route - ensure it's a number
    typeof options.httpsPort === 'number' ? options.httpsPort :
      Array.isArray(options.httpsPort) ? options.httpsPort[0] : 443,
    {
      // Set the HTTP port
      match: {
        ports: options.httpPort || 80,
        domains
      },
      name: `HTTP to HTTPS Redirect for ${Array.isArray(domains) ? domains.join(', ') : domains}`
    }
  );

  return [httpsRoute, httpRedirectRoute];
}
