"""Tests for XAI Suite Pydantic models."""

import pytest
from datetime import datetime

from xai_suite.ia.models import (
    ExplanationRequest,
    ExplanationRequestV2,
    NarrativeResponse,
    NarrativeResponseV2,
    ExplanationResponseV2,
    Insight,
    ComplianceResponse,
    ApplicableArticle,
    HealthResponse,
    DomainInfo,
    DomainsResponse,
    ErrorResponse,
)


class TestExplanationRequest:
    """Tests for ExplanationRequest model."""

    def test_minimal_request(self):
        """Test minimal valid request."""
        request = ExplanationRequest(
            method="SHAP",
            feature_names=["f1", "f2"],
            importance_scores=[0.5, -0.3]
        )

        assert request.method == "SHAP"
        assert len(request.feature_names) == 2
        assert len(request.importance_scores) == 2

    def test_full_request(self):
        """Test full request with all fields."""
        request = ExplanationRequest(
            method="SHAP",
            feature_names=["f1", "f2"],
            importance_scores=[0.5, -0.3],
            feature_values=[1.0, 2.0],
            base_value=0.5,
            output_value=0.8,
            model_type="classification",
            context={"key": "value"}
        )

        assert request.feature_values == [1.0, 2.0]
        assert request.base_value == 0.5
        assert request.output_value == 0.8
        assert request.model_type == "classification"


class TestExplanationRequestV2:
    """Tests for ExplanationRequestV2 model."""

    def test_minimal_v2_request(self):
        """Test minimal valid V2 request."""
        request = ExplanationRequestV2(
            method="SHAP",
            feature_names=["f1", "f2"],
            importance_scores=[0.5, -0.3]
        )

        assert request.method == "SHAP"
        assert request.domain == "generic"  # default
        assert request.include_insights is True  # default
        assert request.include_compliance is True  # default

    def test_v2_request_with_domain(self):
        """Test V2 request with domain."""
        request = ExplanationRequestV2(
            method="LIME",
            feature_names=["f1", "f2"],
            importance_scores=[0.5, -0.3],
            domain="cybersecurity"
        )

        assert request.domain == "cybersecurity"

    def test_v2_request_flags(self):
        """Test V2 request with flags disabled."""
        request = ExplanationRequestV2(
            method="SHAP",
            feature_names=["f1"],
            importance_scores=[0.5],
            include_insights=False,
            include_compliance=False
        )

        assert request.include_insights is False
        assert request.include_compliance is False


class TestInsight:
    """Tests for Insight model."""

    def test_valid_insight(self):
        """Test valid insight."""
        insight = Insight(
            type="warning",
            priority="high",
            title="Test Warning",
            description="This is a test warning",
            action="Take action",
            related_features=["feature_1", "feature_2"]
        )

        assert insight.type == "warning"
        assert insight.priority == "high"
        assert len(insight.related_features) == 2

    def test_insight_types(self):
        """Test different insight types."""
        for insight_type in ["warning", "recommendation", "observation"]:
            insight = Insight(
                type=insight_type,
                priority="medium",
                title="Test",
                description="Test",
                related_features=[]
            )
            assert insight.type == insight_type

    def test_insight_priorities(self):
        """Test different insight priorities."""
        for priority in ["critical", "high", "medium", "low"]:
            insight = Insight(
                type="warning",
                priority=priority,
                title="Test",
                description="Test",
                related_features=[]
            )
            assert insight.priority == priority

    def test_insight_optional_action(self):
        """Test insight without action."""
        insight = Insight(
            type="observation",
            priority="low",
            title="Test",
            description="Test",
            related_features=[]
        )

        assert insight.action is None


class TestApplicableArticle:
    """Tests for ApplicableArticle model."""

    def test_valid_article(self):
        """Test valid applicable article."""
        article = ApplicableArticle(
            article="article_13",
            title="Transparency and provision of information",
            relevance="XAI explanations support Article 13 compliance"
        )

        assert article.article == "article_13"
        assert "Transparency" in article.title


class TestComplianceResponse:
    """Tests for ComplianceResponse model."""

    def test_valid_compliance(self):
        """Test valid compliance response."""
        compliance = ComplianceResponse(
            audit_id="audit-2026-02-04-abc123",
            timestamp=datetime.utcnow(),
            applicable_articles=[
                ApplicableArticle(
                    article="article_13",
                    title="Transparency",
                    relevance="Supports transparency"
                )
            ]
        )

        assert compliance.audit_id.startswith("audit-")
        assert len(compliance.applicable_articles) == 1


class TestNarrativeResponse:
    """Tests for NarrativeResponse model."""

    def test_valid_narrative(self):
        """Test valid narrative response."""
        response = NarrativeResponse(
            narrative="This is the explanation narrative.",
            compliance_id="audit-123",
            timestamp=datetime.utcnow(),
            method="SHAP"
        )

        assert "explanation" in response.narrative
        assert response.method == "SHAP"


class TestNarrativeResponseV2:
    """Tests for NarrativeResponseV2 model."""

    def test_valid_v2_narrative(self):
        """Test valid V2 narrative response."""
        response = NarrativeResponseV2(
            text="This is the explanation narrative.",
            method="SHAP",
            domain="cybersecurity",
            timestamp=datetime.utcnow()
        )

        assert response.text is not None
        assert response.domain == "cybersecurity"


class TestExplanationResponseV2:
    """Tests for ExplanationResponseV2 model."""

    def test_valid_full_response(self):
        """Test valid full V2 response."""
        response = ExplanationResponseV2(
            narrative=NarrativeResponseV2(
                text="Explanation text",
                method="SHAP",
                domain="generic",
                timestamp=datetime.utcnow()
            ),
            insights=[
                Insight(
                    type="warning",
                    priority="high",
                    title="Test",
                    description="Test",
                    related_features=[]
                )
            ],
            compliance=ComplianceResponse(
                audit_id="audit-123",
                timestamp=datetime.utcnow(),
                applicable_articles=[]
            )
        )

        assert response.narrative is not None
        assert len(response.insights) == 1
        assert response.compliance is not None

    def test_response_with_empty_insights(self):
        """Test response with empty insights list."""
        response = ExplanationResponseV2(
            narrative=NarrativeResponseV2(
                text="Explanation text",
                method="SHAP",
                domain="generic",
                timestamp=datetime.utcnow()
            ),
            insights=[],  # Empty list, not None
            compliance=ComplianceResponse(
                audit_id="audit-123",
                timestamp=datetime.utcnow(),
                applicable_articles=[]
            )
        )

        assert response.narrative is not None
        assert response.insights == []
        assert response.compliance is not None


class TestHealthResponse:
    """Tests for HealthResponse model."""

    def test_valid_health(self):
        """Test valid health response."""
        response = HealthResponse(
            status="healthy",
            version="0.3.0",
            timestamp=datetime.utcnow(),
            llm_backend="template",
            available_domains=["generic", "cybersecurity"]
        )

        assert response.status == "healthy"
        assert "generic" in response.available_domains


class TestDomainModels:
    """Tests for domain-related models."""

    def test_domain_info(self):
        """Test DomainInfo model."""
        domain = DomainInfo(
            id="cybersecurity",
            name="Cybersecurity",
            description="Network security monitoring"
        )

        assert domain.id == "cybersecurity"
        assert domain.name == "Cybersecurity"

    def test_domains_response(self):
        """Test DomainsResponse model."""
        response = DomainsResponse(
            domains=[
                DomainInfo(id="generic", name="Generic", description="Default domain"),
                DomainInfo(id="cybersecurity", name="Cybersecurity", description="Security domain")
            ]
        )

        assert len(response.domains) == 2


class TestErrorResponse:
    """Tests for ErrorResponse model."""

    def test_valid_error(self):
        """Test valid error response."""
        error = ErrorResponse(
            error="unauthorized",
            message="Invalid API key",
            timestamp=datetime.utcnow()
        )

        assert error.error == "unauthorized"
        assert "Invalid" in error.message
