/**
 * AI Guardrails Service
 *
 * Pre- and post-processing guardrails for AI responses in the
 * Twilio WhatsApp agent. Prevents prompt injection, XSS, abuse,
 * PII leakage, and enforces WhatsApp message length limits.
 */

import type {
  GuardrailResult,
  GuardrailViolationType,
  StructuredAIResponse,
  ConversationContext,
  AIIntent,
} from '@/lib/types/twilio-whatsapp.types';
import { sanitizeChatMessage, detectXSSPatterns } from '@/lib/sanitizers/chat.sanitizer';
import { logger } from '@/lib/logger';

// ─── Unicode Normalization ──────────────────────────────────

/**
 * Normalize text for guardrail matching:
 * 1. Strip zero-width characters (ZWS, ZWNJ, ZWJ, RLO, LRO, etc.)
 * 2. Map common Cyrillic/Greek homoglyphs to ASCII Latin
 * 3. NFKD normalize for decomposed forms
 */
const ZERO_WIDTH_REGEX = /[\u200B-\u200F\u2028-\u202F\uFEFF\u00AD\u034F\u061C\u115F\u1160\u17B4\u17B5\u180E]/g;

const HOMOGLYPH_MAP: Record<string, string> = {
  '\u0410': 'A', '\u0430': 'a', // Cyrillic А/а → A/a
  '\u0412': 'B', '\u0432': 'b', // Cyrillic В/в → B/b (visual)
  '\u0421': 'C', '\u0441': 'c', // Cyrillic С/с → C/c
  '\u0415': 'E', '\u0435': 'e', // Cyrillic Е/е → E/e
  '\u041D': 'H', '\u043D': 'h', // Cyrillic Н/н → H/h (visual)
  '\u041A': 'K', '\u043A': 'k', // Cyrillic К/к → K/k
  '\u041C': 'M', '\u043C': 'm', // Cyrillic М/м → M/m
  '\u041E': 'O', '\u043E': 'o', // Cyrillic О/о → O/o
  '\u0420': 'P', '\u0440': 'p', // Cyrillic Р/р → P/p
  '\u0422': 'T', '\u0442': 't', // Cyrillic Т/т → T/t
  '\u0425': 'X', '\u0445': 'x', // Cyrillic Х/х → X/x
  '\u0423': 'Y', '\u0443': 'y', // Cyrillic У/у → Y/y (visual)
  '\u0456': 'i',                  // Cyrillic і → i
  '\u0458': 'j',                  // Cyrillic ј → j
  '\u0455': 's',                  // Cyrillic ѕ → s
};

function normalizeForGuardrails(text: string): string {
  // 1. Strip zero-width and invisible characters
  let normalized = text.replace(ZERO_WIDTH_REGEX, '');

  // 2. NFKD normalize (decomposes characters)
  normalized = normalized.normalize('NFKD');

  // 3. Map homoglyphs to ASCII
  normalized = Array.from(normalized)
    .map((ch) => HOMOGLYPH_MAP[ch] || ch)
    .join('');

  // 4. Strip emoji and symbols (keep only letters, digits, whitespace, basic punctuation, Arabic)
  //    This prevents emoji insertion between injection keywords
  normalized = normalized.replace(/[^\p{L}\p{N}\s.,!?:;'"()\-/\\@#]/gu, ' ');

  // 5. Collapse multiple spaces into one
  normalized = normalized.replace(/\s{2,}/g, ' ').trim();

  return normalized;
}

// ─── Prompt Injection Patterns ──────────────────────────────

const INJECTION_PATTERNS: RegExp[] = [
  /ignore\s+(all\s+)?previous\s+instructions/i,
  /you\s+are\s+now\s+/i,
  /act\s+as\s+(a|an)\s+(different|new|unrestricted|unfiltered|evil|malicious|hacked|jailbroken)\b/i,
  /system\s*:\s*/i,
  /\[INST\]/i,
  /<\|im_start\|>/i,
  /pretend\s+(you\s+are|that\s+you\s+are|you\s+have\s+no)\s+/i,
  /forget\s+(everything|your|all)/i,
  /new\s+instructions?\s*:/i,
  /override\s+(your|the)\s+(instructions?|rules?|system|safety|restrictions?|guardrails?)/i,
  /jailbreak/i,
  /DAN\s+mode/i,
  /do\s+anything\s+now/i,
  /bypass\s+(your|the|all)\s+(restrictions?|rules?|guardrails?|filters?|safety|limits?|protections?|instructions?|guidelines?)/i,
  /reveal\s+(your|the)\s+system\s+prompt/i,
];

// ─── Arabic Injection Patterns ─────────────────────────────

const ARABIC_INJECTION_PATTERNS: RegExp[] = [
  /تجاهل\s+(كل\s+)?التعليمات\s+(السابقة)?/,        // ignore (all) (previous) instructions
  /أنت\s+الآن\s+/,                                    // you are now
  /تصرف\s+(ك|مثل)\s+/,                               // act as / act like
  /انسَ?\s+(كل|جميع)\s+/,                             // forget all/everything
  /تعليمات\s+جديدة\s*:/,                              // new instructions:
  /تجاوز\s+(كل\s+)?القيود/,                           // bypass (all) restrictions
  /اكشف\s+(عن\s+)?نظام/,                              // reveal system
  /تخطى\s+(كل\s+)?الحماية/,                           // bypass (all) protections
  /غيّر\s+(تعليماتك|سلوكك)/,                         // change your instructions/behavior
  /أعطني\s+(كل\s+)?بيانات\s+(العملاء|الزبائن)/,     // give me (all) customer data
];

// ─── Abuse Patterns ─────────────────────────────────────────

const ABUSE_PATTERNS: RegExp[] = [
  /\b(f+u+c+k+|sh+i+t+|a+ss+h+ole|b+i+t+c+h)\b/i,
  /kill\s+(your|my)self/i,
  /\b(threaten|i('|')?ll\s+hurt|death\s+threat)\b/i,
];

// ─── Constants ──────────────────────────────────────────────

const MAX_INPUT_LENGTH = 10000;
const WHATSAPP_MAX_LENGTH = 1600;
const WHATSAPP_TRUNCATE_AT = 1500;

const VALID_INTENTS: AIIntent[] = [
  'company_query',
  'booking_request',
  'amend_appointment',
  'check_status',
  'greeting',
  'general',
  'off_topic',
  'abuse',
  // Real estate intents
  'property_search',
  'viewing_request',
  'viewing_management',
];

// Phone number pattern: sequences of 7+ digits (with optional separators)
const PHONE_PATTERN = /(?:\+?\d[\d\s\-().]{6,}\d)/g;

// Date patterns to exclude from PII phone detection (ISO dates, common formats)
const DATE_PATTERN = /^\d{4}[-/]\d{2}[-/]\d{2}$|^\d{2}[-/]\d{2}[-/]\d{4}$/;

// ─── Service ────────────────────────────────────────────────

class AIGuardrailsService {
  /**
   * Pre-check an incoming user message before sending to AI.
   * Sanitizes input and checks for injection, XSS, and abuse.
   */
  preCheck(message: string): GuardrailResult {
    // 1. Length check
    if (message.length > MAX_INPUT_LENGTH) {
      logger.warn('[Guardrails] Message exceeds maximum length', {
        length: message.length,
      });
      return {
        safe: false,
        type: 'too_long' as GuardrailViolationType,
        reason: 'Message exceeds maximum length',
        sanitizedMessage: '',
      };
    }

    // 2. Sanitize message
    const sanitized = sanitizeChatMessage(message);

    // 3. XSS check (run on original message before sanitization stripped it)
    const xssResult = detectXSSPatterns(message);
    if (xssResult.isSuspicious) {
      logger.warn('[Guardrails] XSS patterns detected', {
        patterns: xssResult.patterns,
      });
      return {
        safe: false,
        type: 'xss' as GuardrailViolationType,
        reason: `XSS patterns detected: ${xssResult.patterns.join(', ')}`,
        sanitizedMessage: sanitized,
      };
    }

    // 4. Prompt injection check (normalized for Unicode bypass attacks)
    const normalized = normalizeForGuardrails(message);
    for (const pattern of INJECTION_PATTERNS) {
      if (pattern.test(normalized)) {
        logger.warn('[Guardrails] Potential prompt injection detected', {
          pattern: pattern.source,
        });
        return {
          safe: false,
          type: 'prompt_injection' as GuardrailViolationType,
          reason: 'Potential prompt injection detected',
          sanitizedMessage: sanitized,
        };
      }
    }

    // 4b. Arabic injection check (run on original message)
    for (const pattern of ARABIC_INJECTION_PATTERNS) {
      if (pattern.test(message)) {
        logger.warn('[Guardrails] Arabic prompt injection detected', {
          pattern: pattern.source,
        });
        return {
          safe: false,
          type: 'prompt_injection' as GuardrailViolationType,
          reason: 'Potential prompt injection detected',
          sanitizedMessage: sanitized,
        };
      }
    }

    // 5. Abuse check
    for (const pattern of ABUSE_PATTERNS) {
      if (pattern.test(message)) {
        logger.warn('[Guardrails] Inappropriate content detected');
        return {
          safe: false,
          type: 'abuse' as GuardrailViolationType,
          reason: 'Inappropriate content detected',
          sanitizedMessage: sanitized,
        };
      }
    }

    // 6. All checks passed
    return {
      safe: true,
      sanitizedMessage: sanitized,
    };
  }

  /**
   * Post-check an AI response before sending to the customer.
   * Enforces WhatsApp length limits, validates intent, and checks for PII leaks.
   */
  postCheck(aiResponse: StructuredAIResponse, context: ConversationContext): GuardrailResult {
    let responseText = aiResponse.response;

    // 1. Truncate if exceeds WhatsApp limit
    if (responseText.length > WHATSAPP_MAX_LENGTH) {
      logger.info('[Guardrails] Truncating AI response for WhatsApp limit', {
        originalLength: responseText.length,
      });
      responseText = responseText.slice(0, WHATSAPP_TRUNCATE_AT) + '...';
    }

    // 2. Check for phone number leaks (numbers that aren't the customer's own)
    const customerPhone = context.customerPhone.replace(/\D/g, '');
    const phoneMatches = responseText.match(PHONE_PATTERN);

    if (phoneMatches) {
      for (const match of phoneMatches) {
        const trimmed = match.trim();
        // Skip date-like patterns (e.g., 2026-02-21, 21/02/2026)
        if (DATE_PATTERN.test(trimmed)) continue;

        const digitsOnly = trimmed.replace(/\D/g, '');
        // Skip if it matches the customer's own phone number
        if (customerPhone && customerPhone.endsWith(digitsOnly)) continue;
        if (customerPhone && digitsOnly.endsWith(customerPhone)) continue;

        logger.warn('[Guardrails] Potential PII leak in AI response', {
          detectedPattern: match.replace(/\d/g, 'X'), // redact in logs
        });
        return {
          safe: false,
          type: 'pii_leak' as GuardrailViolationType,
          reason: 'AI response contains phone number that may be a PII leak',
          sanitizedMessage: responseText,
        };
      }
    }

    // 3. Validate intent
    if (!VALID_INTENTS.includes(aiResponse.intent)) {
      logger.warn('[Guardrails] Invalid AI intent', {
        intent: aiResponse.intent,
      });
      return {
        safe: false,
        reason: `Invalid intent: ${aiResponse.intent}`,
        sanitizedMessage: responseText,
      };
    }

    // 4. All checks passed
    return {
      safe: true,
      sanitizedMessage: responseText,
    };
  }
}

export const aiGuardrailsService = new AIGuardrailsService();
