"""
Simple threshold-based constraint checker.

This implementation uses simple yes/no threshold checking for constraints,
making it faster but less nuanced than dual confidence checking.
"""

from typing import Any

from loguru import logger

from ..candidates.base_candidate import Candidate
from ..constraints.base_constraint import Constraint
from .base_constraint_checker import (
    BaseConstraintChecker,
    ConstraintCheckResult,
)


class ThresholdChecker(BaseConstraintChecker):
    """
    Simple threshold-based constraint checker.

    This checker:
    1. Uses simple LLM yes/no responses for constraint satisfaction
    2. Makes rejection decisions based on simple thresholds
    3. Faster than dual confidence but less detailed
    """

    def __init__(
        self,
        *args,
        satisfaction_threshold: float = 0.7,  # Minimum score to consider satisfied
        required_satisfaction_rate: float = 0.8,  # % of constraints that must be satisfied
        **kwargs,
    ):
        """
        Initialize threshold checker.

        Args:
            satisfaction_threshold: Minimum score for constraint satisfaction
            required_satisfaction_rate: Percentage of constraints that must be satisfied
        """
        super().__init__(*args, **kwargs)
        self.satisfaction_threshold = satisfaction_threshold
        self.required_satisfaction_rate = required_satisfaction_rate

    def check_candidate(
        self, candidate: Candidate, constraints: list[Constraint]
    ) -> ConstraintCheckResult:
        """Check candidate using simple threshold analysis."""
        logger.info(f"Checking candidate: {candidate.name} (threshold)")

        constraint_scores = {}
        detailed_results = []
        satisfied_count = 0
        total_constraints = len(constraints)

        for constraint in constraints:
            # Gather evidence
            evidence_list = self._gather_evidence_for_constraint(
                candidate, constraint
            )

            if evidence_list:
                # Simple satisfaction check
                satisfaction_score = self._check_constraint_satisfaction(
                    candidate, constraint, evidence_list
                )

                is_satisfied = satisfaction_score >= self.satisfaction_threshold
                if is_satisfied:
                    satisfied_count += 1

                # Store results
                constraint_scores[constraint.value] = {
                    "total": satisfaction_score,
                    "satisfied": is_satisfied,
                    "weight": constraint.weight,
                }

                detailed_results.append(
                    {
                        "constraint": constraint.value,
                        "score": satisfaction_score,
                        "satisfied": is_satisfied,
                        "weight": constraint.weight,
                        "type": constraint.type.value,
                    }
                )

                self._log_constraint_result(
                    candidate, constraint, satisfaction_score, {}
                )

            else:
                # No evidence - consider unsatisfied
                constraint_scores[constraint.value] = {
                    "total": 0.0,
                    "satisfied": False,
                    "weight": constraint.weight,
                }

                detailed_results.append(
                    {
                        "constraint": constraint.value,
                        "score": 0.0,
                        "satisfied": False,
                        "weight": constraint.weight,
                        "type": constraint.type.value,
                    }
                )

                logger.info(
                    f"? {candidate.name} | {constraint.value}: No evidence found"
                )

        # Check rejection based on satisfaction rate
        satisfaction_rate = (
            satisfied_count / total_constraints if total_constraints > 0 else 0
        )
        should_reject = satisfaction_rate < self.required_satisfaction_rate

        rejection_reason = None
        if should_reject:
            rejection_reason = f"Only {satisfied_count}/{total_constraints} constraints satisfied ({satisfaction_rate:.0%})"

        # Calculate total score
        if should_reject:
            total_score = 0.0
        else:
            # Use satisfaction rate as score
            total_score = satisfaction_rate

        logger.info(
            f"Final score for {candidate.name}: {total_score:.2%} ({satisfied_count}/{total_constraints} satisfied)"
        )

        return ConstraintCheckResult(
            candidate=candidate,
            total_score=total_score,
            constraint_scores=constraint_scores,
            should_reject=should_reject,
            rejection_reason=rejection_reason,
            detailed_results=detailed_results,
        )

    def should_reject_candidate(
        self,
        candidate: Candidate,
        constraint: Constraint,
        evidence_data: list[dict[str, Any]],
    ) -> tuple[bool, str]:
        """Simple rejection based on evidence availability and quality."""
        if not evidence_data:
            return (
                True,
                f"No evidence found for constraint '{constraint.value}'",
            )

        satisfaction_score = self._check_constraint_satisfaction(
            candidate, constraint, evidence_data
        )

        if satisfaction_score < self.satisfaction_threshold:
            return (
                True,
                f"Constraint '{constraint.value}' not satisfied (score: {satisfaction_score:.0%})",
            )

        return False, ""

    def _check_constraint_satisfaction(
        self,
        candidate: Candidate,
        constraint: Constraint,
        evidence_list: list[dict[str, Any]],
    ) -> float:
        """Check if constraint is satisfied using simple LLM prompt."""
        # Combine evidence texts
        combined_evidence = "\n".join(
            [e.get("text", "")[:200] for e in evidence_list[:3]]
        )

        prompt = f"""
Does the candidate "{candidate.name}" satisfy this constraint: "{constraint.value}"?

Evidence:
{combined_evidence}

Consider the evidence and respond with a satisfaction score from 0.0 to 1.0 where:
- 1.0 = Definitely satisfies the constraint
- 0.5 = Partially satisfies or unclear
- 0.0 = Definitely does not satisfy the constraint

Score:
"""

        try:
            response = self.model.invoke(prompt).content.strip()

            # Extract score
            import re

            match = re.search(r"(\d*\.?\d+)", response)
            if match:
                score = float(match.group(1))
                return max(0.0, min(score, 1.0))

        except Exception:
            logger.exception("Error checking constraint satisfaction")

        return 0.5  # Default to neutral if parsing fails
