import { ComplianceRule, CompliancePolicy, ScanFinding, ScanResult } from './types';
import { getActivePolicy } from './policy';

// Cache compiled regex per policy version
const patternCache = new Map<string, RegExp>();

function compilePattern(patternStr: string): RegExp {
  if (patternCache.has(patternStr)) {
    return patternCache.get(patternStr)!;
  }
  const regex = new RegExp(patternStr, 'gi');
  patternCache.set(patternStr, regex);
  return regex;
}

export function scanField(text: string, fieldName: string, rules: ComplianceRule[]): ScanFinding[] {
  const findings: ScanFinding[] = [];

  for (const rule of rules) {
    try {
      const regex = compilePattern(rule.pattern);
      regex.lastIndex = 0; // Reset for global matching
      let match: RegExpExecArray | null;

      while ((match = regex.exec(text)) !== null) {
        findings.push({
          ruleId: rule.id,
          matchedText: match[0],
          severity: rule.severity,
          position: { start: match.index, end: match.index + match[0].length },
          field: fieldName,
          label: rule.label,
        });
      }
    } catch (err) {
      console.error(`[COMPLIANCE] Invalid regex pattern "${rule.pattern}":`, err);
    }
  }

  return findings;
}

export async function scanContent(
  fields: Record<string, string>,
  policy?: CompliancePolicy | null
): Promise<ScanResult> {
  const activePolicy = policy || await getActivePolicy();
  if (!activePolicy) {
    return { status: 'PASS', severityScore: 0, findings: [] };
  }

  const allRules = [
    ...activePolicy.prohibitedTerms,
    ...activePolicy.discouragedTerms,
  ];

  const allFindings: ScanFinding[] = [];

  for (const [fieldName, text] of Object.entries(fields)) {
    if (!text) continue;
    // Strip HTML tags for scanning but keep raw text
    const plainText = text.replace(/<[^>]+>/g, ' ');
    const fieldFindings = scanField(plainText, fieldName, allRules);
    allFindings.push(...fieldFindings);
  }

  const severityScore = allFindings.reduce((sum, f) => sum + f.severity, 0);
  const { blockThreshold, warnThreshold } = activePolicy.severityThresholds;

  let status: 'PASS' | 'WARN' | 'BLOCK' = 'PASS';
  if (severityScore >= blockThreshold) {
    status = 'BLOCK';
  } else if (severityScore >= warnThreshold) {
    status = 'WARN';
  }

  return { status, severityScore, findings: allFindings };
}
