import * as plugins from '../../plugins.js';

/**
 * Shared Route Context Interface
 * 
 * This interface defines the route context object that is used by both
 * SmartProxy and NetworkProxy, ensuring consistent context throughout the system.
 */

/**
 * Route context for route matching and function-based target resolution
 */
export interface IRouteContext {
  // Connection basics
  port: number;          // The matched incoming port
  domain?: string;       // The domain from SNI or Host header
  clientIp: string;      // The client's IP address
  serverIp: string;      // The server's IP address
  vpn?: {                // Authenticated VPN identity from trusted PROXY v2 metadata
    clientId: string;
    assignedIp: string;
    transportType?: string;
    remoteAddr?: string;
  };
  
  // HTTP specifics (NetworkProxy only)
  path?: string;         // URL path (for HTTP connections)
  query?: string;        // Query string (for HTTP connections) 
  headers?: Record<string, string>; // HTTP headers (for HTTP connections)
  
  // TLS information
  isTls: boolean;        // Whether the connection is TLS
  tlsVersion?: string;   // TLS version if applicable
  
  // Routing information
  routeName?: string;    // The name of the matched route
  routeId?: string;      // The ID of the matched route
  
  // Resolved values
  targetHost?: string | string[]; // The resolved target host
  targetPort?: number;   // The resolved target port
  
  // Request metadata
  timestamp: number;     // The request timestamp
  connectionId: string;  // Unique connection identifier
}

/**
 * Extended context interface with HTTP-specific objects
 * Used only in NetworkProxy for HTTP request handling
 */
export interface IHttpRouteContext extends IRouteContext {
  req?: plugins.http.IncomingMessage;
  res?: plugins.http.ServerResponse;
  method?: string; // HTTP method (GET, POST, etc.)
}

/**
 * Extended context interface with HTTP/2-specific objects
 * Used only in NetworkProxy for HTTP/2 request handling
 */
export interface IHttp2RouteContext extends IHttpRouteContext {
  stream?: plugins.http2.ServerHttp2Stream;
  headers?: Record<string, string>; // HTTP/2 pseudo-headers like :method, :path
}

/**
 * Create a basic route context from connection information
 */
export function createBaseRouteContext(options: {
  port: number;
  clientIp: string;
  serverIp: string;
  domain?: string;
  isTls: boolean;
  tlsVersion?: string;
  connectionId: string;
}): IRouteContext {
  return {
    ...options,
    timestamp: Date.now(),
  };
}

/**
 * Convert IHttpRouteContext to IRouteContext
 * This is used to ensure type compatibility when passing HTTP-specific context 
 * to methods that require the base IRouteContext type
 */
export function toBaseContext(httpContext: IHttpRouteContext): IRouteContext {
  // Create a new object with only the properties from IRouteContext
  const baseContext: IRouteContext = {
    port: httpContext.port,
    domain: httpContext.domain,
    clientIp: httpContext.clientIp,
    serverIp: httpContext.serverIp,
    vpn: httpContext.vpn,
    path: httpContext.path,
    query: httpContext.query,
    headers: httpContext.headers,
    isTls: httpContext.isTls,
    tlsVersion: httpContext.tlsVersion,
    routeName: httpContext.routeName,
    routeId: httpContext.routeId,
    timestamp: httpContext.timestamp,
    connectionId: httpContext.connectionId
  };
  
  // Only copy targetHost if it's a string
  if (httpContext.targetHost) {
    baseContext.targetHost = httpContext.targetHost;
  }
  
  // Copy targetPort if it exists
  if (httpContext.targetPort) {
    baseContext.targetPort = httpContext.targetPort;
  }
  
  return baseContext;
}
