"""
general_analysis MTF 합성·정렬 점수.
"""

from __future__ import annotations

from typing import Any

import pandas as pd

from config import (
    ALIGN_BB_POS_HIGH,
    ALIGN_BB_POS_LOW,
    ALIGN_RSI_CONFLICT_TIMING_HIGH,
    ALIGN_RSI_CONFLICT_TIMING_LOW,
    ALIGN_RSI_CONFLICT_TREND_HIGH,
    ALIGN_RSI_CONFLICT_TREND_LOW,
    ALIGN_RSI_OVERBOUGHT,
    ALIGN_RSI_OVERSOLD,
)
from deepcoin.analysis.general_analysis_config import TIMING_INTERVALS, TREND_INTERVALS
from deepcoin.analysis.general_analysis_core import ga_col, interval_tf_prefix


def general_analysis_mtf_scores(
    prefixed_row: dict[str, Any],
) -> dict[str, float | int | str]:
    """
    간격 접두사가 붙은 스냅샷 행에서 MTF 합성 점수 계산.

    Args:
        prefixed_row: m3_ga_rsi 형태 flat dict.

    Returns:
        ga_align_* 점수.
    """
    rsi_oversold = 0
    rsi_overbought = 0
    trend_up = 0
    trend_down = 0
    n_timing = 0
    n_trend = 0
    conflict = 0

    for interval in TIMING_INTERVALS:
        p = interval_tf_prefix(interval)
        rk = f"{p}_RSI"
        if rk in prefixed_row and prefixed_row[rk] is not None:
            n_timing += 1
            rsi = float(prefixed_row[rk])
            if rsi < ALIGN_RSI_OVERSOLD:
                rsi_oversold += 1
            if rsi > ALIGN_RSI_OVERBOUGHT:
                rsi_overbought += 1

    for interval in TREND_INTERVALS:
        p = interval_tf_prefix(interval)
        sk = f"{p}_{ga_col('struct_trend')}"
        if sk in prefixed_row:
            n_trend += 1
            t = prefixed_row[sk]
            if t == "up":
                trend_up += 1
            elif t == "down":
                trend_down += 1

    m3_rsi = prefixed_row.get("m3_RSI")
    d1_rsi = prefixed_row.get("d1_RSI")
    if m3_rsi is not None and d1_rsi is not None:
        if (
            float(m3_rsi) < ALIGN_RSI_CONFLICT_TIMING_LOW
            and float(d1_rsi) > ALIGN_RSI_CONFLICT_TREND_HIGH
        ):
            conflict = 1
        if (
            float(m3_rsi) > ALIGN_RSI_CONFLICT_TIMING_HIGH
            and float(d1_rsi) < ALIGN_RSI_CONFLICT_TREND_LOW
        ):
            conflict = 1

    timing_buy_align = rsi_oversold / max(len(TIMING_INTERVALS), 1)
    timing_sell_align = rsi_overbought / max(len(TIMING_INTERVALS), 1)

    return {
        "ga_align_rsi_oversold_tf": rsi_oversold,
        "ga_align_rsi_overbought_tf": rsi_overbought,
        "ga_align_trend_up_tf": trend_up,
        "ga_align_trend_down_tf": trend_down,
        "ga_align_timing_buy_score": round(timing_buy_align, 3),
        "ga_align_timing_sell_score": round(timing_sell_align, 3),
        "ga_align_trend_score": round(
            (trend_up - trend_down) / max(n_trend, 1), 3
        ),
        "ga_align_mtf_conflict": conflict,
    }


def general_analysis_mtf_vote_latest(
    frames_enriched: dict[int, pd.DataFrame],
) -> dict[str, float | int | str]:
    """
    각 TF 최신 완성봉 지표로 TF 가중 투표·필터 점수 산출.

    Args:
        frames_enriched: interval → enrich된 DataFrame.

    Returns:
        ga_vote_* 점수 (접두사 없음, ga_col로 감쌀 것).
    """
    votes_buy = 0
    votes_sell = 0
    trend_ok = 0
    n = 0

    for interval in TIMING_INTERVALS:
        df = frames_enriched.get(interval)
        if df is None or df.empty:
            continue
        row = df.iloc[-1]
        n += 1
        rsi = row.get("RSI")
        if rsi is not None and not pd.isna(rsi):
            if float(rsi) < ALIGN_RSI_OVERSOLD:
                votes_buy += 1
            if float(rsi) > ALIGN_RSI_OVERBOUGHT:
                votes_sell += 1
        bb_pos = row.get("bb_pos")
        if bb_pos is not None and float(bb_pos) < ALIGN_BB_POS_LOW:
            votes_buy += 1
        if bb_pos is not None and float(bb_pos) > ALIGN_BB_POS_HIGH:
            votes_sell += 1

    for interval in TREND_INTERVALS:
        df = frames_enriched.get(interval)
        if df is None or df.empty:
            continue
        row = df.iloc[-1]
        st = row.get(ga_col("struct_trend"), "range")
        if st == "up":
            trend_ok += 1
        elif st == "down":
            trend_ok -= 1

    return {
        "vote_timing_buy": votes_buy,
        "vote_timing_sell": votes_sell,
        "vote_trend_score": trend_ok,
        "vote_tf_used": n,
    }


def general_analysis_vote_columns() -> list[str]:
    return ["vote_timing_buy", "vote_timing_sell", "vote_trend_score", "vote_tf_used"]
