"""
Tests basiques pour valider les modèles de données.

Ces tests vérifient que les modèles Pydantic sont correctement définis
et que les validations fonctionnent.
"""

from datetime import datetime

import pytest
from pydantic import ValidationError

from pipeline_mco_pmsi.models import (
    ClinicalDocument,
    ClinicalFact,
    Code,
    Evidence,
    Qualifier,
    Span,
)


class TestSpan:
    """Tests pour le modèle Span."""

    def test_span_valid(self):
        """Test création d'un Span valide."""
        span = Span(start=0, end=10)
        assert span.start == 0
        assert span.end == 10

    def test_span_end_must_be_after_start(self):
        """Test que end doit être > start."""
        with pytest.raises(ValidationError):
            Span(start=10, end=5)

    def test_span_immutable(self):
        """Test que Span est immutable."""
        span = Span(start=0, end=10)
        with pytest.raises(ValidationError):
            span.start = 5  # type: ignore


class TestEvidence:
    """Tests pour le modèle Evidence."""

    def test_evidence_valid(self):
        """Test création d'une Evidence valide."""
        evidence = Evidence(
            document_id="doc_001",
            span=Span(start=0, end=10),
            text="Gastrite aiguë",
        )
        assert evidence.document_id == "doc_001"
        assert evidence.text == "Gastrite aiguë"

    def test_evidence_with_context(self):
        """Test Evidence avec contexte."""
        evidence = Evidence(
            document_id="doc_001",
            span=Span(start=0, end=10),
            text="Gastrite aiguë",
            context="Patient présente une gastrite aiguë depuis 48h",
        )
        assert evidence.context is not None


class TestQualifier:
    """Tests pour le modèle Qualifier."""

    def test_qualifier_affirme(self):
        """Test Qualifier affirmé."""
        qualifier = Qualifier(
            certainty="affirmé",
            markers=[],
            confidence=0.95,
        )
        assert qualifier.certainty == "affirmé"
        assert qualifier.confidence == 0.95

    def test_qualifier_nie(self):
        """Test Qualifier nié."""
        qualifier = Qualifier(
            certainty="nié",
            markers=["pas de", "absence de"],
            confidence=0.85,
        )
        assert qualifier.certainty == "nié"
        assert len(qualifier.markers) == 2

    def test_qualifier_invalid_certainty(self):
        """Test que certainty doit être valide."""
        with pytest.raises(ValidationError):
            Qualifier(
                certainty="invalide",  # type: ignore
                markers=[],
                confidence=0.5,
            )

    def test_qualifier_confidence_bounds(self):
        """Test que confidence doit être entre 0 et 1."""
        with pytest.raises(ValidationError):
            Qualifier(
                certainty="affirmé",
                markers=[],
                confidence=1.5,  # Invalide
            )


class TestClinicalDocument:
    """Tests pour le modèle ClinicalDocument."""

    def test_clinical_document_valid(self):
        """Test création d'un ClinicalDocument valide."""
        doc = ClinicalDocument(
            document_id="doc_001",
            document_type="cr_medical",
            content="Patient admis pour douleurs abdominales.",
            creation_date=datetime(2024, 1, 15, 10, 30),
            priority=2,
        )
        assert doc.document_id == "doc_001"
        assert doc.document_type == "cr_medical"
        assert doc.priority == 2

    def test_clinical_document_invalid_type(self):
        """Test que document_type doit être valide."""
        with pytest.raises(ValidationError):
            ClinicalDocument(
                document_id="doc_001",
                document_type="invalide",  # type: ignore
                content="Contenu",
                creation_date=datetime.now(),
                priority=1,
            )


class TestCode:
    """Tests pour le modèle Code."""

    def test_code_valid(self):
        """Test création d'un Code valide."""
        evidence = Evidence(
            document_id="doc_001",
            span=Span(start=0, end=14),
            text="Gastrite aiguë",
        )
        code = Code(
            code="K29.7",
            label="Gastrite, sans précision",
            type="dp",
            evidence=[evidence],
            confidence=0.85,
            reasoning="Diagnostic principal basé sur les symptômes",
            referentiel_version="2026",
        )
        assert code.code == "K29.7"
        assert code.type == "dp"
        assert len(code.evidence) == 1

    def test_code_evidence_count(self):
        """Test que evidence doit avoir 1 à 3 éléments."""
        evidence = Evidence(
            document_id="doc_001",
            span=Span(start=0, end=10),
            text="Test",
        )

        # 0 preuves : invalide
        with pytest.raises(ValidationError):
            Code(
                code="K29.7",
                label="Test",
                type="dp",
                evidence=[],  # Invalide
                confidence=0.5,
                reasoning="Test",
                referentiel_version="2026",
            )

        # 4 preuves : invalide
        with pytest.raises(ValidationError):
            Code(
                code="K29.7",
                label="Test",
                type="dp",
                evidence=[evidence, evidence, evidence, evidence],  # Invalide
                confidence=0.5,
                reasoning="Test",
                referentiel_version="2026",
            )


class TestClinicalFact:
    """Tests pour le modèle ClinicalFact."""

    def test_clinical_fact_valid(self):
        """Test création d'un ClinicalFact valide."""
        evidence = Evidence(
            document_id="doc_001",
            span=Span(start=0, end=14),
            text="Gastrite aiguë",
        )
        qualifier = Qualifier(
            certainty="affirmé",
            markers=[],
            confidence=0.95,
        )
        fact = ClinicalFact(
            fact_id="fact_001",
            type="diagnostic",
            text="Gastrite aiguë",
            qualifier=qualifier,
            temporality="actuel",
            evidence=evidence,
            confidence=0.90,
        )
        assert fact.fact_id == "fact_001"
        assert fact.type == "diagnostic"
        assert fact.temporality == "actuel"
