"""
Step 7: c浪做空信号

4H级别识别下降趋势：
条件：H1 → L → H2(更低) → 跌破L
入场：跌破L的阴线（收盘<L 且 阴线 且 放量>1.2x）
确认：后续2根不收回L上方
止损：入场K线高点 + 0.5%
只对BTC和ETH做空
做空在4H级别直接入场（不做1H精准入场）
"""

import numpy as np
import pandas as pd
from dataclasses import dataclass
from typing import List

from .zigzag import zigzag
from .pipeline import Signal
from ..config import settings as S


@dataclass
class ShortSetup:
    """做空结构：H1 → L → H2(更低) → 跌破L"""
    h1_idx: int
    h1_price: float
    l_idx: int
    l_price: float
    h2_idx: int
    h2_price: float
    break_idx: int       # 跌破L的K线
    break_price: float   # 入场价（收盘价）
    entry_high: float    # 入场K线高点（用于止损）
    volume_ratio: float


def find_short_signals(
    coin: str,
    df_4h: pd.DataFrame,
) -> List[Signal]:
    """
    在4H级别寻找做空信号

    结构：H1 → L → H2(更低) → 跌破L
    """
    highs = df_4h['high'].values
    lows = df_4h['low'].values
    opens = df_4h['open'].values
    closes = df_4h['close'].values
    volumes = df_4h['volume'].values
    timestamps = df_4h['timestamp']
    n = len(closes)

    # 用4H ZigZag识别摆动点
    points = zigzag(highs, lows, S.ZIGZAG_THRESHOLD_4H)

    signals = []

    # 寻找 H → L → H(lower) 结构
    for i in range(len(points) - 2):
        idx1, type1, price1 = points[i]
        idx2, type2, price2 = points[i + 1]
        idx3, type3, price3 = points[i + 2]

        # 需要 H → L → H 且 H2 < H1
        if type1 != 'H' or type2 != 'L' or type3 != 'H':
            continue
        if price3 >= price1:
            continue  # H2必须更低

        support_level = price2  # L就是支撑位

        # 从H2往后扫描，找跌破L的阴线
        for j in range(idx3 + 1, min(idx3 + 60, n)):
            if closes[j] >= support_level:
                continue
            # 阴线
            if closes[j] >= opens[j]:
                continue
            # 放量 > 1.2x
            vol_start = max(0, j - 20)
            avg_vol = np.mean(volumes[vol_start:j]) if j > vol_start else volumes[j]
            if avg_vol == 0:
                continue
            vol_ratio = volumes[j] / avg_vol
            if vol_ratio < 1.2:
                continue

            # 确认：后续2根不收回L上方
            confirm_end = min(j + 3, n)
            confirmed = True
            for k in range(j + 1, confirm_end):
                if closes[k] > support_level:
                    confirmed = False
                    break

            if confirmed and (confirm_end - j - 1) >= 2:
                entry_price = closes[j]
                entry_high = highs[j]
                stop_loss = entry_high * (1 + S.SL_SHORT_OFFSET)
                sl_distance = (stop_loss - entry_price) / entry_price

                if sl_distance > S.SL_MAX_DISTANCE:
                    continue

                signals.append(Signal(
                    coin=coin,
                    direction='short',
                    signal_type='做空',
                    entry_time=timestamps.iloc[j],
                    entry_price=entry_price,
                    stop_loss=stop_loss,
                    sl_distance=sl_distance,
                    box_high=price1,      # H1作为参考
                    box_low=support_level,  # L作为支撑
                    box_width_pct=(price1 - support_level) / support_level,
                    box_duration_bars=idx3 - idx1,
                    volume_ratio=vol_ratio,
                    entry_method='4H直接',  # 做空直接入场
                ))
                break  # 每个结构只取第一个有效突破

    return signals
