"""
general_analysis Volume Profile (POC, VAH, VAL).
"""

from __future__ import annotations

import numpy as np
import pandas as pd

from config import GA_VP_BINS, GA_VP_VALUE_AREA_PCT
from deepcoin.analysis.general_analysis_core import ga_col


def general_analysis_volume_profile(
    win: pd.DataFrame,
    bins: int | None = None,
    value_area_pct: float | None = None,
) -> dict[str, float | int]:
    """
    lookback 구간 가격-거래량 분포에서 POC·VAH·VAL 계산.

    Args:
        win: OHLCV.
        bins: 가격 구간 수.
        value_area_pct: value area 누적 비율 (기본 70%).

    Returns:
        ga_vp_* 키 dict (접두사 없음).
    """
    res: dict[str, float | int] = {
        "vp_poc": 0.0,
        "vp_vah": 0.0,
        "vp_val": 0.0,
        "vp_close_vs_poc_pct": 0.0,
        "vp_in_value_area": 0,
    }
    if bins is None:
        bins = GA_VP_BINS
    if value_area_pct is None:
        value_area_pct = GA_VP_VALUE_AREA_PCT

    if win is None or len(win) < 10 or "Volume" not in win.columns:
        return res

    h = win["High"].astype(float).values
    l = win["Low"].astype(float).values
    c = win["Close"].astype(float).values
    v = win["Volume"].astype(float).values
    tp = (h + l + c) / 3.0

    lo, hi = float(l.min()), float(h.max())
    if hi <= lo:
        return res

    edges = np.linspace(lo, hi, bins + 1)
    hist = np.zeros(bins, dtype=float)
    for i in range(len(tp)):
        idx = int(np.clip(np.digitize(tp[i], edges) - 1, 0, bins - 1))
        hist[idx] += v[i]

    if hist.sum() <= 0:
        return res

    poc_idx = int(np.argmax(hist))
    poc = float((edges[poc_idx] + edges[poc_idx + 1]) / 2)
    res["vp_poc"] = poc

    order = np.argsort(hist)[::-1]
    cum = 0.0
    selected: list[int] = []
    total = hist.sum()
    for idx in order:
        selected.append(int(idx))
        cum += hist[idx]
        if cum >= total * value_area_pct:
            break
    sel_min, sel_max = min(selected), max(selected)
    res["vp_val"] = float(edges[sel_min])
    res["vp_vah"] = float(edges[sel_max + 1])
    res["vp_close_vs_poc_pct"] = float((c[-1] / poc - 1) * 100) if poc else 0.0
    res["vp_in_value_area"] = int(res["vp_val"] <= c[-1] <= res["vp_vah"])

    return res


def general_analysis_volume_columns() -> list[str]:
    return ["vp_poc", "vp_vah", "vp_val", "vp_close_vs_poc_pct", "vp_in_value_area"]


def general_analysis_volume_snapshot(win: pd.DataFrame) -> dict[str, object]:
    """Volume profile → ga_vp_*."""
    return {ga_col(k): v for k, v in general_analysis_volume_profile(win).items()}
