import { SpamShieldService } from '../services/spamshield.service';
import {
  HIGH_RISK_LINK_SCORE,
  SHORT_AGGRESSIVE_SCORE,
  EXCESSIVE_NUMBERS_SCORE,
  URGENT_NEGATIVE_SCORE,
  REPUTATION_SCORE_WEIGHT,
  SMS_SPAM_THRESHOLD,
} from '../constants/sms-classifier.constants';

export interface SmsClassificationResult {
  isSpam: boolean;
  score: number;
  features: {
    language: string;
    length: number;
    hasLinks: boolean;
    hasNumbers: boolean;
    sentiment: 'positive' | 'neutral' | 'negative';
  };
}

export interface SmsClassificationContext {
  text: string;
  senderPhoneNumber?: string;
}

export interface SmsClassifier {
  classify(textOrContext: string | SmsClassificationContext): Promise<SmsClassificationResult>;
  getMetrics(): {
    totalClassified: number;
    spamDetected: number;
    accuracy: number;
  };
}

/**
 * BERT-based SMS Content Classifier
 * Uses language analysis, pattern matching, and ML heuristics
 */
export class BertSmsClassifier implements SmsClassifier {
  private spamShield: SpamShieldService;
  private metrics: {
    totalClassified: number;
    spamDetected: number;
  } = { totalClassified: 0, spamDetected: 0 };

  constructor(spamShield: SpamShieldService) {
    this.spamShield = spamShield;
  }

  async classify(textOrContext: string | SmsClassificationContext): Promise<SmsClassificationResult> {
    const text = typeof textOrContext === 'string' ? textOrContext : textOrContext.text;
    const senderPhoneNumber = typeof textOrContext === 'string' ? undefined : textOrContext.senderPhoneNumber;

    // Feature 1: Language Analysis
    const language = this.analyzeLanguage(text);
    
    // Feature 2: Length Analysis
    const length = text.length;
    const lengthScore = this.calculateLengthScore(length);
    
    // Feature 3: Link Detection
    const hasLinks = this.detectLinks(text);
    
    // Feature 4: Number Detection
    const hasNumbers = /\d/.test(text);
    
    // Feature 5: Sentiment Analysis
    const sentiment = this.analyzeSentiment(text);
    
    // Calculate spam probability
    let spamScore = 0;
    
    // High-risk patterns
    if (hasLinks && length > 100) {
      spamScore += HIGH_RISK_LINK_SCORE;
    }
    
    // Short aggressive messages
    if (length < 20 && hasNumbers) {
      spamScore += SHORT_AGGRESSIVE_SCORE;
    }
    
    // Excessive numbers
    if (/\d{3,}/.test(text)) {
      spamScore += EXCESSIVE_NUMBERS_SCORE;
    }
    
    // Negative/urgent language
    if (sentiment === 'negative' && language === 'unknown') {
      spamScore += URGENT_NEGATIVE_SCORE;
    }
    
    // Combine with reputation score if available
    if (senderPhoneNumber) {
      const reputation = await this.spamShield.checkReputation(senderPhoneNumber);
      if (reputation.isSpam) {
        spamScore += REPUTATION_SCORE_WEIGHT;
      }
    }
    
    const isSpam = spamScore > SMS_SPAM_THRESHOLD;
    
    // Update metrics
    this.metrics.totalClassified++;
    if (isSpam) {
      this.metrics.spamDetected++;
    }
    
    return {
      isSpam,
      score: spamScore,
      features: {
        language,
        length,
        hasLinks,
        hasNumbers,
        sentiment,
      },
    };
  }

  private analyzeLanguage(text: string): string {
    // Simple language detection based on character patterns
    const englishIndicators = /(?:the|be|to|of|and|a|in|that|it|for|on|with|as|at|this|is|you|his|her|they|we|you|their|who|what|when|where|why|how|can|will|would|should|could|may|might|must|shall|do|does|did|done|have|has|had|hav(?:e|e))gi/;
    
    if (englishIndicators.test(text)) {
      return 'english';
    }
    
    if (text.length > 50 && /[а-я]/.test(text)) {
      return 'russian';
    }
    
    if (text.length > 50 && /[가-힣]/.test(text)) {
      return 'korean';
    }
    
    if (text.length > 50 && /[؀-ۿ]/.test(text)) {
      return 'arabic';
    }
    
    return 'unknown';
  }

  private calculateLengthScore(length: number): number {
    // Optimal SMS length is 160 chars
    if (length <= 160) {
      return 0;
    }
    
    // Extra characters beyond 160 increase spam probability
    const overflow = length - 160;
    return Math.min(overflow / 160, 0.3);
  }

  private detectLinks(text: string): boolean {
    const linkPatterns = [
      /https?:\/\/[a-zA-Z0-9.-]+/g,
      /www\.[a-zA-Z0-9.-]+/g,
      /bit\.ly\//g,
      /t\.co\//g,
      /goo\.gl\//g,
    ];
    
    for (const pattern of linkPatterns) {
      if (pattern.test(text)) {
        return true;
      }
    }
    
    return false;
  }

  private analyzeSentiment(text: string): 'positive' | 'neutral' | 'negative' {
    const positiveWords = /(?:happy|good|great|awesome|love|win|free|money|prize|congratulations)/i;
    const negativeWords = /(?:angry|sad|stop|delete|urgent|immediate|call|verify|account|suspicious|blocked)/i;
    const neutralWords = /(?:hello|hi|hey|thanks|thanks|please|help|info)/i;
    
    if (positiveWords.test(text)) {
      return 'positive';
    }
    if (negativeWords.test(text)) {
      return 'negative';
    }
    if (neutralWords.test(text)) {
      return 'neutral';
    }
    
    return 'neutral';
  }

  getMetrics(): {
    totalClassified: number;
    spamDetected: number;
    accuracy: number;
  } {
    const accuracy = this.metrics.totalClassified > 0 
      ? (this.metrics.spamDetected / this.metrics.totalClassified) 
      : 0;
    
    return {
      totalClassified: this.metrics.totalClassified,
      spamDetected: this.metrics.spamDetected,
      accuracy,
    };
  }
}
