
/**
 * Advanced Chatbot Engine for Quote2Contract
 * Features: NLP, Intent Classification, Entity Extraction, Sentiment Analysis, Learning, Multilingual Support
 */

import { detectLanguage, getTranslation, translateOptions, type Language } from './i18n';
import { trainingData, calculateTrainingScore } from './chatbot-training-data';

// Simple tokenizer fallback (for when natural isn't available)
const simpleTokenize = (text: string): string[] => {
  return text.toLowerCase().split(/\s+/).filter(word => word.length > 0);
};

// Simple stemmer fallback
const simpleStem = (word: string): string => {
  // Basic stemming - remove common suffixes
  return word.replace(/ing$|ed$|s$|ly$/, '');
};

// Tokenize function
const tokenize = (text: string): string[] => {
  return simpleTokenize(text);
};

// Stem function
const stem = (word: string): string => {
  return simpleStem(word);
};

// Intent types for Quote2Contract
export type Intent = 
  | 'greeting'
  | 'quote_inquiry'
  | 'pricing'
  | 'services'
  | 'roofing_types'
  | 'contract_status'
  | 'payment'
  | 'timeline'
  | 'contact'
  | 'complaint'
  | 'feedback'
  | 'unknown';

export type EntityType = 'service' | 'material' | 'location' | 'date' | 'price';

export interface Entity {
  type: EntityType;
  value: string;
  confidence: number;
}

export interface ChatbotResponse {
  text: string;
  intent: Intent;
  entities: Entity[];
  sentiment: 'positive' | 'neutral' | 'negative';
  confidence: number;
  language: Language;
  options?: Array<{ label: string; value: string }>;
  fields?: any[];
  requiresHumanEscalation?: boolean;
}

export interface ChatMessage {
  role: 'USER' | 'ASSISTANT';
  content: string;
  timestamp: Date;
  intent?: Intent;
  sentiment?: string;
}

export interface SessionData {
  id: string;
  messages: ChatMessage[];
  context: Record<string, any>;
  learningData: any[];
  created: Date;
  lastActive: Date;
}

// Intent keyword patterns for classification
const intentPatterns: Record<Intent, string[]> = {
  greeting: ['hello', 'hi', 'hey', 'good morning', 'good afternoon', 'good evening', 'greetings'],
  quote_inquiry: ['quote', 'estimate', 'pricing for', 'how much', 'cost of', 'need pricing'],
  pricing: ['price', 'cost', 'rates', 'charges', 'fees', 'pricing'],
  services: ['services', 'offer', 'do you do', 'can you', 'provide', 'installation', 'repair', 'maintenance'],
  roofing_types: ['types', 'materials', 'tile', 'shingle', 'metal', 'slate', 'options', 'what kind'],
  contract_status: ['contract', 'status', 'where is', 'check my', 'my quote', 'my order'],
  payment: ['payment', 'pay', 'financing', 'credit', 'invoice', 'billing'],
  timeline: ['how long', 'when', 'duration', 'timeframe', 'schedule', 'start date'],
  contact: ['contact', 'call', 'email', 'reach', 'speak', 'talk to', 'human', 'representative'],
  complaint: ['complaint', 'issue', 'problem', 'unhappy', 'dissatisfied', 'wrong', 'terrible', 'awful', 'bad service'],
  feedback: ['thank', 'thanks', 'great', 'excellent', 'amazing', 'wonderful', 'love', 'appreciate'],
  unknown: [],
};

// Classify intent using keyword matching with NLP and training data
function classifyIntent(text: string, language: Language): { intent: Intent; confidence: number } {
  const lowerText = text.toLowerCase();
  const tokens = tokenize(lowerText);
  const stemmedTokens = tokens.map(token => stem(token));
  
  let bestIntent: Intent = 'unknown';
  let bestScore = 0;
  
  // Check each intent pattern
  for (const [intent, patterns] of Object.entries(intentPatterns)) {
    if (intent === 'unknown') continue;
    
    let score = 0;
    
    // Pattern matching score
    for (const pattern of patterns) {
      const patternTokens = tokenize(pattern.toLowerCase());
      const stemmedPattern = patternTokens.map(token => stem(token));
      
      // Check for exact matches
      if (lowerText.includes(pattern)) {
        score += 2; // Exact match bonus
      }
      
      // Check for stemmed token matches
      for (const stemmedToken of stemmedTokens) {
        if (stemmedPattern.includes(stemmedToken)) {
          score += 1;
        }
      }
    }
    
    // Add training data score (weighted more heavily)
    const trainingScore = calculateTrainingScore(text, intent, language);
    score += trainingScore * 5; // Training data bonus
    
    if (score > bestScore) {
      bestScore = score;
      bestIntent = intent as Intent;
    }
  }
  
  // Calculate confidence (0-1 scale)
  const confidence = Math.min(bestScore / 8, 1.0);
  
  return { intent: bestIntent, confidence };
}

// Extract entities from text
function extractEntities(text: string): Entity[] {
  const entities: Entity[] = [];
  const lowerText = text.toLowerCase();
  
  // Service entities
  const services = ['installation', 'repair', 'maintenance', 'inspection', 'replacement', 'cleaning'];
  services.forEach(service => {
    if (lowerText.includes(service)) {
      entities.push({ type: 'service', value: service, confidence: 0.9 });
    }
  });
  
  // Material entities
  const materials = ['tile', 'shingle', 'metal', 'slate', 'asphalt', 'concrete', 'clay'];
  materials.forEach(material => {
    if (lowerText.includes(material)) {
      entities.push({ type: 'material', value: material, confidence: 0.9 });
    }
  });
  
  // Price entities (e.g., $1000, R5000)
  const priceRegex = /[\$R€£]\s*\d+(?:,\d{3})*(?:\.\d{2})?/g;
  const prices = text.match(priceRegex);
  if (prices) {
    prices.forEach(price => {
      entities.push({ type: 'price', value: price, confidence: 0.95 });
    });
  }
  
  // Date entities (simple extraction)
  const dateKeywords = ['today', 'tomorrow', 'next week', 'next month', 'asap', 'immediately'];
  dateKeywords.forEach(keyword => {
    if (lowerText.includes(keyword)) {
      entities.push({ type: 'date', value: keyword, confidence: 0.8 });
    }
  });
  
  return entities;
}

// Analyze sentiment
function analyzeSentiment(text: string): 'positive' | 'neutral' | 'negative' {
  const lowerText = text.toLowerCase();
  
  // Simple sentiment analysis based on keywords
  const positiveWords = ['great', 'excellent', 'amazing', 'wonderful', 'good', 'happy', 'love', 'thank', 'perfect', 'awesome'];
  const negativeWords = ['bad', 'terrible', 'awful', 'poor', 'unhappy', 'hate', 'problem', 'issue', 'wrong', 'complaint'];
  
  let score = 0;
  
  for (const word of positiveWords) {
    if (lowerText.includes(word)) score += 1;
  }
  
  for (const word of negativeWords) {
    if (lowerText.includes(word)) score -= 1;
  }
  
  if (score > 0) return 'positive';
  if (score < 0) return 'negative';
  return 'neutral';
}

// Response template keys (to be translated based on language)
const responseTemplateKeys: Record<Intent, string[]> = {
  greeting: ['greeting_welcome', 'greeting_hi'],
  quote_inquiry: ['quote_start', 'quote_guide'],
  pricing: ['pricing_varies', 'pricing_factors'],
  services: ['services_list', 'services_full'],
  roofing_types: ['materials_list', 'materials_options'],
  contract_status: ['status_check', 'status_lookup'],
  payment: ['payment_options', 'payment_methods'],
  timeline: ['timeline_typical', 'timeline_estimate'],
  contact: ['contact_info', 'contact_connect'],
  complaint: ['complaint_sorry', 'complaint_resolve'],
  feedback: ['feedback_thanks', 'feedback_delighted'],
  unknown: ['unknown_clarify', 'unknown_assist'],
};

// Get contextual options based on intent
function getContextualOptions(intent: Intent): Array<{ label: string; value: string }> | undefined {
  switch (intent) {
    case 'greeting':
      return [
        { label: '📋 Get a Quote', value: 'I need a quote' },
        { label: '💰 Check Pricing', value: 'What are your prices?' },
        { label: '🔧 View Services', value: 'What services do you offer?' },
        { label: '📞 Contact Support', value: 'Contact information' },
      ];
    case 'quote_inquiry':
      return [
        { label: '🏠 Residential Roofing', value: 'Residential roofing quote' },
        { label: '🏢 Commercial Roofing', value: 'Commercial roofing quote' },
        { label: '🔨 Roof Repair', value: 'Roof repair quote' },
        { label: '🔍 Inspection Only', value: 'Roof inspection' },
      ];
    case 'services':
      return [
        { label: '⚡ New Installation', value: 'New roof installation' },
        { label: '🔧 Repairs', value: 'Roof repairs' },
        { label: '🛠️ Maintenance', value: 'Roof maintenance' },
        { label: '🚨 Emergency Service', value: 'Emergency roofing' },
      ];
    case 'roofing_types':
      return [
        { label: '🏛️ Tile Roofing', value: 'Tile roofing information' },
        { label: '📐 Shingle Roofing', value: 'Shingle roofing information' },
        { label: '⚙️ Metal Roofing', value: 'Metal roofing information' },
        { label: '💎 Premium Materials', value: 'Premium roofing materials' },
      ];
    default:
      return undefined;
  }
}

// Main chatbot processing function with multilingual support
export async function processChatMessage(
  message: string,
  sessionData?: SessionData
): Promise<ChatbotResponse> {
  // Detect language
  const language = detectLanguage(message);
  
  // Classify intent with language context
  const { intent, confidence } = classifyIntent(message, language);
  
  // Extract entities
  const entities = extractEntities(message);
  
  // Analyze sentiment
  const sentiment = analyzeSentiment(message);
  
  // Select and translate response template
  const templateKeys = responseTemplateKeys[intent] || responseTemplateKeys.unknown;
  const randomKey = templateKeys[Math.floor(Math.random() * templateKeys.length)];
  const responseText = getTranslation(randomKey, language);
  
  // Get contextual options and translate them
  let options = getContextualOptions(intent);
  if (options) {
    options = translateOptions(options, language);
  }
  
  // Determine if human escalation is needed
  const requiresHumanEscalation = 
    intent === 'complaint' || 
    sentiment === 'negative' || 
    (intent === 'unknown' && confidence < 0.2);
  
  return {
    text: responseText,
    intent,
    entities,
    sentiment,
    confidence,
    language,
    options,
    requiresHumanEscalation,
  };
}

// Learn from feedback
export function learnFromFeedback(
  message: string,
  intent: Intent,
  feedback: 'POSITIVE' | 'NEGATIVE'
) {
  if (feedback === 'POSITIVE') {
    // Store successful interactions for future training
    console.log(`Learning: "${message}" -> ${intent} (positive feedback)`);
  } else {
    // Log negative feedback for review and improvement
    console.log(`Review needed: "${message}" -> ${intent} (negative feedback)`);
  }
}

// Session management
const sessions = new Map<string, SessionData>();

export function getSession(sessionId: string): SessionData {
  if (!sessions.has(sessionId)) {
    sessions.set(sessionId, {
      id: sessionId,
      messages: [],
      context: {},
      learningData: [],
      created: new Date(),
      lastActive: new Date(),
    });
  }
  
  const session = sessions.get(sessionId)!;
  session.lastActive = new Date();
  return session;
}

export function updateSession(sessionId: string, message: ChatMessage) {
  const session = getSession(sessionId);
  session.messages.push(message);
  session.lastActive = new Date();
}

// Clean up old sessions (> 24 hours inactive)
export function cleanupSessions() {
  const now = new Date();
  const oneDayAgo = new Date(now.getTime() - 24 * 60 * 60 * 1000);
  
  for (const [sessionId, session] of sessions.entries()) {
    if (session.lastActive < oneDayAgo) {
      sessions.delete(sessionId);
    }
  }
}

// Run cleanup every hour
setInterval(cleanupSessions, 60 * 60 * 1000);
