"""
GT 체결 amount_krw·총자산 비율 분석 — 시뮬 tier·배분율 최적 추정.
"""

from __future__ import annotations

from typing import Any

from config import (
    GT_BUY_PCT_LARGE_LEG,
    GT_BUY_PCT_SMALL_LEG,
    GT_INITIAL_CASH_KRW,
    GT_LARGE_LEG_TOP_PCT,
    TRADING_FEE_RATE,
)
from deepcoin.matching.position_sizing import (
    leg_asset_pct_scale,
    optimal_weight_share,
    portfolio_totals,
    top_leg_ids_by_forward_return,
)


def analyze_gt_buy_allocation(
    trades: list[dict[str, Any]],
    *,
    initial_cash: float = GT_INITIAL_CASH_KRW,
    fee_rate: float = TRADING_FEE_RATE,
) -> dict[str, Any]:
    """
    GT 시각순 체결에서 매수별 (실제투입/총자산) 비율을 분석합니다.

    Args:
        trades: amount_krw·weight·leg_id가 채워진 GT trade dict.
        initial_cash: 시작 현금.
        fee_rate: 수수료율.

    Returns:
        leg tier별·전체 배분 통계 및 권장 pct_large/pct_small.
    """
    chron = sorted(trades, key=lambda x: x["dt"])
    if not chron:
        return {"note": "체결 없음"}

    large_legs = top_leg_ids_by_forward_return(chron, GT_LARGE_LEG_TOP_PCT)
    cash = float(initial_cash)
    qty = 0.0

    ratios_large: list[float] = []
    ratios_small: list[float] = []
    ratios_all: list[float] = []

    for i, t in enumerate(chron):
        price = float(t["price"])
        if price <= 0:
            continue
        leg_id = int(t.get("leg_id", 0))
        action = t.get("action", "")

        if action == "buy":
            w = float(t.get("weight", 1.0))
            rem = sum(
                float(chron[j].get("weight", 1.0))
                for j in range(i, len(chron))
                if int(chron[j].get("leg_id", 0)) == leg_id
                and chron[j].get("action") == "buy"
            )
            opt = optimal_weight_share(w, rem) if rem > 0 else 1.0
            total_asset, _, _ = portfolio_totals(cash, qty, price)
            amount = float(t.get("amount_krw") or 0)
            if total_asset > 0 and amount > 0 and opt > 0:
                implied = amount / (total_asset * opt)
                ratios_all.append(implied)
                if leg_id in large_legs:
                    ratios_large.append(implied)
                else:
                    ratios_small.append(implied)
            if amount > 0:
                fee = amount * fee_rate
                cash -= amount + fee
                qty += amount / price
        elif action == "sell" and qty > 0:
            gross = float(t.get("amount_krw") or qty * price)
            cash += gross * (1.0 - fee_rate)
            qty = 0.0

    def _stats(vals: list[float]) -> dict[str, float]:
        if not vals:
            return {}
        s = sorted(vals)
        n = len(s)
        return {
            "count": n,
            "mean": round(sum(s) / n, 4),
            "median": round(s[n // 2], 4),
            "p25": round(s[max(0, n // 4)], 4),
            "p75": round(s[min(n - 1, 3 * n // 4)], 4),
        }

    st_all = _stats(ratios_all)
    st_large = _stats(ratios_large)
    st_small = _stats(ratios_small)

    rec_large = st_large.get("median", GT_BUY_PCT_LARGE_LEG)
    rec_small = st_small.get("median", GT_BUY_PCT_SMALL_LEG)
    if not rec_large or rec_large <= 0:
        rec_large = GT_BUY_PCT_LARGE_LEG
    if not rec_small or rec_small <= 0:
        rec_small = GT_BUY_PCT_SMALL_LEG

    return {
        "large_leg_ids": sorted(large_legs),
        "large_leg_count": len(large_legs),
        "config_pct_large": GT_BUY_PCT_LARGE_LEG,
        "config_pct_small": GT_BUY_PCT_SMALL_LEG,
        "observed_implied_scale": {
            "all": st_all,
            "large_leg": st_large,
            "small_leg": st_small,
        },
        "recommended_pct_large_leg": round(rec_large, 4),
        "recommended_pct_small_leg": round(rec_small, 4),
        "note": (
            "implied_scale = amount / (pre_buy_total_asset × weight_share); "
            "시뮬 tier는 GT 분석 median 사용"
        ),
    }


def gt_tier_scale_from_analysis(
    leg_id: int,
    large_legs: set[int],
    analysis: dict[str, Any] | None = None,
) -> float:
    """
    GT 분석 권장값 또는 config tier scale.

    Args:
        leg_id: leg 번호.
        large_legs: 상위 leg.
        analysis: analyze_gt_buy_allocation 결과.

    Returns:
        총자산 대비 매수 스케일 (0~1).
    """
    if analysis and analysis.get("observed_implied_scale", {}).get("all"):
        if leg_id in large_legs:
            return float(analysis.get("recommended_pct_large_leg", GT_BUY_PCT_LARGE_LEG))
        return float(analysis.get("recommended_pct_small_leg", GT_BUY_PCT_SMALL_LEG))
    return leg_asset_pct_scale(leg_id, large_legs)
