# ============================================================
# JQ量化跟单系统 7.0 — 信号发送模块
# 上传到聚宽研究环境
# ============================================================
import requests, time, uuid

SERVER = 'https://api.588gs.cn/api/v7/signal/receive'

def _send(result, token, name, long_short=1, run_type='live'):
    if result is None:
        return result
    try:
        stock = str(getattr(result, 'security', '') or '')
        qty   = int(getattr(result, 'amount', 0) or 0)
        if not stock or qty == 0:
            return result
        signal = {
            'signal_id':    str(getattr(result, 'order_id', '') or uuid.uuid4()),
            'stock_code':   stock,
            'direction':    1 if getattr(result, 'is_buy', True) else 2,
            'signal_price': float(getattr(result, 'price',       0) or 0),
            'signal_qty':   abs(qty),
            'filled_qty':   int(getattr(result,   'filled',      0) or 0),
            'filled_price': float(getattr(result, 'price',       0) or 0),
            'cost_price':   float(getattr(result, 'avg_cost',    0) or 0),
            'commission':   float(getattr(result, 'commission',  0) or 0),
            'order_status': str(getattr(result,   'status',     '') or ''),
            'long_short':   long_short,
            'signal_time':  str(getattr(result,   'add_time',   '') or time.strftime('%Y-%m-%d %H:%M:%S')),
            'run_type':     run_type,
        }
        r    = requests.post(SERVER, json=signal, timeout=5,
                             headers={'Authorization': f'Bearer {token}',
                                      'Content-Type': 'application/json'})
        resp = r.json()
        ok   = resp.get('code') == 0
        tag  = '' if run_type == 'live' else '[回测]'
        print(f'交易信号发送 - {"成功" if ok else "失败"} [{name}]{tag} {stock} | {resp}')
    except Exception as e:
        print(f'交易信号发送 - 失败 [{name}] {e}')
    return result


class JQStock:
    def __init__(self, token, name, _order, _order_target, _order_value, _order_target_value, run_type='live'):
        self.token    = token
        self.name     = name or token[:8]
        self.run_type = run_type
        self._order              = _order
        self._order_target       = _order_target
        self._order_value        = _order_value
        self._order_target_value = _order_target_value

    def order(self, security, amount, style=None):
        return _send(self._order(security, amount, style=style), self.token, self.name, run_type=self.run_type)

    def order_target(self, security, amount, style=None):
        return _send(self._order_target(security, amount, style=style), self.token, self.name, run_type=self.run_type)

    def order_value(self, security, value, style=None):
        return _send(self._order_value(security, value, style=style), self.token, self.name, run_type=self.run_type)

    def order_target_value(self, security, value, style=None):
        return _send(self._order_target_value(security, value, style=style), self.token, self.name, run_type=self.run_type)


class JQStockMulti:
    def __init__(self, clients, _order, _order_target, _order_value, _order_target_value, run_type='live'):
        self._clients            = clients
        self.run_type            = run_type
        self._order              = _order
        self._order_target       = _order_target
        self._order_value        = _order_value
        self._order_target_value = _order_target_value

    def _broadcast(self, result):
        for c in self._clients:
            _send(result, c['token'], c['name'], run_type=self.run_type)
        return result

    def order(self, security, amount, style=None):
        return self._broadcast(self._order(security, amount, style=style))

    def order_target(self, security, amount, style=None):
        return self._broadcast(self._order_target(security, amount, style=style))

    def order_value(self, security, value, style=None):
        return self._broadcast(self._order_value(security, value, style=style))

    def order_target_value(self, security, value, style=None):
        return self._broadcast(self._order_target_value(security, value, style=style))


def wrap_stock(token='', name='', clients=None, run_type='live',
               _order=None, _order_target=None, _order_value=None, _order_target_value=None):
    if clients:
        jq = JQStockMulti(clients, _order, _order_target, _order_value, _order_target_value, run_type)
    else:
        jq = JQStock(token=token, name=name, run_type=run_type,
                     _order=_order, _order_target=_order_target,
                     _order_value=_order_value, _order_target_value=_order_target_value)
    return jq.order, jq.order_target, jq.order_value, jq.order_target_value
