"""Verifier logic for checking task completion.

Supports different verifier types:
- state_check: Verify that state matches expected conditions
- output_contains: Verify that output contains expected patterns
"""

import re
from typing import Any


def get_value_at_path(data: dict, path: str) -> Any:
    """Get a value from a nested dict/list using dot notation with array indices.

    Args:
        data: The data structure to traverse
        path: Path like "database.users[0].email"

    Returns:
        The value at the path, or None if not found
    """
    current = data

    # Split path into parts, handling array indices
    # e.g., "database.users[0].email" -> ["database", "users", "[0]", "email"]
    parts = re.split(r'\.|\[|\]', path)
    parts = [p for p in parts if p]  # Remove empty strings

    for part in parts:
        if current is None:
            return None

        # Check if it's an array index
        if part.isdigit():
            index = int(part)
            if isinstance(current, list) and 0 <= index < len(current):
                current = current[index]
            else:
                return None
        else:
            if isinstance(current, dict) and part in current:
                current = current[part]
            else:
                return None

    return current


def verify_state_check(state: dict, verifier: dict) -> tuple[bool, str | None]:
    """Verify state against conditions.

    Args:
        state: Current state to check
        verifier: Verifier config with conditions

    Returns:
        Tuple of (passed, failure_reason)
    """
    conditions = verifier.get("conditions", [])

    for condition in conditions:
        path = condition.get("path", "")
        actual_value = get_value_at_path(state, path)

        # Check equality
        if "equals" in condition:
            expected = condition["equals"]
            if actual_value != expected:
                return False, f"State check failed: {path} = {actual_value!r}, expected {expected!r}"

        # Check not equals
        if "not_equals" in condition:
            not_expected = condition["not_equals"]
            if actual_value == not_expected:
                return False, f"State check failed: {path} = {actual_value!r}, should not equal {not_expected!r}"

        # Check contains (for strings or lists)
        if "contains" in condition:
            substring = condition["contains"]
            if isinstance(actual_value, str):
                if substring not in actual_value:
                    return False, f"State check failed: {path} does not contain {substring!r}"
            elif isinstance(actual_value, list):
                if substring not in actual_value:
                    return False, f"State check failed: {path} does not contain {substring!r}"
            else:
                return False, f"State check failed: {path} is not a string or list"

    return True, None


def verify_output_contains(output: str, verifier: dict) -> tuple[bool, str | None]:
    """Verify that output contains expected patterns.

    Args:
        output: The model's output text
        verifier: Verifier config with patterns

    Returns:
        Tuple of (passed, failure_reason)
    """
    patterns = verifier.get("patterns", [])
    missing = []

    for pattern in patterns:
        if pattern not in output:
            missing.append(pattern)

    if missing:
        return False, f"Output missing patterns: {missing}"

    return True, None


def verify_task(
    verifier: dict,
    state: dict,
    output: str,
) -> tuple[bool, float, str | None]:
    """Run verification for a task.

    Args:
        verifier: Verifier configuration from task
        state: Final state after task execution
        output: Combined output from model responses

    Returns:
        Tuple of (passed, score, failure_reason)
    """
    verifier_type = verifier.get("type", "")

    if verifier_type == "state_check":
        passed, reason = verify_state_check(state, verifier)
        return passed, 1.0 if passed else 0.0, reason

    elif verifier_type == "output_contains":
        passed, reason = verify_output_contains(output, verifier)
        return passed, 1.0 if passed else 0.0, reason

    else:
        # Unknown verifier type - fail safe
        return False, 0.0, f"Unknown verifier type: {verifier_type}"
