#!/usr/bin/env python3
"""
Tests unitaires pour l'évaluateur de qualité.
"""
import pytest
from pathlib import Path
from evaluation.quality_evaluator import QualityEvaluator, EvaluationResult


class TestQualityEvaluator:
    """Tests pour QualityEvaluator."""
    
    def test_normalize_text(self):
        """Test de normalisation de texte."""
        evaluator = QualityEvaluator(Path("tests/ground_truth"))
        
        assert evaluator.normalize_text("DUPONT") == "dupont"
        assert evaluator.normalize_text("  DUPONT  ") == "dupont"
        assert evaluator.normalize_text("DUPONT\n\nMARTIN") == "dupont martin"
        assert evaluator.normalize_text("Jean-Pierre") == "jean-pierre"
    
    def test_types_match(self):
        """Test de correspondance des types."""
        evaluator = QualityEvaluator(Path("tests/ground_truth"))
        
        # Correspondance directe
        assert evaluator.types_match("NOM", "NOM")
        assert evaluator.types_match("NOM", "NOM_GLOBAL")
        assert evaluator.types_match("TEL", "TEL_GLOBAL")
        
        # Correspondance croisée
        assert evaluator.types_match("NOM", "PRENOM")
        assert evaluator.types_match("PRENOM", "NOM")
        
        # Non correspondance
        assert not evaluator.types_match("NOM", "TEL")
        assert not evaluator.types_match("EMAIL", "ADRESSE")
    
    def test_calculate_metrics(self):
        """Test de calcul des métriques."""
        evaluator = QualityEvaluator(Path("tests/ground_truth"))
        
        # Cas parfait
        precision, recall, f1 = evaluator.calculate_metrics(10, 0, 0)
        assert precision == 1.0
        assert recall == 1.0
        assert f1 == 1.0
        
        # Cas avec erreurs
        precision, recall, f1 = evaluator.calculate_metrics(8, 2, 2)
        assert precision == 0.8  # 8 / (8 + 2)
        assert recall == 0.8     # 8 / (8 + 2)
        assert abs(f1 - 0.8) < 0.0001  # Tolérance pour les flottants
        
        # Cas zéro
        precision, recall, f1 = evaluator.calculate_metrics(0, 0, 0)
        assert precision == 0.0
        assert recall == 0.0
        assert f1 == 0.0
    
    def test_compare_simple(self):
        """Test de comparaison simple."""
        evaluator = QualityEvaluator(Path("tests/ground_truth"))
        
        annotations = [
            {"page": 0, "type": "NOM", "text": "DUPONT", "context": "Dr. DUPONT"},
            {"page": 0, "type": "TEL", "text": "01 23 45 67 89", "context": "Tel: 01 23 45 67 89"}
        ]
        
        detections = [
            {"page": 0, "kind": "NOM", "original": "DUPONT"},
            {"page": 0, "kind": "TEL", "original": "01 23 45 67 89"}
        ]
        
        tp, fn, fp = evaluator.compare(annotations, detections)
        
        assert len(tp) == 2
        assert len(fn) == 0
        assert len(fp) == 0
    
    def test_compare_with_false_negative(self):
        """Test avec faux négatif."""
        evaluator = QualityEvaluator(Path("tests/ground_truth"))
        
        annotations = [
            {"page": 0, "type": "NOM", "text": "DUPONT", "context": "Dr. DUPONT"},
            {"page": 0, "type": "TEL", "text": "01 23 45 67 89", "context": "Tel: 01 23 45 67 89"}
        ]
        
        detections = [
            {"page": 0, "kind": "NOM", "original": "DUPONT"}
            # TEL manquant
        ]
        
        tp, fn, fp = evaluator.compare(annotations, detections)
        
        assert len(tp) == 1
        assert len(fn) == 1
        assert len(fp) == 0
        assert fn[0]["type"] == "TEL"
        assert fn[0]["reason"] == "not_detected"
    
    def test_compare_with_false_positive(self):
        """Test avec faux positif."""
        evaluator = QualityEvaluator(Path("tests/ground_truth"))
        
        annotations = [
            {"page": 0, "type": "NOM", "text": "DUPONT", "context": "Dr. DUPONT"}
        ]
        
        detections = [
            {"page": 0, "kind": "NOM", "original": "DUPONT"},
            {"page": 0, "kind": "NOM", "original": "MARTIN"}  # Faux positif
        ]
        
        tp, fn, fp = evaluator.compare(annotations, detections)
        
        assert len(tp) == 1
        assert len(fn) == 0
        assert len(fp) == 1
        assert fp[0]["text"] == "MARTIN"
    
    def test_evaluation_result_to_dict(self):
        """Test de conversion en dictionnaire."""
        result = EvaluationResult(
            pdf_path="test.pdf",
            true_positives=10,
            false_positives=2,
            false_negatives=1,
            precision=0.8333,
            recall=0.9091,
            f1_score=0.8696
        )
        
        data = result.to_dict()
        
        assert data["pdf_path"] == "test.pdf"
        assert data["true_positives"] == 10
        assert data["precision"] == 0.8333
        assert data["recall"] == 0.9091
        assert data["f1_score"] == 0.8696


if __name__ == "__main__":
    pytest.main([__file__, "-v"])
