"""核心檢查邏輯"""

import hashlib


def _hash(value):
    """將值轉為字串後計算 SHA-256 hash"""
    return hashlib.sha256(str(value).encode()).hexdigest()


def check_value(answer, expected_hash, expected_type, hints=None):
    """檢查變數值是否正確

    Parameters
    ----------
    answer : any
        學生的答案
    expected_hash : str
        正確答案的 SHA-256 hash
    expected_type : type
        期望的型態 (int, float, str, bool)
    hints : list[str], optional
        漸進式提示列表

    Returns
    -------
    bool
        是否通過
    """
    if not isinstance(answer, expected_type):
        return False, "type_error", type(answer).__name__, expected_type.__name__

    if _hash(answer) == expected_hash:
        return True, "correct", None, None

    return False, "wrong_value", None, None


def _compare(result, tc):
    """比對結果：支援 hash 或直接比較"""
    if "expected_hash" in tc:
        return _hash(result) == tc["expected_hash"]
    if "expected" in tc:
        expected = tc["expected"]
        if isinstance(expected, (int, float)) and isinstance(result, (int, float)):
            return abs(result - expected) < 1e-9
        if isinstance(expected, tuple) and isinstance(result, tuple):
            if len(expected) != len(result):
                return False
            for e, r in zip(expected, result):
                if isinstance(e, (int, float)) and isinstance(r, (int, float)):
                    if abs(e - r) > 1e-9:
                        return False
                elif e != r:
                    return False
            return True
        return result == expected
    return False


def check_function(fn, test_cases):
    """用測試案例檢查函數

    Parameters
    ----------
    fn : callable
        學生定義的函數
    test_cases : list[dict]
        每個 dict 包含 'args' 和 'expected_hash' 或 'expected'

    Returns
    -------
    tuple(bool, list)
        (全部通過, 各案例結果)
    """
    if not callable(fn):
        return False, [{"passed": False, "error": "不是一個函數"}]

    results = []
    for i, tc in enumerate(test_cases):
        args = tc.get("args", ())
        kwargs = tc.get("kwargs", {})
        try:
            result = fn(*args, **kwargs)
            passed = _compare(result, tc)
            results.append({
                "case": i + 1,
                "passed": passed,
                "got_type": type(result).__name__,
            })
        except Exception as e:
            results.append({
                "case": i + 1,
                "passed": False,
                "error": str(e),
            })

    all_passed = all(r["passed"] for r in results)
    return all_passed, results
