import type { RoutingRequest, RoutingRulePattern } from './routing.types';

/**
 * 匹配 RoutingRequest 是否满足 pattern。
 * 任意字段不匹配返回 false；pattern 字段都不指定（空 pattern）= 兜底规则，必匹配。
 *
 * 不支持 OR / regex / 嵌套；这些进 v2。
 */
export function matchesPattern(req: RoutingRequest, pattern: RoutingRulePattern): boolean {
  if (pattern.taskType !== undefined) {
    if (!matchEnum(req.taskType, pattern.taskType)) return false;
  }
  if (pattern.toolName !== undefined) {
    if (!matchEnum(req.toolName, pattern.toolName)) return false;
  }
  if (pattern.subAgentType !== undefined && req.subAgentType !== pattern.subAgentType) {
    return false;
  }
  if (pattern.skillIntent !== undefined && req.skillIntent !== pattern.skillIntent) {
    return false;
  }
  if (pattern.surface !== undefined) {
    if (!matchEnum(req.surface, pattern.surface)) return false;
  }
  if (pattern.hasImage !== undefined && req.hasImage !== pattern.hasImage) return false;
  if (pattern.hasAudio !== undefined && req.hasAudio !== pattern.hasAudio) return false;
  if (pattern.latencyPriority !== undefined && req.latencyPriority !== pattern.latencyPriority) {
    return false;
  }
  if (pattern.costPriority !== undefined && req.costPriority !== pattern.costPriority) {
    return false;
  }
  if (pattern.contextTokens !== undefined) {
    if (!matchNumeric(req.contextTokens, pattern.contextTokens)) return false;
  }
  if (pattern.turnDepth !== undefined) {
    if (!matchNumeric(req.turnDepth, pattern.turnDepth)) return false;
  }
  return true;
}

function matchEnum<T extends string>(actual: T | undefined, expected: T | T[]): boolean {
  if (actual === undefined) return false;
  return Array.isArray(expected) ? expected.includes(actual) : actual === expected;
}

function matchNumeric(
  actual: number,
  expected: number | { '>'?: number; '<'?: number; '>='?: number; '<='?: number },
): boolean {
  if (typeof expected === 'number') return actual === expected;
  if (expected['>'] !== undefined && !(actual > expected['>'])) return false;
  if (expected['<'] !== undefined && !(actual < expected['<'])) return false;
  if (expected['>='] !== undefined && !(actual >= expected['>='])) return false;
  if (expected['<='] !== undefined && !(actual <= expected['<='])) return false;
  return true;
}
