"""
性价比检查模块
供 okx_position_advisor.py 调用
"""

import os, sys
sys.path.insert(0, os.path.dirname(__file__))
from config_loader import get as cfg

def get_okx_fee_rate(inst_type='SWAP'):
    """
    从OKX API获取实际费率
    返回: (maker_rate, taker_rate) 正数表示收费，负数表示返佣
    """
    import requests, hmac, hashlib, base64, time, os, re
    
    # 读取凭证
    creds = {}
    with open(os.path.expanduser("~/.bashrc")) as f:
        for line in f:
            m = re.match(r'export\s+(OKX_\w+)=(.*)', line.strip())
            if m:
                val = m.group(2).strip().strip('"').strip("'")
                creds[m.group(1)] = val
    
    api_key = creds.get('OKX_API_KEY', '')
    secret = creds.get('OKX_SECRET', '')
    passphrase = creds.get('OKX_PASSPHRASE', '')
    
    proxies = {"http": "http://127.0.0.1:7890", "https": "http://127.0.0.1:7890"}
    
    ts = time.strftime("%Y-%m-%dT%H:%M:%S.000Z", time.gmtime())
    path = f"/api/v5/account/trade-fee?instType={inst_type}"
    msg = f"{ts}GET{path}"
    sig = hmac.new(secret.encode(), msg.encode(), hashlib.sha256).digest()
    sig_b64 = base64.b64encode(sig).decode()
    
    headers = {
        "OK-ACCESS-KEY": api_key,
        "OK-ACCESS-SIGN": sig_b64,
        "OK-ACCESS-TIMESTAMP": ts,
        "OK-ACCESS-PASSPHRASE": passphrase,
    }
    
    try:
        r = requests.get(f"https://www.okx.com{path}", headers=headers, proxies=proxies, timeout=15)
        data = r.json()
        if data['code'] == '0' and data['data']:
            maker = float(data['data'][0]['maker'])
            taker = float(data['data'][0]['taker'])
            return maker, taker
    except Exception as e:
        pass
    
    # 默认费率 (fallback)
    return 0.0002, 0.0005


def calc_cost_performance(entry_price, sl_price, tp_price, contracts, ct_val, leverage, fee_rate=None):
    """
    计算开仓性价比
    
    参数:
        entry_price: 入场价
        sl_price: 止损价
        tp_price: 止盈价
        contracts: 合约张数
        ct_val: 合约面值 (如ETH=0.1)
        leverage: 杠杆倍数
        fee_rate: 单边手续费率 (默认从OKX API获取)
    
    返回:
        dict: {
            'rr_ratio': 盈亏比,
            'tp_distance': TP距离,
            'sl_distance': SL距离,
            'profit_amount': 盈利金额(USDT),
            'loss_amount': 亏损金额(USDT),
            'fee_cost': 手续费(USDT),
            'fee_pct': 手续费占盈利百分比,
            'rating': 'high'/'medium'/'low',
            'rating_emoji': '✅'/'⚠️'/'❌',
            'rating_text': '性价比高'/'性价比一般'/'性价比低',
            'auto_execute': True/False,
            'reason': 原因说明
        }
    """
    # 如果没有传入费率，从OKX API获取
    if fee_rate is None:
        maker_rate, taker_rate = get_okx_fee_rate()
        # 用taker费率（市价单）- 可能是负数（返佣）
        fee_rate = taker_rate
    if fee_rate is None:
        fee_rate = cfg('cost_performance', 'fee_rate', 0.0005)
    # 计算距离
    tp_distance = abs(tp_price - entry_price)
    sl_distance = abs(sl_price - entry_price)
    
    # 防止除零
    if sl_distance == 0:
        return {
            'rr_ratio': 0,
            'tp_distance': tp_distance,
            'sl_distance': sl_distance,
            'profit_amount': 0,
            'loss_amount': 0,
            'fee_cost': 0,
            'fee_pct': 100,
            'rating': 'low',
            'rating_emoji': '❌',
            'rating_text': '性价比低',
            'auto_execute': False,
            'reason': '止损距离为0'
        }
    
    # 盈亏比
    rr_ratio = tp_distance / sl_distance
    
    # 盈亏金额
    position_size = contracts * ct_val
    profit_amount = tp_distance * position_size
    loss_amount = sl_distance * position_size
    
    # 手续费 (开+平, 含杠杆)
    # 注意：fee_rate可能是负数（返佣），此时fee_cost也是负数（即赚手续费）
    notional_value = entry_price * position_size
    fee_cost = notional_value * fee_rate * 2  # 手续费基于名义价值，不乘杠杆
    
    # 手续费占盈利百分比（返佣时为负数，表示额外收益）
    if profit_amount > 0:
        fee_pct = (fee_cost / profit_amount * 100)
    else:
        fee_pct = 100 if fee_cost >= 0 else -100
    
    # 性价比评级
    # 注意：返佣时fee_pct为负数，表示额外收益，应该提高评级
    reasons = []
    
    # 计算净盈利（盈利 + 返佣 或 盈利 - 手续费）
    net_profit = profit_amount + fee_cost  # fee_cost为负时是返佣，为正时是收费
    
    rr_high = cfg('cost_performance', 'rr_high', 2.0)
    rr_medium = cfg('cost_performance', 'rr_medium', 1.5)
    fee_high = cfg('cost_performance', 'fee_high_pct', 10)
    fee_medium = cfg('cost_performance', 'fee_medium_pct', 5)
    min_profit = cfg('position_sizing', 'min_profit_usdt', 10)

    if rr_ratio >= rr_high and net_profit >= min_profit:
        # 盈亏比达标 且 净盈利达标
        if fee_pct < 0:  # 返佣
            rating = 'high'
            rating_emoji = '✅'
            rating_text = '性价比高'
            auto_execute = True
        elif fee_pct < fee_medium:  # 低费率
            rating = 'high'
            rating_emoji = '✅'
            rating_text = '性价比高'
            auto_execute = True
        else:  # 高费率
            rating = 'medium'
            rating_emoji = '⚠️'
            rating_text = '性价比一般'
            auto_execute = False
    elif rr_ratio >= rr_medium and net_profit >= min_profit:
        rating = 'medium'
        rating_emoji = '⚠️'
        rating_text = '性价比一般'
        auto_execute = False
    else:
        rating = 'low'
        rating_emoji = '❌'
        rating_text = '性价比低'
        auto_execute = False
    
    # 具体原因
    if rr_ratio < rr_medium:
        reasons.append(f'盈亏比{rr_ratio:.1f}:1<1.5:1')
    elif rr_ratio < rr_high:
        reasons.append(f'盈亏比{rr_ratio:.1f}:1偏低')
    
    if fee_pct > fee_high:
        reasons.append(f'手续费占比{fee_pct:.0f}%过高')
    elif fee_pct > fee_medium:
        reasons.append(f'手续费占比{fee_pct:.0f}%偏高')
    elif fee_pct < 0:
        reasons.append(f'返佣{abs(fee_pct):.0f}%')
    
    if net_profit < min_profit:
        reasons.append(f'净盈利{net_profit:.1f}USDT<5USDT')
    
    reason = '; '.join(reasons) if reasons else ('盈亏比≥2:1, 手续费合理, 盈利达标' if rating == 'high' else '')
    
    return {
        'rr_ratio': round(rr_ratio, 2),
        'tp_distance': round(tp_distance, 4),
        'sl_distance': round(sl_distance, 4),
        'profit_amount': round(profit_amount, 2),
        'loss_amount': round(loss_amount, 2),
        'fee_cost': round(fee_cost, 2),
        'fee_pct': round(fee_pct, 2),
        'net_profit': round(net_profit, 2),  # 新增：净盈利
        'rating': rating,
        'rating_emoji': rating_emoji,
        'rating_text': rating_text,
        'auto_execute': auto_execute,
        'reason': reason
    }


def calc_min_contracts_for_profit(tp_distance, ct_val, min_profit=None):
    if min_profit is None:
        min_profit = cfg('position_sizing', 'min_profit_usdt', 10)
    """
    计算达到最小盈利所需的合约张数
    
    参数:
        tp_distance: TP距离
        ct_val: 合约面值
        min_profit: 最小盈利额 (默认10USDT)
    
    返回:
        int: 需要的合约张数 (向上取整)
    """
    if tp_distance <= 0 or ct_val <= 0:
        return 0
    
    # 盈利 = tp_distance * ct_val * contracts
    # contracts = min_profit / (tp_distance * ct_val)
    raw_contracts = min_profit / (tp_distance * ct_val)
    
    # 向上取整到lot_sz (这里先取整，外面再处理)
    import math
    return math.ceil(raw_contracts)


# 测试
if __name__ == '__main__':
    # 测试案例1: 性价比高
    check1 = calc_cost_performance(
        entry_price=1700,
        sl_price=1666,
        tp_price=1775,
        contracts=6,
        ct_val=0.1,
        leverage=25
    )
    print("测试1 - ETH做多 (性价比高):")
    print(f"  盈亏比: {check1['rr_ratio']}:1")
    print(f"  盈利: {check1['profit_amount']} USDT")
    print(f"  手续费: {check1['fee_cost']} USDT ({check1['fee_pct']}%)")
    print(f"  评级: {check1['rating_text']}")
    print(f"  自动开仓: {check1['auto_execute']}")
    print()
    
    # 测试案例2: 性价比低 (盈利<5USDT)
    check2 = calc_cost_performance(
        entry_price=67.21,
        sl_price=70.57,
        tp_price=63.85,
        contracts=1,
        ct_val=0.1,
        leverage=10
    )
    print("测试2 - HYPE做空 (盈利<5USDT):")
    print(f"  盈亏比: {check2['rr_ratio']}:1")
    print(f"  盈利: {check2['profit_amount']} USDT")
    print(f"  手续费: {check2['fee_cost']} USDT ({check2['fee_pct']}%)")
    print(f"  评级: {check2['rating_text']}")
    print(f"  原因: {check2['reason']}")
    print(f"  自动开仓: {check2['auto_execute']}")
    print()
    
    # 测试案例3: 计算最小张数
    min_contracts = calc_min_contracts_for_profit(
        tp_distance=3.36,
        ct_val=0.1,
        min_profit=10
    )
    print(f"测试3 - HYPE最小张数: {min_contracts}张 (盈利={3.36*0.1*min_contracts:.1f}USDT)")
