/**
 * @ai-summary Classifies receipt type from email text or OCR raw text
 * @ai-context Uses keyword matching to determine fuel vs maintenance receipts
 *   before falling back to OCR-based classification. Returns confidence score.
 */

import { logger } from '../../../core/logging/logger';
import type { ClassificationResult, ReceiptClassificationType } from './email-ingestion.types';

/** Fuel-related keywords (case-insensitive matching) */
const FUEL_KEYWORDS: string[] = [
  'gas',
  'fuel',
  'gallons',
  'octane',
  'pump',
  'diesel',
  'unleaded',
  'shell',
  'chevron',
  'exxon',
  'bp',
];

/** Maintenance-related keywords (case-insensitive matching). Multi-word entries matched as phrases. */
const MAINTENANCE_KEYWORDS: string[] = [
  'oil change',
  'brake',
  'alignment',
  'tire',
  'rotation',
  'inspection',
  'labor',
  'parts',
  'service',
  'repair',
  'transmission',
  'coolant',
];

/** Minimum keyword matches required for a confident classification */
const CONFIDENCE_THRESHOLD = 2;

export class ReceiptClassifier {
  /**
   * Classify receipt type from email subject and body text.
   * Returns a confident result if >= 2 keyword matches for one type.
   */
  classifyFromText(subject: string | null, body: string | null): ClassificationResult {
    const text = [subject || '', body || ''].join(' ');
    return this.classifyText(text, 'email');
  }

  /**
   * Classify receipt type from OCR raw text output.
   * Uses same keyword matching as email text classification.
   */
  classifyFromOcrRawText(rawText: string): ClassificationResult {
    return this.classifyText(rawText, 'ocr');
  }

  /**
   * Core keyword matching logic shared by email and OCR classification.
   */
  private classifyText(text: string, source: 'email' | 'ocr'): ClassificationResult {
    const normalizedText = text.toLowerCase();

    const fuelMatches = this.countKeywordMatches(normalizedText, FUEL_KEYWORDS);
    const maintenanceMatches = this.countKeywordMatches(normalizedText, MAINTENANCE_KEYWORDS);

    logger.info('Receipt classification keyword analysis', {
      source,
      fuelMatches,
      maintenanceMatches,
      textLength: text.length,
    });

    // Both below threshold - unclassified
    if (fuelMatches < CONFIDENCE_THRESHOLD && maintenanceMatches < CONFIDENCE_THRESHOLD) {
      return { type: 'unclassified', confidence: 0 };
    }

    // Clear winner with threshold met
    if (fuelMatches >= CONFIDENCE_THRESHOLD && fuelMatches > maintenanceMatches) {
      return {
        type: 'fuel',
        confidence: Math.min(fuelMatches / (fuelMatches + maintenanceMatches), 1),
      };
    }

    if (maintenanceMatches >= CONFIDENCE_THRESHOLD && maintenanceMatches > fuelMatches) {
      return {
        type: 'maintenance',
        confidence: Math.min(maintenanceMatches / (fuelMatches + maintenanceMatches), 1),
      };
    }

    // Tie with both meeting threshold - unclassified (ambiguous)
    if (fuelMatches >= CONFIDENCE_THRESHOLD && maintenanceMatches >= CONFIDENCE_THRESHOLD) {
      return { type: 'unclassified', confidence: 0 };
    }

    return { type: 'unclassified', confidence: 0 };
  }

  /**
   * Count how many keywords from the list appear in the text.
   * Multi-word keywords are matched as phrases.
   */
  private countKeywordMatches(normalizedText: string, keywords: string[]): number {
    let matches = 0;
    for (const keyword of keywords) {
      if (normalizedText.includes(keyword)) {
        matches++;
      }
    }
    return matches;
  }

  /**
   * Map classifier type to the EmailRecordType used in the processing pipeline.
   */
  static toRecordType(classificationType: ReceiptClassificationType): 'fuel_log' | 'maintenance_record' | null {
    switch (classificationType) {
      case 'fuel': return 'fuel_log';
      case 'maintenance': return 'maintenance_record';
      case 'unclassified': return null;
    }
  }
}
