/**
 * Route matching utilities for SmartProxy components
 * 
 * This file provides utility functions that use the unified matchers
 * and additional route-specific utilities.
 */

import { DomainMatcher, PathMatcher, IpMatcher, HeaderMatcher } from './matchers/index.js';
import { RouteSpecificity } from './specificity.js';
import type { IRouteSpecificity } from './types.js';
import type { IRouteConfig } from '../../proxies/smart-proxy/models/route-types.js';


/**
 * Match domains from a route against a given domain
 * 
 * @param domains Array or single domain pattern to match against
 * @param domain Domain to match
 * @returns Whether the domain matches any of the patterns
 */
export function matchRouteDomain(domains: string | string[] | undefined, domain: string | undefined): boolean {
  // If no domains specified in the route, match all domains
  if (!domains) {
    return true;
  }

  // If no domain in the request, can't match domain-specific routes
  if (!domain) {
    return false;
  }
  
  const patterns = Array.isArray(domains) ? domains : [domains];
  return patterns.some(pattern => DomainMatcher.match(pattern, domain));
}



/**
 * Calculate route specificity score
 * Higher score means more specific matching criteria
 * 
 * @param match Match criteria to evaluate
 * @returns Numeric specificity score
 */
export function calculateRouteSpecificity(match: {
  domains?: string | string[];
  path?: string;
  clientIp?: string[];
  tlsVersion?: string[];
  headers?: Record<string, string | RegExp>;
}): number {
  let score = 0;
  
  // Path specificity using PathMatcher
  if (match.path) {
    score += PathMatcher.calculateSpecificity(match.path);
  }
  
  // Domain specificity using DomainMatcher
  if (match.domains) {
    const domains = Array.isArray(match.domains) ? match.domains : [match.domains];
    // Use the highest specificity among all domains
    const domainScore = Math.max(...domains.map(d => DomainMatcher.calculateSpecificity(d)));
    score += domainScore;
  }
  
  // Headers specificity using HeaderMatcher
  if (match.headers) {
    const stringHeaders: Record<string, string> = {};
    for (const [key, value] of Object.entries(match.headers)) {
      stringHeaders[key] = value instanceof RegExp ? value.source : value;
    }
    score += HeaderMatcher.calculateSpecificity(stringHeaders);
  }
  
  // Client IP adds some specificity
  if (match.clientIp && match.clientIp.length > 0) {
    // Use the first IP pattern for specificity
    score += IpMatcher.calculateSpecificity(match.clientIp[0]);
  }
  
  // TLS version adds minimal specificity
  if (match.tlsVersion && match.tlsVersion.length > 0) {
    score += match.tlsVersion.length * 10;
  }
  
  return score;
}