"""
general_analysis 하모닉 패턴 (Gartley, Bat 근사).
"""

from __future__ import annotations

import numpy as np

from deepcoin.analysis.general_analysis_core import find_pivots, ga_col


def _ratio(a: float, b: float) -> float:
    if abs(b) < 1e-12:
        return 0.0
    return abs(a / b)


def _near(x: float, target: float, tol: float = 0.08) -> bool:
    return abs(x - target) <= tol


def general_analysis_harmonic_snapshot(win) -> dict[str, object]:
    """
    최근 5개 피벗으로 Gartley·Bat 유사 비율 검사.

    Args:
        win: OHLCV DataFrame.

    Returns:
        ga_harmonic_* dict.
    """
    res: dict[str, object] = {
        "harmonic_gartley": 0,
        "harmonic_bat": 0,
        "harmonic_label": "none",
    }
    if win is None or len(win) < 30:
        return {ga_col(k): v for k, v in res.items()}

    h = win["High"].astype(float).values
    l = win["Low"].astype(float).values
    peaks, troughs = find_pivots(h, l, order=2)
    pivots = sorted([(i, "H", h[i]) for i in peaks] + [(i, "L", l[i]) for i in troughs])
    if len(pivots) < 5:
        return {ga_col(k): v for k, v in res.items()}

    pts = pivots[-5:]
    prices = [p[2] for p in pts]
    xa = abs(prices[1] - prices[0])
    ab = abs(prices[2] - prices[1])
    bc = abs(prices[3] - prices[2])
    cd = abs(prices[4] - prices[3])

    if xa < 1e-9:
        return {ga_col(k): v for k, v in res.items()}

    r_ab = _ratio(ab, xa)
    r_bc = _ratio(bc, ab) if ab > 1e-9 else 0.0
    r_cd = _ratio(cd, bc) if bc > 1e-9 else 0.0

    if _near(r_ab, 0.618) and 0.35 <= r_bc <= 0.95 and 1.1 <= r_cd <= 1.75:
        res["harmonic_gartley"] = 1
        res["harmonic_label"] = "gartley"
    if _near(r_ab, 0.382) and 0.35 <= r_bc <= 0.95 and 1.5 <= r_cd <= 2.1:
        res["harmonic_bat"] = 1
        res["harmonic_label"] = "bat"

    return {ga_col(k): v for k, v in res.items()}


def general_analysis_harmonic_columns() -> list[str]:
    return ["harmonic_gartley", "harmonic_bat", "harmonic_label"]
