'use strict';

/**
 * Query sanitizer: defends against prompt contamination in search queries.
 * AI agents sometimes prepend 2000+ char system prompts before actual questions.
 *
 * Rules:
 * - <= 200 chars: passthrough (normal user queries)
 * - > 200 chars + injection patterns: extract the actual question
 * - > 200 chars, no injection: truncate to 500 chars
 */

const INJECTION_PATTERNS = [
  /you are an? (ai|assistant|agent|bot|language model)/i,
  /system\s*:?\s*(prompt|instruction|message)/i,
  /ignore\s+(previous|all|above)\s+(instructions?|prompts?)/i,
  /\b(do not|don't|never)\s+(mention|reveal|share|disclose)/i,
  /\brole\s*:\s*(system|assistant|user)\b/i,
  /\binstructions?\s*:/i,
  /\bcontext\s*:\s*you/i,
  /\brespond\s+(only|always)\s+(in|with)\b/i,
  /\byou are a\b/i,
  /\bact as\b/i,
  /\bpretend to be\b/i,
  /\brespond only in\b/i,
  /\boutput format\s*:/i,
  /\bthe following is\b/i,
  /\bfrom now on\b/i,
];

const QUESTION_PATTERNS = [
  // Sentence ending with ? (including multilingual: ？ and ¿)
  /([^.!?\n]{10,}[?\uff1f\xbf])/g,
  // Sentences starting with question words
  /\b(what|who|where|when|why|how|which|can|could|would|should|is|are|do|does|did|has|have|will|tell me)\b[^.!?\n]{5,}[.!?\n]?/gi,
];

function sanitizeQuery(rawQuery) {
  if (!rawQuery || typeof rawQuery !== 'string') return '';
  const trimmed = rawQuery.trim();

  // Short queries pass through
  if (trimmed.length <= 200) return trimmed;

  // Check for injection patterns
  const hasInjection = INJECTION_PATTERNS.some(p => p.test(trimmed));

  if (hasInjection) {
    // Try to extract the actual question
    // Strategy 1: Find question mark sentences
    const questions = [];
    for (const pattern of QUESTION_PATTERNS) {
      pattern.lastIndex = 0; // reset regex state
      let match;
      while ((match = pattern.exec(trimmed)) !== null) {
        questions.push(match[0].trim());
      }
    }

    // Prefer the last question (most likely the actual user query)
    if (questions.length > 0) {
      const lastQuestion = questions[questions.length - 1];
      if (lastQuestion.length >= 10) return lastQuestion.slice(0, 500);
    }

    // Strategy 2: Extract last complete sentence (walk backward from end)
    const sentences = trimmed.split(/[.!?\n]+/).filter(s => s.trim().length >= 10);
    if (sentences.length > 0) {
      const lastSentence = sentences[sentences.length - 1].trim();
      if (lastSentence.length >= 10) return lastSentence.slice(0, 500);
    }

    // Fallback: take the last 200 chars (tail is more likely the real query)
    return trimmed.slice(-200).trim();
  }

  // Long but no injection — just truncate
  return trimmed.slice(0, 500);
}

module.exports = { sanitizeQuery, INJECTION_PATTERNS };
