from typing import Any

from backend.extract_schema import EXTRACT_FIELDS


def extract_expected_from_sample(task: str, sample: dict[str, Any]) -> dict[str, Any] | None:
    if task == "classify" and sample.get("expected_category") is not None:
        return {"category": sample["expected_category"]}

    if task == "match" and sample.get("expected_is_match") is not None:
        return {"is_match": sample["expected_is_match"]}

    if task == "extract" and sample.get("expected_result") is not None:
        return sample["expected_result"]

    return None


def _normalize_text(value: Any) -> str:
    return str(value).strip().lower().replace(" ", "")


def _list_overlap(expected: list[Any], actual: list[Any]) -> bool:
    if not expected:
        return True

    if not actual:
        return False

    normalized_actual = [_normalize_text(item) for item in actual]
    for item in expected:
        target = _normalize_text(item)
        if any(target in candidate or candidate in target for candidate in normalized_actual):
            continue
        return False

    return True


def evaluate_correctness(
    task: str,
    expected: dict[str, Any] | None,
    result: dict[str, Any] | None,
) -> bool | None:
    if expected is None or result is None:
        return None

    if task == "classify":
        return expected.get("category") == result.get("category")

    if task == "match":
        return expected.get("is_match") == result.get("is_match")

    if task == "extract":
        for key in EXTRACT_FIELDS:
            expected_values = expected.get(key, [])
            if not isinstance(expected_values, list) or not expected_values:
                continue
            actual_values = result.get(key, [])
            if not isinstance(actual_values, list):
                return False
            if not _list_overlap(expected_values, actual_values):
                return False
        return True

    return None


def format_match_label(is_correct: bool | None) -> str:
    if is_correct is True:
        return "正确"
    if is_correct is False:
        return "错误"
    return "未比对"
