"""レースごとの本命（堅実順位1位）に対する「自信度」スコア（0〜100）。

統計的な当たる確率ではなく、スコア差・本命のレース内シェア・場の過去実績を
合成した **賭け金の目安に使える強さ指標**。
v2: 本命の際立ち・シェアをやや重視し、全体レンジを実用上わかりやすく引き上げ。
v3〜v4: 表示ラベルの閾値のみ調整（スコア計算は v2 と同一）。
"""
from __future__ import annotations


def _clamp(x: float, lo: float, hi: float) -> float:
    return max(lo, min(hi, x))


def _ordered_by_accuracy(horses: list[dict]) -> list[dict]:
    if not horses:
        return []
    if all(r.get("rank_accuracy") is not None for r in horses):
        return sorted(horses, key=lambda r: int(r["rank_accuracy"]))
    return sorted(
        horses,
        key=lambda r: float(r.get("score_accuracy") or r.get("score") or 0.0),
        reverse=True,
    )


def compute_honmei_confidence(
    horses: list[dict],
    empirical_p6: dict | None = None,
) -> dict | None:
    """
    本命 = 堅実順位1位（rank_accuracy 最小）の馬について、自信度 0〜100 と内訳を返す。
    """
    ranked = _ordered_by_accuracy(horses)
    if not ranked:
        return None

    honmei = ranked[0]
    s1 = float(honmei.get("score_accuracy") or honmei.get("score") or 0.0)
    if len(ranked) >= 2:
        s2 = float(ranked[1].get("score_accuracy") or ranked[1].get("score") or 0.0)
    else:
        s2 = s1 * 0.85

    raw_margin = max(0.0, s1 - s2)
    # スコア差が大きいほど「本命が際立っている」→ 自信度に寄与（30点差で飽和、v1よりやや敏感）
    margin_norm = _clamp(raw_margin / 30.0, 0.0, 1.0)

    n = max(len(horses), 1)
    top_share = float(honmei.get("win_rate") or honmei.get("stage3_prob") or 0.0)
    floor = 1.0 / float(n)
    if n <= 1:
        top_norm = 1.0
    else:
        top_norm = _clamp((top_share - floor) / max(1e-9, 1.0 - floor), 0.0, 1.0)

    emp_rate: float | None = None
    emp_norm = 0.5
    if empirical_p6:
        ts = empirical_p6.get("tansho_marks") or {}
        r = ts.get("honmei_hit_rate")
        if r is not None:
            emp_rate = float(r)
            # おおよそ 0.22〜0.48 のレンジを 0〜1 に線形マップ（場の実績が良いほど上げる）
            emp_norm = _clamp((emp_rate - 0.22) / (0.48 - 0.22), 0.0, 1.0)

    if emp_rate is not None:
        # 当レースの差・シェアを重視、場の過去は補助（0.38 / 0.38 / 0.24）
        combined = 0.38 * margin_norm + 0.38 * top_norm + 0.24 * emp_norm
    else:
        combined = 0.58 * margin_norm + 0.42 * top_norm

    # 穏やかなレンジ補正（過度に低くならないよう +10% 近辺と底上げ、上限は 100）
    combined_adj = min(1.0, combined * 1.1 + 0.03)
    score_100 = int(round(_clamp(combined_adj, 0.0, 1.0) * 100))

    if score_100 >= 70:
        label = "自信高め"
    elif score_100 >= 50:
        label = "少し自信あり"
    else:
        label = "控え目"

    return {
        "version": 4,
        "score_0_100": score_100,
        "label": label,
        "meaning": "本命の際立ち・レース内シェア・（取得できれば）同場の過去◎的中率を合成した自信度。真の当確ではない。",
        "honmei": {
            "horse_number": int(honmei.get("horse_number") or 0),
            "horse_name": str(honmei.get("horse_name") or ""),
            "rank_accuracy": int(honmei["rank_accuracy"]) if honmei.get("rank_accuracy") is not None else 1,
            "score_accuracy": round(s1, 2),
            "stage3_prob": round(top_share, 6),
        },
        "components": {
            "score_margin_norm_0_1": round(margin_norm, 4),
            "score_margin_points": round(raw_margin, 2),
            "top_share_in_field_norm_0_1": round(top_norm, 4),
            "track_honmei_hit_rate": emp_rate,
            "track_honmei_hit_rate_norm_0_1": round(emp_norm, 4) if emp_rate is not None else None,
        },
        "weights_note": "v4: スコア合成はv2同様。ラベル 自信高め≥70 / 少し自信あり≥50 / 控え目<50",
    }
