"""競馬場コースの構造ナレッジ（阪神・中山）に基づく第2段階補正。

根拠テキストは `docs/knowledge/` の取り込み（Google Docs エクスポート）に準拠。
数値はルールベースの微小補正（±数点）に留め、過学習しにくいよう控えめに設定する。
"""
from __future__ import annotations

from datetime import date

# JRA 競馬場コード（racecourse_code 2桁）
TRACK_NAKAYAMA = "06"
TRACK_HANSHIN = "09"


def _z2(code: str | None) -> str:
    if not code:
        return ""
    return str(code).strip().zfill(2)


def hanshin_turf_inner_outer(distance_m: int) -> str | None:
    """阪神芝: 内回り / 外回りの切替（距離ベース）。"""
    if distance_m in (1200, 1400, 2000, 2200, 3000):
        return "inner"
    if distance_m in (1600, 1800, 2400):
        return "outer"
    return None


def nakayama_turf_inner_outer(distance_m: int) -> str | None:
    """中山芝: 内回り / 外回りの切替（距離ベース）。"""
    if distance_m in (1200, 1600, 2200):
        return "outer"
    if distance_m in (1800, 2000, 2500, 3600):
        return "inner"
    return None


def _track_top3_stats(history_rows: list[dict], track_code: str) -> tuple[int, float]:
    """同一競馬場における複勝圏実績（サンプル数と率）。"""
    tc = _z2(track_code)
    if not tc:
        return 0, 0.0
    runs = 0
    top3 = 0
    for row in history_rows:
        if _z2(row.get("track_code")) != tc:
            continue
        pos = int(row.get("finish_position") or 99)
        if pos <= 0:
            continue
        runs += 1
        if pos <= 3:
            top3 += 1
    rate = (float(top3) / float(runs)) if runs else 0.0
    return runs, rate


def compute_course_knowledge_bonus(
    track_code: str | None,
    distance_m: int | None,
    surface: str | None,
    race_date: date | None,
    running_style: str,
    history_rows: list[dict],
) -> tuple[float, list[str]]:
    """
    第2段階に上乗せするコース適性ボーナス（目安 ±3 以内に収める）。
    """
    bonus = 0.0
    reasons: list[str] = []
    if not track_code or not distance_m:
        return bonus, reasons

    tc = _z2(track_code)
    dm = int(distance_m)
    surf = str(surface or "")

    tr, rate = _track_top3_stats(history_rows, tc)
    if tr >= 2:
        if rate >= 0.5:
            bonus += 2.0
            reasons.append("course_same_track_fit_plus")
        elif tr >= 3 and rate < 0.15:
            bonus -= 1.5
            reasons.append("course_same_track_fit_minus")

    # 阪神芝: 外は直線・急坂で差し・パワー、内は機動力・立ち回り
    if tc == TRACK_HANSHIN and surf == "芝":
        io = hanshin_turf_inner_outer(dm)
        if io == "outer":
            if running_style == "closer":
                bonus += 1.2
                reasons.append("hanshin_turf_outer_closer")
            elif running_style == "front":
                bonus -= 0.6
                reasons.append("hanshin_turf_outer_front_risk")
        elif io == "inner":
            if running_style == "front":
                bonus += 0.8
                reasons.append("hanshin_turf_inner_front")
            elif running_style == "stalker":
                bonus += 0.5
                reasons.append("hanshin_turf_inner_stalker")
            elif running_style == "closer":
                bonus -= 0.5
                reasons.append("hanshin_turf_inner_closer_risk")

    # 中山: 短直・急坂・小回り。純粋後方は不利になりやすい（展開補正と併用）
    if tc == TRACK_NAKAYAMA:
        if running_style == "closer":
            bonus -= 1.0
            reasons.append("nakayama_short_straight_closer")
        elif running_style in ("front", "stalker"):
            bonus += 0.6
            reasons.append("nakayama_positioning_plus")
        # 9月開催は馬場・ペースが読みづらいことが多いが、一律の数値補正は避ける

    _ = race_date  # 将来: 馬場・開催週などに拡張

    return round(bonus, 2), reasons
