// @lifecycle canonical - Loads verdict patterns from YAML configuration.
/**
 * Verdict Pattern Loader
 *
 * Loads gate verdict parsing patterns from YAML configuration,
 * enabling runtime customization without code changes.
 *
 * @example
 * ```typescript
 * const patterns = loadVerdictPatterns();
 * for (const { regex, priority } of patterns) {
 *   // Use pattern for verdict parsing
 * }
 * ```
 */

import { existsSync } from 'fs';
import { join, dirname } from 'path';
import { fileURLToPath } from 'url';

import { loadYamlFileSync } from '../../../shared/utils/yaml/index.js';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

/**
 * Priority levels for verdict pattern matching.
 * Higher priority patterns are tried first.
 */
export type VerdictPatternPriority = 'primary' | 'high' | 'medium' | 'fallback';

/**
 * A verdict pattern with compiled regex and metadata.
 */
export interface VerdictPattern {
  readonly id: string;
  readonly regex: RegExp;
  readonly priority: VerdictPatternPriority;
  readonly description?: string;
  readonly restrictedSources?: string[];
}

/**
 * Raw pattern definition from YAML.
 */
interface VerdictPatternYaml {
  id: string;
  pattern: string;
  priority: VerdictPatternPriority;
  description?: string;
  restricted_sources?: string[];
  examples?: string[];
}

/**
 * Full YAML configuration structure.
 */
interface VerdictPatternsConfig {
  patterns: VerdictPatternYaml[];
  validation?: {
    require_rationale?: boolean;
    min_rationale_length?: number;
  };
}

// Default patterns as fallback if YAML loading fails
const DEFAULT_PATTERNS: VerdictPattern[] = [
  {
    id: 'full-hyphen',
    regex: /^GATE_REVIEW:\s*(PASS|FAIL)\s*-\s*(.+)$/i,
    priority: 'primary',
    description: 'Full format with hyphen separator',
  },
  {
    id: 'full-colon',
    regex: /^GATE_REVIEW:\s*(PASS|FAIL)\s*:\s*(.+)$/i,
    priority: 'high',
    description: 'Full format with colon separator',
  },
  {
    id: 'simple-hyphen',
    regex: /^GATE\s+(PASS|FAIL)\s*-\s*(.+)$/i,
    priority: 'high',
    description: 'Simplified format with hyphen',
  },
  {
    id: 'simple-colon',
    regex: /^GATE\s+(PASS|FAIL)\s*:\s*(.+)$/i,
    priority: 'medium',
    description: 'Simplified format with colon',
  },
  {
    id: 'minimal',
    regex: /^(PASS|FAIL)\s*[-:]\s*(.+)$/i,
    priority: 'fallback',
    description: 'Minimal format - gate_verdict only',
    restrictedSources: ['gate_verdict'],
  },
];

// Cached patterns (loaded once)
let cachedPatterns: VerdictPattern[] | null = null;
let cachedValidation: { requireRationale: boolean; minRationaleLength: number } | null = null;

/**
 * Resolve the path to the verdict patterns config file.
 */
function resolveConfigPath(): string | null {
  // Try multiple locations
  const candidates = [
    // From src/gates/config/ -> resources/gates/config/
    join(__dirname, '..', '..', '..', 'resources', 'gates', 'config', 'verdict-patterns.yaml'),
    // From dist/gates/config/ -> resources/gates/config/
    join(
      __dirname,
      '..',
      '..',
      '..',
      '..',
      'resources',
      'gates',
      'config',
      'verdict-patterns.yaml'
    ),
    // Environment variable override
    process.env['MCP_VERDICT_PATTERNS_PATH'],
  ].filter(Boolean) as string[];

  for (const path of candidates) {
    if (existsSync(path)) {
      return path;
    }
  }

  return null;
}

/**
 * Compile a YAML pattern definition into a VerdictPattern.
 */
function compilePattern(yaml: VerdictPatternYaml): VerdictPattern {
  return {
    id: yaml.id,
    regex: new RegExp(yaml.pattern, 'i'),
    priority: yaml.priority,
    description: yaml.description,
    restrictedSources: yaml.restricted_sources,
  };
}

/**
 * Load verdict patterns from YAML configuration.
 * Falls back to default patterns if loading fails.
 *
 * @param forceReload - If true, bypass cache and reload from file
 * @returns Array of compiled verdict patterns
 */
export function loadVerdictPatterns(forceReload = false): VerdictPattern[] {
  if (cachedPatterns && !forceReload) {
    return cachedPatterns;
  }

  const configPath = resolveConfigPath();

  if (!configPath) {
    console.warn('[VerdictPatternLoader] Config not found, using defaults');
    cachedPatterns = DEFAULT_PATTERNS;
    return cachedPatterns;
  }

  try {
    const config = loadYamlFileSync<VerdictPatternsConfig>(configPath);

    if (!config?.patterns || !Array.isArray(config.patterns)) {
      console.warn('[VerdictPatternLoader] Invalid config structure, using defaults');
      cachedPatterns = DEFAULT_PATTERNS;
      return cachedPatterns;
    }

    cachedPatterns = config.patterns.map(compilePattern);

    // Cache validation settings
    if (config.validation) {
      cachedValidation = {
        requireRationale: config.validation.require_rationale ?? true,
        minRationaleLength: config.validation.min_rationale_length ?? 1,
      };
    }

    return cachedPatterns;
  } catch (error) {
    console.error('[VerdictPatternLoader] Failed to load config:', error);
    cachedPatterns = DEFAULT_PATTERNS;
    return cachedPatterns;
  }
}

/**
 * Get validation settings for verdict parsing.
 */
export function getVerdictValidationSettings(): {
  requireRationale: boolean;
  minRationaleLength: number;
} {
  // Ensure patterns are loaded (which also loads validation)
  loadVerdictPatterns();

  return (
    cachedValidation ?? {
      requireRationale: true,
      minRationaleLength: 1,
    }
  );
}

/**
 * Clear cached patterns (useful for testing or hot reload).
 */
export function clearVerdictPatternCache(): void {
  cachedPatterns = null;
  cachedValidation = null;
}

/**
 * Get patterns by priority level.
 */
export function getPatternsByPriority(priority: VerdictPatternPriority): VerdictPattern[] {
  return loadVerdictPatterns().filter((p) => p.priority === priority);
}

/**
 * Check if a pattern is restricted to specific sources.
 */
export function isPatternRestrictedToSource(pattern: VerdictPattern, source: string): boolean {
  if (!pattern.restrictedSources || pattern.restrictedSources.length === 0) {
    return false; // No restrictions
  }
  return !pattern.restrictedSources.includes(source);
}
