"""节点 3/6：打分（score）。

归一化（按 source/kind 分组 min-max）-> 跨源融合（combine）-> 综合分阈值预筛。
纯逻辑节点，with_fallback 兜底。
"""
from typing import Any, Dict, List

from graph.scoring import combine, normalize
from graph.validate import with_fallback


@with_fallback("score")
def score_node(state: Dict[str, Any]) -> Dict[str, Any]:
    rows: List[Dict[str, Any]] = state.get("filtered_rows") or []
    config = state["config"]
    weights = config.get("weights") or {}
    llm_cfg = config.get("llm_screen") or {}
    min_score = float(llm_cfg.get("min_score", 0.0))

    normalize(rows)
    combined = combine(rows, weights)
    combined = [c for c in combined if float(c.get("score", 0)) >= min_score]

    stats = dict(state.get("stats") or {})
    stats["score"] = {"combined": len(combined)}
    return {"scored_rows": combined, "stats": stats}
