"""Tests for research-related database models."""

import uuid
from datetime import datetime, timezone

import pytest
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

from local_deep_research.database.models import (
    Base,
    Research,
    ResearchHistory,
    ResearchMode,
    ResearchResource,
    ResearchStatus,
    ResearchStrategy,
    ResearchTask,
    SearchQuery,
    SearchResult,
)


class TestResearchModels:
    """Test suite for research-related models."""

    @pytest.fixture
    def engine(self):
        """Create an in-memory SQLite database for testing."""
        engine = create_engine("sqlite:///:memory:")
        Base.metadata.create_all(engine)
        yield engine
        engine.dispose()

    @pytest.fixture
    def session(self, engine):
        """Create a database session for testing."""
        Session = sessionmaker(bind=engine)
        session = Session()
        yield session
        session.close()

    def test_research_history_creation(self, session):
        """Test creating a ResearchHistory record."""
        research = ResearchHistory(
            id=str(uuid.uuid4()),
            query="What is quantum computing?",
            mode="comprehensive",
            status="completed",
            created_at="2024-01-01T12:00:00",
            completed_at="2024-01-01T12:05:00",
            duration_seconds=300,
            progress=100,
            report_path="/reports/quantum_computing.md",
            title="Quantum Computing Research",
            research_meta={"sources": 10, "quality": "high"},
        )

        session.add(research)
        session.commit()

        # Verify the record
        saved = session.query(ResearchHistory).first()
        assert saved is not None
        assert saved.query == "What is quantum computing?"
        assert saved.mode == "comprehensive"
        assert saved.status == "completed"
        assert saved.duration_seconds == 300
        assert saved.progress == 100
        assert saved.research_meta["sources"] == 10

    def test_research_status_enum(self, session):
        """Test Research model with ResearchStatus enum."""
        # Create Research with enum status
        research = Research(
            query="Test query",
            status=ResearchStatus.PENDING,
            mode=ResearchMode.QUICK,
        )

        session.add(research)
        session.commit()

        # Test status transitions
        research.status = ResearchStatus.IN_PROGRESS
        session.commit()

        assert research.status == ResearchStatus.IN_PROGRESS

        # Test all status values
        for status in ResearchStatus:
            r = Research(
                query=f"Test {status.value}",
                status=status,
                mode=ResearchMode.QUICK,
            )
            session.add(r)

        session.commit()

        # Verify all statuses
        all_research = session.query(Research).all()
        assert len(all_research) >= len(ResearchStatus)

    def test_research_progress_log(self, session):
        """Test progress log JSON field in ResearchHistory."""
        progress_log = {
            "steps": [
                {"time": "2024-01-01T12:00:00", "message": "Starting research"},
                {"time": "2024-01-01T12:01:00", "message": "Searching sources"},
                {"time": "2024-01-01T12:03:00", "message": "Analyzing results"},
                {"time": "2024-01-01T12:05:00", "message": "Generating report"},
            ],
            "current_step": 4,
            "total_steps": 4,
        }

        research = ResearchHistory(
            id=str(uuid.uuid4()),
            query="AI research",
            mode="normal",
            status="completed",
            created_at="2024-01-01T12:00:00",
            progress_log=progress_log,
            progress=100,
        )

        session.add(research)
        session.commit()

        # Verify progress log
        saved = session.query(ResearchHistory).first()
        assert saved.progress_log is not None
        assert len(saved.progress_log["steps"]) == 4
        assert saved.progress_log["current_step"] == 4

    def test_research_task_creation(self, session):
        """Test ResearchTask model."""
        task = ResearchTask(
            title="Machine Learning Research",
            description="Research current ML trends and applications",
            status="in_progress",
            priority=5,
            tags=["ml", "ai", "trends"],
            research_metadata={
                "estimated_time": "2 hours",
                "complexity": "medium",
            },
        )

        session.add(task)
        session.commit()

        # Verify task
        saved = session.query(ResearchTask).first()
        assert saved.title == "Machine Learning Research"
        assert saved.priority == 5
        assert "ml" in saved.tags
        assert saved.research_metadata["complexity"] == "medium"

    def test_search_query_and_results(self, session):
        """Test SearchQuery and SearchResult models."""
        # Create research task first
        task = ResearchTask(
            title="Test Research", description="Test", status="pending"
        )
        session.add(task)
        session.commit()

        # Create search query
        query = SearchQuery(
            research_task_id=task.id,
            query="quantum computing applications",
            search_engine="google",
            search_type="web",
            parameters={"num_results": 10, "time_range": "past_year"},
            status="completed",
        )

        session.add(query)
        session.commit()

        # Add search results
        results = [
            SearchResult(
                research_task_id=task.id,
                search_query_id=query.id,
                title="Quantum Computing in 2024",
                url="https://example.com/quantum-2024",
                snippet="Latest developments in quantum computing...",
                relevance_score=0.95,
                content="Full article content here...",
                content_type="article",
                position=1,
                domain="example.com",
                language="en",
                author="Dr. Smith",
                fetch_status="fetched",
            ),
            SearchResult(
                research_task_id=task.id,
                search_query_id=query.id,
                title="Practical Quantum Applications",
                url="https://example.com/quantum-apps",
                snippet="Real-world applications of quantum tech...",
                relevance_score=0.87,
                position=2,
                domain="example.com",
                fetch_status="pending",
            ),
        ]

        session.add_all(results)
        session.commit()

        # Verify relationships
        assert len(query.results) == 2
        assert query.results[0].relevance_score == 0.95
        assert task.searches[0].query == "quantum computing applications"

    def test_research_strategy(self, session):
        """Test ResearchStrategy model."""
        # Create Research first
        research = Research(
            query="Climate change solutions",
            status=ResearchStatus.PENDING,
            mode=ResearchMode.DETAILED,
        )
        session.add(research)
        session.commit()

        # Create strategy
        strategy = ResearchStrategy(
            research_id=research.id, strategy_name="comprehensive_search"
        )

        session.add(strategy)
        session.commit()

        # Verify
        saved = session.query(ResearchStrategy).first()
        assert saved.strategy_name == "comprehensive_search"
        assert saved.research_id == research.id
        assert saved.research.query == "Climate change solutions"

    def test_research_relationships(self, session):
        """Test relationships between research models."""
        # Create research history
        history = ResearchHistory(
            id=str(uuid.uuid4()),
            query="AI Ethics",
            mode="comprehensive",
            status="completed",
            created_at="2024-01-01T10:00:00",
        )
        session.add(history)
        session.commit()

        # Add resources
        resources = [
            ResearchResource(
                research_id=history.id,
                title="AI Ethics Guidelines",
                url="https://example.com/ai-ethics",
                content_preview="Guidelines for ethical AI development...",
                source_type="article",
                resource_metadata={"credibility": "high"},
                created_at="2024-01-01T10:30:00",
            ),
            ResearchResource(
                research_id=history.id,
                title="Ethics in Machine Learning",
                url="https://example.com/ml-ethics",
                content_preview="Exploring ethical considerations in ML...",
                source_type="research_paper",
                resource_metadata={"peer_reviewed": True},
                created_at="2024-01-01T10:45:00",
            ),
        ]

        session.add_all(resources)
        session.commit()

        # Verify relationships
        assert len(history.resources) == 2
        assert history.resources[0].title == "AI Ethics Guidelines"

        # Test cascade delete
        session.delete(history)
        session.commit()

        # Resources should be deleted too
        remaining_resources = session.query(ResearchResource).count()
        assert remaining_resources == 0

    def test_research_metadata_handling(self, session):
        """Test JSON metadata fields across models."""
        # ResearchHistory with complex metadata
        history = ResearchHistory(
            id=str(uuid.uuid4()),
            query="Complex research",
            mode="normal",
            status="completed",
            created_at="2024-01-01T00:00:00",
            research_meta={
                "sources": {"academic": 5, "news": 10, "blogs": 3},
                "quality_metrics": {
                    "relevance": 0.85,
                    "credibility": 0.9,
                    "recency": 0.95,
                },
                "search_iterations": 3,
                "total_sources_examined": 50,
            },
        )

        session.add(history)
        session.commit()

        # Verify complex metadata
        saved = session.query(ResearchHistory).first()
        assert saved.research_meta["sources"]["academic"] == 5
        assert saved.research_meta["quality_metrics"]["relevance"] == 0.85

    def test_search_result_content(self, session):
        """Test SearchResult content storage and retrieval."""
        # Create parent objects
        task = ResearchTask(
            title="Content Test",
            description="Testing content storage",
            status="pending",
        )
        session.add(task)
        session.commit()

        query = SearchQuery(
            research_task_id=task.id,
            query="test query",
            search_engine="google",
            status="completed",
        )
        session.add(query)
        session.commit()

        # Large content
        large_content = "x" * 10000  # 10KB of content

        result = SearchResult(
            research_task_id=task.id,
            search_query_id=query.id,
            title="Large Article",
            url="https://example.com/large",
            snippet="Beginning of large article...",
            content=large_content,
            content_type="article",
            relevance_score=0.8,
            position=1,
            domain="example.com",
            language="en",
            fetch_status="fetched",
            fetched_at=datetime.now(timezone.utc),
        )

        session.add(result)
        session.commit()

        # Verify content
        saved = session.query(SearchResult).first()
        assert len(saved.content) == 10000
        assert saved.fetch_status == "fetched"
        assert saved.domain == "example.com"

    def test_research_error_handling(self, session):
        """Test error tracking in research models."""
        # Failed research
        failed_research = ResearchHistory(
            id=str(uuid.uuid4()),
            query="This will fail",
            mode="quick",
            status="failed",
            created_at="2024-01-01T00:00:00",
            research_meta={
                "error": "NetworkError",
                "error_message": "Connection timeout",
                "retry_count": 3,
                "last_error_timestamp": "2024-01-01T00:05:00",
            },
        )

        session.add(failed_research)
        session.commit()

        # Failed search query
        task = ResearchTask(
            title="Error Test", description="Test", status="failed"
        )
        session.add(task)
        session.commit()

        failed_query = SearchQuery(
            research_task_id=task.id,
            query="problematic query",
            search_engine="bing",
            status="failed",
            error_message="Rate limit exceeded",
            retry_count=5,
        )

        session.add(failed_query)
        session.commit()

        # Verify error tracking
        assert failed_research.research_meta["error"] == "NetworkError"
        assert failed_query.error_message == "Rate limit exceeded"
        assert failed_query.retry_count == 5
