"""
Test constraint and constraint checking classes.
"""

from loguru import logger

# Import all modules at the top level - these are verified to work
from local_deep_research.advanced_search_system.constraints.base_constraint import (
    Constraint,
    ConstraintType,
)
from local_deep_research.advanced_search_system.constraints.constraint_analyzer import (
    ConstraintAnalyzer,
)
from local_deep_research.advanced_search_system.constraint_checking.base_constraint_checker import (
    BaseConstraintChecker,
)
from local_deep_research.advanced_search_system.constraint_checking.constraint_checker import (
    ConstraintChecker,
)
from local_deep_research.advanced_search_system.constraint_checking.dual_confidence_checker import (
    DualConfidenceChecker,
)
from local_deep_research.advanced_search_system.constraint_checking.strict_checker import (
    StrictChecker,
)
from local_deep_research.advanced_search_system.constraint_checking.threshold_checker import (
    ThresholdChecker,
)
from local_deep_research.advanced_search_system.constraint_checking.rejection_engine import (
    RejectionEngine,
)
from local_deep_research.advanced_search_system.constraint_checking.evidence_analyzer import (
    EvidenceAnalyzer,
)
from local_deep_research.advanced_search_system.candidates.base_candidate import (
    Candidate,
)


class TestConstraintImports:
    """Test that constraint-related classes can be imported."""

    def test_base_constraint_import(self):
        """Test base constraint classes import."""
        assert Constraint is not None
        assert ConstraintType is not None
        logger.info("Base constraint classes imported successfully")

    def test_constraint_analyzer_import(self):
        """Test ConstraintAnalyzer import."""
        assert ConstraintAnalyzer is not None


class TestConstraintCheckingImports:
    """Test constraint checking module imports."""

    def test_base_constraint_checker_import(self):
        """Test base constraint checker import."""
        assert BaseConstraintChecker is not None

    def test_constraint_checker_import(self):
        """Test ConstraintChecker import."""
        assert ConstraintChecker is not None

    def test_dual_confidence_checker_import(self):
        """Test DualConfidenceChecker import."""
        assert DualConfidenceChecker is not None

    def test_strict_checker_import(self):
        """Test StrictChecker import."""
        assert StrictChecker is not None

    def test_threshold_checker_import(self):
        """Test ThresholdChecker import."""
        assert ThresholdChecker is not None

    def test_rejection_engine_import(self):
        """Test RejectionEngine import."""
        assert RejectionEngine is not None

    def test_evidence_analyzer_import(self):
        """Test EvidenceAnalyzer import."""
        assert EvidenceAnalyzer is not None


class TestConstraintAnalyzer:
    """Test ConstraintAnalyzer functionality."""

    def test_instantiation(self, mock_llm):
        """Test that analyzer can be instantiated."""
        analyzer = ConstraintAnalyzer(mock_llm)
        assert analyzer is not None
        logger.info("ConstraintAnalyzer instantiated successfully")


class TestConstraintChecker:
    """Test ConstraintChecker functionality."""

    def test_instantiation(self, mock_llm):
        """Test that checker can be instantiated."""
        checker = ConstraintChecker(mock_llm)
        assert checker is not None
        logger.info("ConstraintChecker instantiated successfully")


class TestDualConfidenceChecker:
    """Test DualConfidenceChecker functionality."""

    def test_instantiation(self, mock_llm):
        """Test that checker can be instantiated."""
        checker = DualConfidenceChecker(mock_llm)
        assert checker is not None
        logger.info("DualConfidenceChecker instantiated successfully")


class TestConstraintCheckerFunctionality:
    """Test ConstraintChecker with actual functionality."""

    def test_constraint_checker_with_custom_thresholds(self, mock_llm):
        """Test ConstraintChecker with custom thresholds."""
        checker = ConstraintChecker(
            model=mock_llm,
            negative_threshold=0.3,
            positive_threshold=0.5,
            uncertainty_penalty=0.15,
            negative_weight=0.6,
        )

        assert checker.rejection_engine is not None
        assert checker.evidence_analyzer is not None
        logger.info("ConstraintChecker with custom thresholds created")

    def test_constraint_checker_without_evidence_gatherer(self, mock_llm):
        """Test checker behavior without evidence gatherer."""
        checker = ConstraintChecker(model=mock_llm)

        # Create test candidate and constraint
        candidate = Candidate(name="Test Candidate")
        constraint = Constraint(
            id="recency_constraint",
            type=ConstraintType.TEMPORAL,
            description="Must be recent",
            value="recent",
            weight=1.0,
        )

        # Should handle gracefully without evidence gatherer
        result = checker.check_candidate(candidate, [constraint])

        assert result is not None
        assert result.candidate == candidate
        logger.info(f"Checker returned score: {result.total_score}")


class TestEvidenceAnalyzer:
    """Test EvidenceAnalyzer functionality."""

    def test_instantiation(self, mock_llm):
        """Test that analyzer can be instantiated."""
        analyzer = EvidenceAnalyzer(mock_llm)
        assert analyzer is not None
        assert analyzer.model == mock_llm
        logger.info("EvidenceAnalyzer instantiated successfully")


class TestRejectionEngine:
    """Test RejectionEngine functionality."""

    def test_instantiation_default_thresholds(self):
        """Test RejectionEngine with default thresholds."""
        engine = RejectionEngine()
        assert engine is not None
        logger.info("RejectionEngine instantiated with defaults")

    def test_instantiation_custom_thresholds(self):
        """Test RejectionEngine with custom thresholds."""
        engine = RejectionEngine(
            negative_threshold=0.3,
            positive_threshold=0.5,
        )

        assert engine.negative_threshold == 0.3
        assert engine.positive_threshold == 0.5
        logger.info("RejectionEngine with custom thresholds created")


class TestConstraintDataClasses:
    """Test constraint-related data classes."""

    def test_constraint_creation(self):
        """Test Constraint dataclass creation."""
        constraint = Constraint(
            id="test_constraint",
            type=ConstraintType.TEMPORAL,
            description="Must be from 2023",
            value="2023",
            weight=1.5,
        )

        assert constraint.value == "2023"
        assert constraint.type == ConstraintType.TEMPORAL
        assert constraint.weight == 1.5
        assert constraint.id == "test_constraint"
        assert constraint.description == "Must be from 2023"
        logger.info("Constraint created successfully")

    def test_constraint_types(self):
        """Test all ConstraintType enum values exist."""
        # Check common constraint types exist
        assert hasattr(ConstraintType, "TEMPORAL")
        assert hasattr(ConstraintType, "LOCATION")

        # Get all types
        all_types = list(ConstraintType)
        logger.info(
            f"ConstraintType has {len(all_types)} types: {[t.value for t in all_types]}"
        )


class TestCandidateClass:
    """Test Candidate class."""

    def test_candidate_creation(self):
        """Test Candidate class creation."""
        candidate = Candidate(name="Test Entity")
        assert candidate.name == "Test Entity"
        logger.info("Candidate created successfully")

    def test_candidate_with_additional_fields(self):
        """Test Candidate with additional fields if supported."""
        # Try to create with additional fields
        candidate = Candidate(
            name="Test Entity",
        )

        assert candidate.name == "Test Entity"

        # Check what attributes are available
        attrs = [a for a in dir(candidate) if not a.startswith("_")]
        logger.info(f"Candidate attributes: {attrs}")
