#!/usr/bin/env python3
"""
Feed Hunter Position Monitor
Checks current prices for active simulation positions and updates P&L

Usage:
    python3 monitor-positions.py [--update] [--alert-threshold 0.1]
"""

import argparse
import json
import os
import re
import time
from datetime import datetime, timezone
from urllib.parse import urlparse
import urllib.request
import urllib.error

# Price sources for different asset types
PRICE_SOURCES = {
    'polymarket': {
        'url_pattern': r'polymarket\.com.*?(@[\w]+|markets?[\w/-]+)',
        'api_base': 'https://gamma-api.polymarket.com/markets',
        'method': 'polymarket_api'
    },
    'crypto': {
        'url_pattern': r'(bitcoin|btc|ethereum|eth|solana|sol|cardano|ada)',
        'api_base': 'https://api.coingecko.com/api/v3/simple/price',
        'method': 'coingecko_api'
    },
    'stock': {
        'url_pattern': r'(nasdaq|nyse|stock)',
        'api_base': 'https://api.example.com/stock',  # Placeholder
        'method': 'stock_api'
    }
}

def detect_asset_type(position):
    """Detect what type of asset this position represents"""
    asset = position.get('asset', '').lower()
    source_url = position.get('source_post', '')
    strategy = position.get('strategy', '').lower()
    
    # Check if it's a prediction market
    if 'polymarket' in source_url or 'polymarket' in asset or 'polymarket' in strategy:
        return 'polymarket'
    elif 'super bowl' in asset or 'win' in asset or 'seahawks' in asset:
        return 'polymarket'  # Sports bets are usually prediction markets
    elif any(crypto in asset for crypto in ['btc', 'eth', 'sol', 'bitcoin', 'ethereum', 'solana']):
        return 'crypto'
    elif any(stock in asset for stock in ['stock', 'nasdaq', 'nyse', 'spy', 'tsla']):
        return 'stock'
    else:
        return 'unknown'

def get_polymarket_price(position):
    """Get current price from Polymarket API"""
    try:
        # Extract market info from source URL or asset name
        source_url = position.get('source_post', '')
        asset = position.get('asset', '')
        
        # For now, return mock price update
        # In real implementation, would parse URL and call Polymarket API
        if 'seahawks' in asset.lower() and 'super bowl' in asset.lower():
            # Mock price movement for Seahawks Super Bowl bet
            import random
            # Simulate some price movement around entry price
            entry_price = position.get('entry_price', 0.68)
            price_change = random.uniform(-0.05, 0.05)
            new_price = max(0.01, min(0.99, entry_price + price_change))
            return {
                'success': True,
                'price': round(new_price, 2),
                'timestamp': datetime.now(timezone.utc).isoformat(),
                'source': 'polymarket_mock'
            }
    except Exception as e:
        print(f"Polymarket price fetch error: {e}")
    
    return {'success': False, 'error': 'Price fetch failed'}

def get_crypto_price(position):
    """Get crypto price from CoinGecko"""
    try:
        asset = position.get('asset', '').lower()
        
        # Map asset names to CoinGecko IDs
        coin_map = {
            'bitcoin': 'bitcoin',
            'btc': 'bitcoin',
            'ethereum': 'ethereum',
            'eth': 'ethereum',
            'solana': 'solana',
            'sol': 'solana'
        }
        
        coin_id = None
        for name, id in coin_map.items():
            if name in asset:
                coin_id = id
                break
        
        if not coin_id:
            return {'success': False, 'error': 'Unknown crypto asset'}
        
        url = f"https://api.coingecko.com/api/v3/simple/price?ids={coin_id}&vs_currencies=usd"
        with urllib.request.urlopen(url, timeout=10) as response:
            data = json.loads(response.read().decode())
            
        price = data[coin_id]['usd']
        return {
            'success': True,
            'price': price,
            'timestamp': datetime.now(timezone.utc).isoformat(),
            'source': 'coingecko'
        }
        
    except Exception as e:
        print(f"Crypto price fetch error: {e}")
        return {'success': False, 'error': str(e)}

def get_stock_price(position):
    """Get stock price (placeholder - would need real API)"""
    # Placeholder for stock price API
    return {'success': False, 'error': 'Stock price API not implemented'}

def get_current_price(position):
    """Get current price for a position based on asset type"""
    asset_type = detect_asset_type(position)
    
    if asset_type == 'polymarket':
        return get_polymarket_price(position)
    elif asset_type == 'crypto':
        return get_crypto_price(position)
    elif asset_type == 'stock':
        return get_stock_price(position)
    else:
        return {'success': False, 'error': f'Unknown asset type: {asset_type}'}

def calculate_pnl(position, current_price):
    """Calculate P&L for a position"""
    entry_price = position.get('entry_price', 0)
    quantity = position.get('quantity', 0)
    size = position.get('size', 0)
    position_type = position.get('type', 'long')
    
    if position_type == 'bet':
        # For prediction market bets (binary outcome)
        # P&L = quantity * (current_price - entry_price)
        unrealized_pnl = quantity * (current_price - entry_price)
        unrealized_pnl_pct = ((current_price / entry_price) - 1) * 100 if entry_price > 0 else 0
    else:
        # For regular long positions
        # P&L = size * (current_price / entry_price - 1)
        unrealized_pnl = size * (current_price / entry_price - 1) if entry_price > 0 else 0
        unrealized_pnl_pct = ((current_price / entry_price) - 1) * 100 if entry_price > 0 else 0
    
    return {
        'unrealized_pnl': round(unrealized_pnl, 2),
        'unrealized_pnl_pct': round(unrealized_pnl_pct, 2),
        'current_price': current_price
    }

def check_stop_loss_take_profit(position, current_price):
    """Check if position hits stop loss or take profit"""
    stop_loss = position.get('stop_loss')
    take_profit = position.get('take_profit')
    
    triggers = []
    
    if stop_loss and current_price <= stop_loss:
        triggers.append({
            'type': 'stop_loss',
            'trigger_price': stop_loss,
            'current_price': current_price,
            'message': f"STOP LOSS triggered at {current_price} (target: {stop_loss})"
        })
    
    if take_profit and current_price >= take_profit:
        triggers.append({
            'type': 'take_profit',
            'trigger_price': take_profit,
            'current_price': current_price,
            'message': f"TAKE PROFIT triggered at {current_price} (target: {take_profit})"
        })
    
    return triggers

def load_active_positions():
    """Load active positions from JSON file"""
    positions_file = 'data/simulations/active.json'
    
    if not os.path.exists(positions_file):
        return None
    
    try:
        with open(positions_file, 'r') as f:
            return json.load(f)
    except Exception as e:
        print(f"Error loading positions: {e}")
        return None

def save_active_positions(data):
    """Save updated positions to JSON file"""
    positions_file = 'data/simulations/active.json'
    
    try:
        with open(positions_file, 'w') as f:
            json.dump(data, f, indent=2)
        return True
    except Exception as e:
        print(f"Error saving positions: {e}")
        return False

def send_alert(position, trigger_info, pnl_info):
    """Send alert about position trigger (placeholder)"""
    print(f"🚨 ALERT: {trigger_info['message']}")
    print(f"   Position: {position['asset'][:50]}...")
    print(f"   P&L: ${pnl_info['unrealized_pnl']:.2f} ({pnl_info['unrealized_pnl_pct']:+.1f}%)")
    print(f"   Strategy: {position.get('strategy', 'Unknown')}")
    print("")

def monitor_positions(update=False, alert_threshold=0.1):
    """Monitor all active positions"""
    print("🖤 Feed Hunter - Position Monitor")
    print(f"Time: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
    print("")
    
    # Load active positions
    data = load_active_positions()
    if not data:
        print("❌ No active positions file found")
        return
    
    positions = data.get('positions', [])
    if not positions:
        print("📭 No active positions to monitor")
        return
    
    print(f"📊 Monitoring {len(positions)} active positions...")
    print("")
    
    updated = False
    alerts_sent = 0
    
    for i, position in enumerate(positions):
        pos_id = position.get('id', f'pos_{i}')
        asset = position.get('asset', 'Unknown')
        
        print(f"[{i+1}] {asset[:50]}...")
        print(f"    ID: {pos_id}")
        print(f"    Entry: ${position.get('entry_price', 0):.2f}")
        print(f"    Strategy: {position.get('strategy', 'Unknown')}")
        
        # Get current price
        price_result = get_current_price(position)
        
        if price_result['success']:
            current_price = price_result['price']
            print(f"    Current: ${current_price:.2f} ({price_result['source']})")
            
            # Calculate P&L
            pnl_info = calculate_pnl(position, current_price)
            pnl_color = "💚" if pnl_info['unrealized_pnl'] >= 0 else "❤️"
            print(f"    P&L: {pnl_color} ${pnl_info['unrealized_pnl']:.2f} ({pnl_info['unrealized_pnl_pct']:+.1f}%)")
            
            # Check stop loss / take profit
            triggers = check_stop_loss_take_profit(position, current_price)
            for trigger in triggers:
                print(f"    🚨 {trigger['message']}")
                send_alert(position, trigger, pnl_info)
                alerts_sent += 1
            
            # Update position if requested
            if update:
                position.update(pnl_info)
                position['last_updated'] = datetime.now(timezone.utc).isoformat()
                updated = True
        
        else:
            print(f"    ❌ Price fetch failed: {price_result.get('error', 'Unknown error')}")
        
        print("")
    
    # Save updates if any
    if updated and update:
        if save_active_positions(data):
            print("✅ Positions updated and saved")
        else:
            print("❌ Failed to save position updates")
    
    # Summary
    print("📈 Monitor Summary:")
    print(f"   Positions checked: {len(positions)}")
    print(f"   Alerts sent: {alerts_sent}")
    if updated:
        print(f"   Updates saved: ✅")
    print("")

def main():
    parser = argparse.ArgumentParser(description="Monitor active simulation positions")
    parser.add_argument("--update", action="store_true", help="Update positions with current prices")
    parser.add_argument("--alert-threshold", type=float, default=0.1, help="P&L threshold for alerts (10% default)")
    parser.add_argument("--interval", type=int, help="Run continuously every N seconds")
    
    args = parser.parse_args()
    
    try:
        if args.interval:
            print(f"🔄 Starting continuous monitoring every {args.interval} seconds")
            print("Press Ctrl+C to stop")
            print("")
            
            while True:
                monitor_positions(update=args.update, alert_threshold=args.alert_threshold)
                print(f"⏱️  Sleeping for {args.interval} seconds...")
                time.sleep(args.interval)
        else:
            monitor_positions(update=args.update, alert_threshold=args.alert_threshold)
            
    except KeyboardInterrupt:
        print("\n⏹️  Monitor stopped")
    except Exception as e:
        print(f"❌ Monitor error: {e}")

if __name__ == "__main__":
    main()