"""Unit tests for Pydantic AI agents."""

from pydantic_ai.models.test import TestModel
import pytest

from information_composer.pubmed.analyzer.agents import (
    SYSTEM_PROMPTS,
    analyze_domain,
    analyze_summary,
)
from information_composer.pubmed.analyzer.dependencies import AnalysisDeps
from information_composer.pubmed.analyzer.models import (
    AnalysisConfig,
    DomainResult,
    PaperInput,
    SummaryResult,
)


@pytest.fixture
def analysis_config() -> AnalysisConfig:
    """Create test analysis config."""
    return AnalysisConfig(
        analysis_types=["summary", "domain"],
        llm_provider="openai",
        llm_model="gpt-4o-mini",
        domain_list=["Test Domain 1", "Test Domain 2"],
    )


@pytest.fixture
def paper_input() -> PaperInput:
    """Create test paper input."""
    return PaperInput(
        pmid="12345678",
        title="Test Paper Title",
        abstract="This is a test abstract for testing purposes.",
    )


@pytest.fixture
def analysis_deps(analysis_config: AnalysisConfig) -> AnalysisDeps:
    """Create test analysis deps."""
    import asyncio

    from information_composer.pubmed.analyzer.cache import AnalysisCache

    return AnalysisDeps(
        config=analysis_config,
        cache=AnalysisCache(enabled=False),
        semaphore=asyncio.Semaphore(1),
    )


class TestAnalyzeSummary:
    """Tests for analyze_summary function."""

    @pytest.mark.asyncio
    async def test_analyze_summary_returns_valid_result(
        self,
        paper_input: PaperInput,
        analysis_deps: AnalysisDeps,
    ) -> None:
        """Test that analyze_summary returns a valid SummaryResult."""
        # Use TestModel for deterministic output
        test_model = TestModel()
        result = await analyze_summary(paper_input, analysis_deps, model=test_model)

        # AgentRunResult returned, access output via .output attribute
        assert isinstance(result.output, SummaryResult)
        assert len(result.output.main_findings) > 0
        assert len(result.output.innovations) > 0
        assert result.output.conclusions


class TestAnalyzeDomain:
    """Tests for analyze_domain function."""

    @pytest.mark.asyncio
    async def test_analyze_domain_returns_valid_result(
        self,
        paper_input: PaperInput,
        analysis_deps: AnalysisDeps,
    ) -> None:
        """Test that analyze_domain returns a valid DomainResult."""
        domains = ["Test Domain 1", "Test Domain 2"]

        # Use TestModel for deterministic output
        test_model = TestModel()
        result = await analyze_domain(
            paper_input, domains, analysis_deps, model=test_model
        )

        # AgentRunResult returned, access output via .output attribute
        assert isinstance(result.output, DomainResult)
        assert len(result.output.relevant_domains) > 0
        assert result.output.primary_domain in result.output.relevant_domains
        assert all(0 <= score <= 1 for score in result.output.domain_scores.values())


class TestSystemPrompts:
    """Tests for SYSTEM_PROMPTS."""

    def test_system_prompts_has_summary(self) -> None:
        """Test that SYSTEM_PROMPTS contains summary key."""
        assert "summary" in SYSTEM_PROMPTS
        assert len(SYSTEM_PROMPTS["summary"]) > 100

    def test_system_prompts_has_domain(self) -> None:
        """Test that SYSTEM_PROMPTS contains domain key."""
        assert "domain" in SYSTEM_PROMPTS
        assert len(SYSTEM_PROMPTS["domain"]) > 100


class TestAgentsImport:
    """Tests for module imports."""

    def test_import_agents_module(self) -> None:
        """Test that agents module can be imported."""
        from information_composer.pubmed.analyzer import agents

        assert hasattr(agents, "analyze_summary")
        assert hasattr(agents, "analyze_domain")
        assert hasattr(agents, "SYSTEM_PROMPTS")

    def test_import_from_init(self) -> None:
        """Test that functions can be imported from package init."""
        from information_composer.pubmed.analyzer import (
            SYSTEM_PROMPTS,
            analyze_domain,
            analyze_summary,
        )

        assert callable(analyze_summary)
        assert callable(analyze_domain)
        assert isinstance(SYSTEM_PROMPTS, dict)
