from typing import List, Dict, Any
from datetime import datetime
from ai_matcher import AIMatcher
from ai_rules import AIRulesEngine
from feedback_logger import FeedbackLogger
from models import Receipt, Transaction, Match

class MatchingEngine:
    def __init__(self):
        self.ai_matcher = AIMatcher()
        self.rules_engine = AIRulesEngine()
        self.feedback_logger = FeedbackLogger()
    
    def process_matching(self, receipts: List[Receipt], transactions: List[Transaction]) -> List[Match]:
        # Get AI matches
        ai_matches = self.ai_matcher.match_receipts_to_transactions(receipts, transactions)
        
        # Apply rules and enhance matches
        enhanced_matches = []
        for match in ai_matches:
            enhanced_match = self._enhance_match_with_rules(match)
            enhanced_matches.append(enhanced_match)
        
        return enhanced_matches
    
    def _enhance_match_with_rules(self, match: Match) -> Match:
        rule_results = self.rules_engine.apply_rules(match.receipt, match.transaction)
        
        # Apply confidence boost from rules
        if rule_results["confidence_boost"] > 0:
            match.confidence_score = min(1.0, match.confidence_score + rule_results["confidence_boost"])
        
        # Auto-approve if rules say so
        if rule_results["auto_approve"]:
            match.confidence_score = 1.0
            match.match_reason += " (Auto-approved by rules)"
        
        return match
    
    def approve_match(self, match: Match, user_id: str):
        # Log the approval
        self.feedback_logger.log_override(
            transaction_id=match.transaction.id,
            original_match=f"AI Score: {match.confidence_score}",
            correction="Approved",
            reason="User approved match",
            user_id=user_id
        )
    
    def reject_match(self, match: Match, reason: str, user_id: str):
        # Log the rejection
        self.feedback_logger.log_override(
            transaction_id=match.transaction.id,
            original_match=f"AI Score: {match.confidence_score}",
            correction="Rejected",
            reason=reason,
            user_id=user_id
        )
    
    def get_matching_stats(self, matches: List[Match]) -> Dict[str, Any]:
        if not matches:
            return {"total": 0, "high_confidence": 0, "low_confidence": 0, "avg_score": 0}
        
        high_confidence = len([m for m in matches if m.confidence_score >= 0.8])
        low_confidence = len([m for m in matches if m.confidence_score < 0.8])
        avg_score = sum(m.confidence_score for m in matches) / len(matches)
        
        return {
            "total": len(matches),
            "high_confidence": high_confidence,
            "low_confidence": low_confidence,
            "avg_score": round(avg_score, 3)
        } 