"""
AkDevz AI Market Intelligence — Price Action & Market Structure Engine
Calculates swing points, BOS, CHoCH, and candlestick rejection signatures.
"""
import numpy as np
from typing import Dict, List, Any, Optional

class PriceActionEngine:
    @staticmethod
    def identify_swings(high: np.ndarray, low: np.ndarray, window: int = 3) -> Dict[str, List[int]]:
        """
        Identifies confirmed swing high and swing low indices using a symmetric lookback/lookahead window.
        """
        n = len(high)
        swing_highs = []
        swing_lows = []

        if n < (2 * window + 1):
            return {"swing_highs": [], "swing_lows": []}

        for i in range(window, n - window):
            # Swing High
            if np.all(high[i] >= high[i - window:i]) and np.all(high[i] >= high[i + 1:i + window + 1]):
                swing_highs.append(i)
            # Swing Low
            if np.all(low[i] <= low[i - window:i]) and np.all(low[i] <= low[i + 1:i + window + 1]):
                swing_lows.append(i)

        return {"swing_highs": swing_highs, "swing_lows": swing_lows}

    @staticmethod
    def detect_trend_structure(high: np.ndarray, low: np.ndarray) -> Dict[str, Any]:
        """
        Detects Higher Highs / Higher Lows (Bullish) or Lower Highs / Lower Lows (Bearish)
        """
        swings = PriceActionEngine.identify_swings(high, low, window=2)
        sh_idx = swings["swing_highs"]
        sl_idx = swings["swing_lows"]

        if len(sh_idx) < 2 or len(sl_idx) < 2:
            return {"structure": "CONSOLIDATING", "bias": "NEUTRAL", "bos": False}

        last_sh = high[sh_idx[-1]]
        prev_sh = high[sh_idx[-2]]
        last_sl = low[sl_idx[-1]]
        prev_sl = low[sl_idx[-2]]

        is_higher_high = last_sh > prev_sh
        is_higher_low = last_sl > prev_sl
        is_lower_high = last_sh < prev_sh
        is_lower_low = last_sl < prev_sl

        if is_higher_high and is_higher_low:
            return {
                "structure": "BULLISH_EXPANSION",
                "bias": "BULLISH",
                "bos": True,
                "detail": f"HH ({last_sh:.2f} > {prev_sh:.2f}) & HL ({last_sl:.2f} > {prev_sl:.2f})"
            }
        elif is_lower_high and is_lower_low:
            return {
                "structure": "BEARISH_EXPANSION",
                "bias": "BEARISH",
                "bos": True,
                "detail": f"LH ({last_sh:.2f} < {prev_sh:.2f}) & LL ({last_sl:.2f} < {prev_sl:.2f})"
            }
        else:
            return {
                "structure": "SIDEWAYS_RANGE",
                "bias": "NEUTRAL",
                "bos": False,
                "detail": "Mixed swing points without clean direction"
            }

    @staticmethod
    def analyze_candlestick(open_p: float, high: float, low: float, close: float) -> Dict[str, Any]:
        """
        Evaluates candle anatomy: body ratio, upper wick rejection, lower wick rejection.
        """
        total_range = high - low
        if total_range <= 0.0001:
            return {"type": "DOJI", "body_pct": 0, "bullish_rejection": False, "bearish_rejection": False}

        body = abs(close - open_p)
        upper_wick = high - max(open_p, close)
        lower_wick = min(open_p, close) - low

        body_ratio = body / total_range
        upper_wick_ratio = upper_wick / total_range
        lower_wick_ratio = lower_wick / total_range

        # Bullish rejection (Hammer / Pinbar): lower wick >= 50% of range, small body
        bullish_rejection = lower_wick_ratio >= 0.50 and body_ratio <= 0.35
        # Bearish rejection (Shooting star / Inverted pinbar): upper wick >= 50% of range
        bearish_rejection = upper_wick_ratio >= 0.50 and body_ratio <= 0.35

        pattern = "NEUTRAL"
        if bullish_rejection:
            pattern = "HAMMER_PINBAR"
        elif bearish_rejection:
            pattern = "SHOOTING_STAR"
        elif body_ratio >= 0.70:
            pattern = "BULLISH_MARUBOZU" if close > open_p else "BEARISH_MARUBOZU"
        elif body_ratio <= 0.15:
            pattern = "DOJI"

        return {
            "pattern": pattern,
            "body_ratio": round(body_ratio, 2),
            "upper_wick_ratio": round(upper_wick_ratio, 2),
            "lower_wick_ratio": round(lower_wick_ratio, 2),
            "bullish_rejection": bullish_rejection,
            "bearish_rejection": bearish_rejection,
        }
