#!/usr/bin/env python3
"""
信号历史数据库 - 记录所有交易信号
用法:
  python3 signal_db.py log '<原始信号文本>'
  python3 signal_db.py history [--trader NAME] [--symbol BTC] [--days 7] [--limit 20]
  python3 signal_db.py stats
  python3 signal_db.py traders
"""

import sqlite3
import os
import re
import json
import sys
import time
from datetime import datetime, timedelta

DB_PATH = os.path.expanduser("~/.hermes/trading/signal_history.db")

def get_conn():
    os.makedirs(os.path.dirname(DB_PATH), exist_ok=True)
    conn = sqlite3.connect(DB_PATH)
    conn.row_factory = sqlite3.Row
    return conn

def init_db():
    conn = get_conn()
    conn.execute("""
        CREATE TABLE IF NOT EXISTS signals (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            timestamp REAL NOT NULL,
            time_str TEXT NOT NULL,
            trader TEXT,
            symbol TEXT,
            side TEXT,
            leverage INTEGER,
            raw_size REAL,
            raw_unit TEXT,
            entry_price REAL,
            current_price REAL,
            margin REAL,
            margin_unit TEXT,
            margin_mode TEXT,
            pnl REAL,
            pnl_pct REAL,
            leverage_change TEXT,
            raw_text TEXT NOT NULL,
            outcome TEXT DEFAULT 'pending',
            outcome_time REAL,
            outcome_detail TEXT
        )
    """)
    conn.execute("""
        CREATE INDEX IF NOT EXISTS idx_signals_time ON signals(timestamp DESC)
    """)
    conn.execute("""
        CREATE INDEX IF NOT EXISTS idx_signals_trader ON signals(trader)
    """)
    conn.execute("""
        CREATE INDEX IF NOT EXISTS idx_signals_symbol ON signals(symbol)
    """)
    conn.commit()
    conn.close()

def extract_trader(text):
    """Extract trader name from signal text.
    
    Common patterns:
    - 【熬鹰资本】 (standalone 【name】 on its own line, no colon)
    - 【交易员】xxx
    - 【老师】xxx  
    - 交易员: xxx
    - 来自xxx:
    - [xxx] at the beginning
    - @username
    - Name followed by colon (e.g. "张三: BTC做多")
    - Name followed by signal keywords
    """
    # Priority 1: Standalone 【name】 on its own line (no colon after)
    # This matches 【熬鹰资本】 but NOT 【币种】: xxx
    standalone = re.search(r'^【([^】]{1,20})】\s*$', text, re.MULTILINE)
    if standalone:
        return standalone.group(1).strip()
    
    patterns = [
        r'【交易员】\s*(.+?)(?:\n|$|【)',
        r'【老师】\s*(.+?)(?:\n|$|【)',
        r'【来源】\s*(.+?)(?:\n|$|【)',
        r'【策略】\s*(.+?)(?:\n|$|【)',
        r'交易员[：:]\s*(.+?)(?:\n|$)',
        r'老师[：:]\s*(.+?)(?:\n|$)',
        r'来源[：:]\s*(.+?)(?:\n|$)',
        r'策略师[：:]\s*(.+?)(?:\n|$)',
        r'^\[([^\]]+)\]',  # [TraderName] at start
        r'^(@\w+)',  # @username at start
        r'^(\S+?)\s*[:：]\s*(?:【|BTC|ETH|做多|做空|开多|开空)',  # Name: signal
        r'^(\S{2,10})\s+(?:【|BTC|ETH|做多|做空|开多|开空)',  # Name signal (no colon)
    ]
    for p in patterns:
        m = re.search(p, text, re.MULTILINE)
        if m:
            name = m.group(1).strip()
            # Filter out non-name matches
            if len(name) > 1 and len(name) < 30 and not re.match(r'^[\d.]+$', name):
                return name
    return None

def extract_signal_fields(text):
    """Parse signal text for key fields."""
    result = {'trader': extract_trader(text)}
    
    # Symbol - multiple patterns
    m = re.search(r'(?:【币种】|币种[：:]\s*)(\w+)', text)
    if not m:
        m = re.search(r'([A-Z]{2,10})USDT', text)
    if not m:
        # Bare symbol before direction keywords (e.g. "ETH做空", "BTC 开多")
        m = re.search(r'\b([A-Z]{2,10})\s*(?:做多|做空|开多|开空|做多|做空|long|short)', text, re.IGNORECASE)
    if m:
        raw = m.group(1).upper().replace("USDT", "").replace("/USDT", "").replace(":USDT", "")
        if len(raw) >= 2:
            result['symbol'] = raw
    
    # Side
    if re.search(r'(做空|卖出|short|sell|空单|开空)', text, re.IGNORECASE):
        result['side'] = 'short'
    elif re.search(r'(做多|买入|long|buy|多单|开多)', text, re.IGNORECASE):
        result['side'] = 'long'
    
    # Leverage from field
    m = re.search(r'(?:【币种】|币种[：:]\s*)[^\n]*?(\d+)\s*[xX倍]', text)
    if not m:
        m = re.search(r'(\d+)\s*[xX倍]', text)
    result['leverage'] = int(m.group(1)) if m else None
    
    # Size
    m = re.search(r'(?:【仓位】|仓位[：:]\s*)([\d,.]+)\s*(\w+)', text)
    if m:
        result['raw_size'] = float(m.group(1).replace(",", ""))
        result['raw_unit'] = m.group(2)
    
    # Entry price
    m = re.search(r'【开仓价】\s*[:：]?\s*([\d,.]+)', text)
    if m:
        result['entry_price'] = float(m.group(1).replace(",", ""))
    
    # Current price
    m = re.search(r'【当前价】\s*[:：]?\s*([\d,.]+)', text)
    if m:
        result['current_price'] = float(m.group(1).replace(",", ""))
    
    # Margin
    m = re.search(r'【保证金】\s*[:：]?\s*([\d,.]+)\s*(\w+)', text)
    if m:
        result['margin'] = float(m.group(1).replace(",", ""))
        result['margin_unit'] = m.group(2)
    
    # Margin mode (全仓/逐仓)
    m = re.search(r'(全仓|逐仓)', text)
    if m:
        result['margin_mode'] = m.group(1)
    
    # PnL
    m = re.search(r'【收益额】\s*[:：]?\s*([-\d,.]+)\s*(\w+)', text)
    if m:
        result['pnl'] = float(m.group(1).replace(",", ""))
    m = re.search(r'【收益额】\s*[:：]?\s*[-\d,.]+\s*\w+\(([-\d.]+)%\)', text)
    if m:
        result['pnl_pct'] = float(m.group(1))
    
    # Leverage change (e.g. "5→10")
    m = re.search(r'修改了杠杆\s*(\d+)\s*[→>→]\s*(\d+)', text)
    if m:
        result['leverage_change'] = f"{m.group(1)}→{m.group(2)}"
    
    # Is close signal
    result['is_close'] = bool(re.search(r'(平仓|止盈|止损|close|全平)', text, re.IGNORECASE))
    
    return result
    

def log_signal(raw_text):
    """Log a signal to the database."""
    init_db()
    fields = extract_signal_fields(raw_text)
    
    conn = get_conn()
    now = time.time()
    time_str = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    
    conn.execute("""
        INSERT INTO signals (timestamp, time_str, trader, symbol, side, leverage, 
                           raw_size, raw_unit, entry_price, current_price,
                           margin, margin_unit, margin_mode, pnl, pnl_pct,
                           leverage_change, raw_text)
        VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
    """, (
        now, time_str,
        fields.get('trader'),
        fields.get('symbol'),
        fields.get('side'),
        fields.get('leverage'),
        fields.get('raw_size'),
        fields.get('raw_unit'),
        fields.get('entry_price'),
        fields.get('current_price'),
        fields.get('margin'),
        fields.get('margin_unit'),
        fields.get('margin_mode'),
        fields.get('pnl'),
        fields.get('pnl_pct'),
        fields.get('leverage_change'),
        raw_text,
    ))
    signal_id = conn.execute("SELECT last_insert_rowid()").fetchone()[0]
    conn.commit()
    conn.close()
    
    return {
        'id': signal_id,
        'time': time_str,
        'trader': fields.get('trader'),
        'symbol': fields.get('symbol'),
        'side': fields.get('side'),
        'leverage': fields.get('leverage'),
    }

def update_outcome(signal_id, outcome, detail=""):
    """Update signal outcome (confirmed/cancelled/expired)."""
    conn = get_conn()
    conn.execute("""
        UPDATE signals SET outcome=?, outcome_time=?, outcome_detail=?
        WHERE id=?
    """, (outcome, time.time(), detail, signal_id))
    conn.commit()
    conn.close()

def find_latest_signal_id(symbol):
    """Find the most recent pending signal ID for a symbol."""
    conn = get_conn()
    row = conn.execute("""
        SELECT id FROM signals WHERE symbol=? AND outcome='pending'
        ORDER BY timestamp DESC LIMIT 1
    """, (symbol,)).fetchone()
    conn.close()
    return row['id'] if row else None

def query_history(trader=None, symbol=None, days=7, limit=20):
    """Query signal history with filters."""
    init_db()
    conn = get_conn()
    
    conditions = ["timestamp > ?"]
    params = [time.time() - days * 86400]
    
    if trader:
        conditions.append("trader LIKE ?")
        params.append(f"%{trader}%")
    if symbol:
        conditions.append("symbol LIKE ?")
        params.append(f"%{symbol}%")
    
    where = " AND ".join(conditions)
    rows = conn.execute(f"""
        SELECT * FROM signals WHERE {where}
        ORDER BY timestamp DESC LIMIT ?
    """, params + [limit]).fetchall()
    conn.close()
    return [dict(r) for r in rows]

def get_trader_stats():
    """Get stats per trader."""
    init_db()
    conn = get_conn()
    rows = conn.execute("""
        SELECT 
            trader,
            COUNT(*) as total,
            SUM(CASE WHEN outcome='confirmed' THEN 1 ELSE 0 END) as confirmed,
            SUM(CASE WHEN outcome='cancelled' THEN 1 ELSE 0 END) as cancelled,
            SUM(CASE WHEN outcome='pending' THEN 1 ELSE 0 END) as pending,
            SUM(CASE WHEN outcome='expired' THEN 1 ELSE 0 END) as expired,
            GROUP_CONCAT(DISTINCT symbol) as symbols
        FROM signals
        GROUP BY trader
        ORDER BY total DESC
    """).fetchall()
    conn.close()
    return [dict(r) for r in rows]

def get_summary_stats():
    """Get overall summary stats."""
    init_db()
    conn = get_conn()
    
    total = conn.execute("SELECT COUNT(*) as c FROM signals").fetchone()['c']
    today = conn.execute(
        "SELECT COUNT(*) as c FROM signals WHERE timestamp > ?",
        (time.time() - 86400,)
    ).fetchone()['c']
    
    by_outcome = conn.execute("""
        SELECT outcome, COUNT(*) as c FROM signals GROUP BY outcome
    """).fetchall()
    
    by_side = conn.execute("""
        SELECT side, COUNT(*) as c FROM signals WHERE side IS NOT NULL GROUP BY side
    """).fetchall()
    
    top_symbols = conn.execute("""
        SELECT symbol, COUNT(*) as c FROM signals 
        WHERE symbol IS NOT NULL
        GROUP BY symbol ORDER BY c DESC LIMIT 5
    """).fetchall()
    
    conn.close()
    return {
        'total': total,
        'today': today,
        'by_outcome': {r['outcome']: r['c'] for r in by_outcome},
        'by_side': {r['side']: r['c'] for r in by_side},
        'top_symbols': [(r['symbol'], r['c']) for r in top_symbols],
    }


def format_history(signals):
    """Format history for display."""
    if not signals:
        return "📭 暂无信号记录"
    
    lines = ["📋 **信号历史记录**\n"]
    for s in signals:
        side_cn = "做多" if s['side'] == 'long' else ("做空" if s['side'] == 'short' else "?")
        outcome_emoji = {
            'confirmed': '✅', 'cancelled': '❌', 'pending': '⏳', 'expired': '⏰'
        }.get(s['outcome'], '❓')
        trader = s['trader'] or '未知'
        lev = f"{s['leverage']}x" if s['leverage'] else '?x'
        
        # Extra info
        extra = []
        if s.get('entry_price'):
            extra.append(f"入场{s['entry_price']}")
        if s.get('pnl'):
            pnl_str = f"{s['pnl']:+,.0f}"
            if s.get('pnl_pct'):
                pnl_str += f"({s['pnl_pct']:+.1f}%)"
            extra.append(f"盈亏{pnl_str}")
        if s.get('margin'):
            extra.append(f"保证金{s['margin']:,.0f}")
        if s.get('margin_mode'):
            extra.append(s['margin_mode'])
        if s.get('leverage_change'):
            extra.append(f"杠杆{s['leverage_change']}")
        
        extra_str = " | " + " ".join(extra) if extra else ""
        
        lines.append(
            f"{outcome_emoji} #{s['id']} | {s['time_str']} | "
            f"👤{trader} | {s['symbol'] or '?'} {side_cn} | "
            f"{lev}{extra_str}"
        )
    
    return "\n".join(lines)


def format_stats(stats):
    """Format stats for display."""
    lines = ["📊 **信号统计**\n"]
    lines.append(f"总计: {stats['total']} 条")
    lines.append(f"今日: {stats['today']} 条\n")
    
    if stats['by_outcome']:
        lines.append("**按结果:**")
        for k, v in stats['by_outcome'].items():
            emoji = {'confirmed': '✅', 'cancelled': '❌', 'pending': '⏳', 'expired': '⏰'}.get(k, '❓')
            lines.append(f"  {emoji} {k}: {v}")
    
    if stats['by_side']:
        lines.append("\n**按方向:**")
        for k, v in stats['by_side'].items():
            cn = "做多" if k == 'long' else "做空"
            lines.append(f"  {cn}: {v}")
    
    if stats['top_symbols']:
        lines.append("\n**热门币种:**")
        for sym, cnt in stats['top_symbols']:
            lines.append(f"  {sym}: {cnt}次")
    
    return "\n".join(lines)


def format_traders(traders):
    """Format trader stats for display."""
    if not traders:
        return "📭 暂无交易员数据"
    
    lines = ["👤 **交易员统计**\n"]
    for t in traders:
        name = t['trader'] or '未知'
        lines.append(
            f"**{name}**: {t['total']}条信号 | "
            f"✅{t['confirmed']} ❌{t['cancelled']} ⏳{t['pending']} | "
            f"币种: {t['symbols'] or '-'}"
        )
    
    return "\n".join(lines)


def main():
    if len(sys.argv) < 2:
        print("用法: signal_db.py <log|history|stats|traders|update> [args]")
        sys.exit(1)
    
    action = sys.argv[1]
    
    if action == "log":
        if len(sys.argv) < 3:
            print("用法: signal_db.py log '<raw_text>'")
            sys.exit(1)
        raw_text = sys.argv[2]
        result = log_signal(raw_text)
        print(json.dumps(result, ensure_ascii=False))
    
    elif action == "history":
        import argparse
        # Simple arg parsing
        trader = symbol = None
        days = 7
        limit = 20
        for i in range(2, len(sys.argv)):
            if sys.argv[i] == "--trader" and i + 1 < len(sys.argv):
                trader = sys.argv[i + 1]
            elif sys.argv[i] == "--symbol" and i + 1 < len(sys.argv):
                symbol = sys.argv[i + 1]
            elif sys.argv[i] == "--days" and i + 1 < len(sys.argv):
                days = int(sys.argv[i + 1])
            elif sys.argv[i] == "--limit" and i + 1 < len(sys.argv):
                limit = int(sys.argv[i + 1])
        signals = query_history(trader, symbol, days, limit)
        print(format_history(signals))
    
    elif action == "stats":
        stats = get_summary_stats()
        print(format_stats(stats))
    
    elif action == "traders":
        traders = get_trader_stats()
        print(format_traders(traders))
    
    elif action == "update":
        if len(sys.argv) < 4:
            print("用法: signal_db.py update <signal_id> <outcome> [detail]")
            sys.exit(1)
        signal_id = int(sys.argv[2])
        outcome = sys.argv[3]
        detail = sys.argv[4] if len(sys.argv) > 4 else ""
        update_outcome(signal_id, outcome, detail)
        print(f"✅ Updated signal #{signal_id} → {outcome}")
    
    else:
        print(f"Unknown action: {action}")
        sys.exit(1)


if __name__ == "__main__":
    main()
