"""Self-checker for validating solutions."""

from typing import Callable, List, Optional

from .types import Plan, Solution, CheckResult


class SelfChecker:
    """Validates solutions through self-checking.

    The SelfChecker is a key component that validates solutions
    and identifies issues, enabling iterative refinement.
    """

    def __init__(
        self,
        check_fn: Optional[Callable[[str, str, str], CheckResult]] = None,
        auto_suggest: bool = True,
        verbose: bool = False,
    ):
        """Initialize the checker.

        Args:
            check_fn: Optional custom check function.
                     Takes (problem, plan_str, solution_str) and returns CheckResult.
            auto_suggest: Whether to auto-generate improvement suggestions
            verbose: Whether to print debug info
        """
        self._check_fn = check_fn or self._default_check
        self._auto_suggest = auto_suggest
        self._verbose = verbose

    def check(
        self,
        problem: str,
        plan: Plan,
        solution: Solution,
    ) -> CheckResult:
        """Check if a solution is valid.

        Args:
            problem: Original problem
            plan: The plan that was executed
            solution: The produced solution

        Returns:
            CheckResult with validation status
        """
        if self._verbose:
            print(f"\n[Checker] Validating solution...")

        plan_str = plan.to_prompt()
        solution_str = f"{solution.reasoning}\n\nAnswer: {solution.answer}"

        result = self._check_fn(problem, plan_str, solution_str)

        if self._verbose:
            status = "PASSED" if result.passed else "FAILED"
            print(f"[Checker] Check {status} (score: {result.score:.2f})")
            if result.issues:
                for issue in result.issues:
                    print(f"  Issue: {issue}")

        return result

    def _default_check(
        self,
        problem: str,
        plan_str: str,
        solution_str: str,
    ) -> CheckResult:
        """Default checking logic.

        Performs basic validation checks.
        """
        issues = []
        suggestions = []

        # Check if solution is empty
        if not solution_str or len(solution_str.strip()) < 10:
            issues.append("Solution is too short or empty")
            suggestions.append("Provide a more detailed solution")

        # Check if answer addresses the problem
        problem_keywords = self._extract_keywords(problem)
        solution_keywords = self._extract_keywords(solution_str)

        overlap = len(problem_keywords & solution_keywords)
        if overlap < 2:
            issues.append("Solution may not directly address the problem")
            suggestions.append("Ensure the solution relates to the problem statement")

        # Calculate score
        if not issues:
            score = 1.0
        else:
            score = max(0.0, 1.0 - 0.2 * len(issues))

        return CheckResult(
            passed=len(issues) == 0,
            issues=issues,
            suggestions=suggestions,
            score=score,
        )

    def _extract_keywords(self, text: str) -> set:
        """Extract important keywords from text.

        Args:
            text: Input text

        Returns:
            Set of keywords
        """
        # Simple keyword extraction
        stop_words = {"the", "a", "an", "is", "are", "was", "were", "be", "been",
                     "being", "have", "has", "had", "do", "does", "did", "will",
                     "would", "could", "should", "may", "might", "must", "shall",
                     "can", "need", "to", "of", "in", "for", "on", "with", "at",
                     "by", "from", "as", "into", "through", "during", "before",
                     "after", "above", "below", "between", "under", "again",
                     "further", "then", "once", "here", "there", "when", "where",
                     "why", "how", "all", "each", "few", "more", "most", "other",
                     "some", "such", "no", "nor", "not", "only", "own", "same",
                     "so", "than", "too", "very", "just", "and", "but", "if",
                     "or", "because", "until", "while", "this", "that", "these",
                     "those", "what", "which", "who", "whom", "this"}

        words = text.lower().split()
        return {w for w in words if w not in stop_words and len(w) > 2}

    def quick_check(self, answer: str, expected_keywords: List[str]) -> CheckResult:
        """Quick check for specific keywords.

        Args:
            answer: The answer to check
            expected_keywords: Keywords that should be present

        Returns:
            CheckResult
        """
        answer_lower = answer.lower()
        missing = [kw for kw in expected_keywords if kw.lower() not in answer_lower]

        return CheckResult(
            passed=len(missing) == 0,
            issues=[f"Missing: {kw}" for kw in missing],
            suggestions=[f"Include '{kw}' in your answer" for kw in missing],
            score=1.0 - 0.1 * len(missing),
        )