"""
Market Data API Routes
Real-time data, technical analysis, liquidity zones, Monte Carlo scenarios
"""

from flask import Blueprint, request, jsonify
from flask_login import login_required, current_user
from app import limiter
from app.services.analytics.market_analyzer import MarketAnalyzer
from app.services.technical_analysis import TechnicalAnalysis
from app.services.risk_analysis import RiskAnalysis
from app.services.price_prediction import PricePrediction
from app.services.correlation_analysis import CorrelationAnalysis
from app.services.whale_hunter_ai import WhaleHunterAI
import yfinance as yf
import pandas as pd
import numpy as np
from datetime import datetime, timedelta

market_api = Blueprint('market_api', __name__)

# Initialize services
tech_analysis = TechnicalAnalysis()
risk_service = RiskAnalysis()
price_predictor = PricePrediction()
correlation_service = CorrelationAnalysis()
whale_hunter = WhaleHunterAI()


def get_historical_data(symbol: str, interval: str = '1h', period: str = '30d'):
    """
    Fetch historical data from Yahoo Finance
    
    Args:
        symbol: Trading symbol (e.g., 'BTC-USD', 'EURUSD=X')
        interval: Data interval (1m, 5m, 15m, 30m, 1h, 4h, 1d, 1wk, 1mo)
        period: Data period (1d, 5d, 1mo, 3mo, 6mo, 1y, 2y, 5y, 10y, ytd, max)
    
    Returns:
        DataFrame with OHLCV data
    """
    try:
        ticker = yf.Ticker(symbol)
        data = ticker.history(period=period, interval=interval)
        
        if data.empty:
            return None
        
        # Handle Forex symbols (volume might be zero)
        if '=X' in symbol and (data['Volume'] == 0).all():
            # Add synthetic volume for forex
            data['Volume'] = 1000000
        
        return data
    except Exception as e:
        print(f"Error fetching data for {symbol}: {e}")
        return None


# ============================================
# Market Snapshot Routes
# ============================================

@market_api.route('/snapshot', methods=['GET'])
@limiter.limit("60 per minute")
def market_snapshot():
    """Get current market snapshot for a symbol"""
    symbol = request.args.get('symbol', 'BTC-USD')
    interval = request.args.get('interval', '1h')
    
    try:
        # Get current data
        ticker = yf.Ticker(symbol)
        info = ticker.info
        
        # Get historical data for change calculation
        hist = ticker.history(period='2d', interval=interval)
        
        if hist.empty:
            return jsonify({'error': 'No data available for symbol'}), 404
        
        current_price = float(hist['Close'].iloc[-1])
        previous_close = float(hist['Close'].iloc[-2]) if len(hist) > 1 else current_price
        change_24h = ((current_price - previous_close) / previous_close) * 100
        
        # Get 24h high/low from last 24 hours of data
        last_day_data = hist.tail(24 if 'h' in interval else 1)
        high_24h = float(last_day_data['High'].max()) if not last_day_data.empty else current_price
        low_24h = float(last_day_data['Low'].min()) if not last_day_data.empty else current_price
        
        return jsonify({
            'symbol': symbol,
            'price': current_price,
            'change_24h': round(change_24h, 2),
            'high_24h': high_24h,
            'low_24h': low_24h,
            'volume': int(hist['Volume'].iloc[-1]) if not pd.isna(hist['Volume'].iloc[-1]) else 0,
            'market_cap': info.get('marketCap'),
            'timestamp': datetime.now().isoformat(),
            'status': 'success'
        })
    except Exception as e:
        return jsonify({'error': str(e), 'status': 'error'}), 500


# ============================================
# Liquidity Analysis Routes
# ============================================

@market_api.route('/liquidity', methods=['GET'])
def liquidity_analysis():
    """Detect liquidity zones using KDE with volume weighting"""
    symbol = request.args.get('symbol', 'BTC-USD')
    interval = request.args.get('interval', '1h')
    period = request.args.get('period', '30d')
    
    try:
        data = get_historical_data(symbol, interval, period)
        if data is None or data.empty:
            return jsonify({'error': 'No data available'}), 404
        
        analyzer = MarketAnalyzer(data['Close'], data['Volume'] if 'Volume' in data else None)
        liquidity_zones = analyzer.detect_liquidity_zones(bandwidth=0.02)
        anomaly_level = analyzer.detect_anomalies(contamination=0.05)
        
        return jsonify({
            'symbol': symbol,
            'liquidity_zones': liquidity_zones,
            'order_flow_anomaly': anomaly_level,
            'status': 'success'
        })
    except Exception as e:
        return jsonify({'error': str(e), 'status': 'error'}), 500


# ============================================
# Volatility Analysis Routes
# ============================================

@market_api.route('/volatility', methods=['GET'])
def volatility_analysis():
    """Analyze volatility outlook using EGARCH model"""
    symbol = request.args.get('symbol', 'BTC-USD')
    interval = request.args.get('interval', '1h')
    period = request.args.get('period', '60d')
    
    try:
        data = get_historical_data(symbol, interval, period)
        if data is None or data.empty:
            return jsonify({'error': 'No data available'}), 404
        
        analyzer = MarketAnalyzer(data['Close'], data['Volume'] if 'Volume' in data else None)
        vol_analysis = analyzer.analyze_volatility(model_type='EGARCH')
        
        # Get historical volatility for comparison
        returns = analyzer.returns
        historical_vol = returns.std() * np.sqrt(252) * 100 if len(returns) > 0 else 0
        
        return jsonify({
            'symbol': symbol,
            'current_volatility': vol_analysis.get('current_volatility', 0),
            'historical_volatility': round(historical_vol, 2),
            'outlook': vol_analysis.get('outlook', 'Normal'),
            'forecast_volatility': vol_analysis.get('forecast_volatility', 0),
            'model_fitted': vol_analysis.get('model_fitted', False),
            'status': 'success'
        })
    except Exception as e:
        return jsonify({'error': str(e), 'status': 'error'}), 500


# ============================================
# Monte Carlo Scenarios Routes
# ============================================

@market_api.route('/scenarios', methods=['GET'])
def monte_carlo_scenarios():
    """Generate Monte Carlo scenarios for price prediction"""
    symbol = request.args.get('symbol', 'BTC-USD')
    interval = request.args.get('interval', '1h')
    period = request.args.get('period', '60d')
    n_paths = int(request.args.get('paths', 20000))
    horizon_days = int(request.args.get('horizon', 2))
    
    try:
        data = get_historical_data(symbol, interval, period)
        if data is None or data.empty:
            return jsonify({'error': 'No data available'}), 404
        
        analyzer = MarketAnalyzer(data['Close'], data['Volume'] if 'Volume' in data else None)
        
        # Run Monte Carlo simulation
        paths = analyzer.monte_carlo_simulation(n_paths=n_paths, horizon_days=horizon_days)
        current_price = data['Close'].iloc[-1]
        
        # Extract scenarios
        scenarios = analyzer.extract_scenarios(paths, current_price)
        
        # Calculate VaR
        var_metrics = analyzer.calculate_var(paths, confidence=0.95)
        
        # Get technical indicators
        tech_indicators = analyzer.get_technical_indicators()
        
        # Price prediction using simple method
        prediction = price_predictor.predict(data['Close'].values, days_ahead=7)
        
        return jsonify({
            'symbol': symbol,
            'current_price': current_price,
            'scenarios': scenarios.get('probabilities', {}),
            'price_targets': {
                'bullish': scenarios.get('levels', {}).get('bull_target', current_price * 1.05),
                'bearish': scenarios.get('levels', {}).get('bear_target', current_price * 0.95),
                'most_likely': current_price
            },
            'risk_metrics': var_metrics,
            'technical_indicators': tech_indicators,
            'price_prediction': prediction,
            'simulation_params': {
                'n_paths': n_paths,
                'horizon_days': horizon_days,
                'interval': interval
            },
            'status': 'success'
        })
    except Exception as e:
        return jsonify({'error': str(e), 'status': 'error'}), 500


# ============================================
# Technical Analysis Routes
# ============================================

@market_api.route('/technical', methods=['GET'])
def technical_analysis():
    """Get technical analysis with support/resistance levels"""
    symbol = request.args.get('symbol', 'BTC-USD')
    interval = request.args.get('interval', '1h')
    period = request.args.get('period', '60d')
    
    try:
        data = get_historical_data(symbol, interval, period)
        if data is None or data.empty:
            return jsonify({'error': 'No data available'}), 404
        
        # Get full technical analysis
        analysis = tech_analysis.get_full_analysis(data, timeframe=interval)
        
        return jsonify({
            'symbol': symbol,
            'interval': interval,
            'analysis': analysis,
            'levels': {
                'support': analysis['support_resistance']['support_levels'],
                'resistance': analysis['support_resistance']['resistance_levels'],
                'current_price': analysis['support_resistance']['current_price']
            },
            'status': 'success'
        })
    except Exception as e:
        return jsonify({'error': str(e), 'status': 'error'}), 500


# ============================================
# Risk Analysis Dashboard Routes
# ============================================

@market_api.route('/risk', methods=['GET'])
def risk_dashboard():
    """Get comprehensive risk analysis dashboard"""
    symbol = request.args.get('symbol', 'BTC-USD')
    interval = request.args.get('interval', '1h')
    period = request.args.get('period', '60d')
    
    try:
        data = get_historical_data(symbol, interval, period)
        if data is None or data.empty:
            return jsonify({'error': 'No data available'}), 404
        
        # Calculate required metrics
        returns = data['Close'].pct_change().dropna()
        volatility = returns.std() * np.sqrt(252) * 100
        
        # Historical volatility (rolling 30 days)
        rolling_vol = returns.rolling(30).std().dropna() * np.sqrt(252) * 100
        historical_vol = rolling_vol.mean() if len(rolling_vol) > 0 else volatility
        
        # ADX and trend from technical analysis
        analysis = tech_analysis.get_full_analysis(data, timeframe=interval)
        adx = analysis['adx']['adx']
        trend = analysis['adx']['trend']
        
        # Volume ratio
        avg_volume = data['Volume'].rolling(50).mean().iloc[-1] if len(data) > 50 else data['Volume'].mean()
        volume_ratio = data['Volume'].iloc[-1] / avg_volume if avg_volume > 0 else 1
        
        # Support/resistance levels
        support = analysis['support_resistance']['support_levels'][0] if analysis['support_resistance']['support_levels'] else data['Close'].iloc[-1] * 0.95
        resistance = analysis['support_resistance']['resistance_levels'][0] if analysis['support_resistance']['resistance_levels'] else data['Close'].iloc[-1] * 1.05
        
        # RSI
        rsi = analysis['rsi']['rsi']
        
        # Get full risk analysis
        risk = risk_service.get_full_risk_analysis(
            volatility=volatility,
            historical_vol=historical_vol,
            adx=adx,
            trend=trend,
            volume_ratio=volume_ratio,
            current_price=data['Close'].iloc[-1],
            support=support,
            resistance=resistance,
            rsi=rsi
        )
        
        return jsonify({
            'symbol': symbol,
            'risk': risk,
            'status': 'success'
        })
    except Exception as e:
        return jsonify({'error': str(e), 'status': 'error'}), 500


# ============================================
# Whale Hunter Signal Routes
# ============================================

@market_api.route('/whale-signal', methods=['GET'])
def whale_signal():
    """Get Whale Hunter AI trading signal"""
    symbol = request.args.get('symbol', 'BTC-USD')
    interval = request.args.get('interval', '1h')
    period = request.args.get('period', '30d')
    
    try:
        data = get_historical_data(symbol, interval, period)
        if data is None or data.empty:
            return jsonify({'error': 'No data available'}), 404
        
        result = whale_hunter.analyze(data, symbol)
        
        return jsonify({
            'symbol': symbol,
            'signal': result.get('signal', {}),
            'indicators': result.get('indicators', {}),
            'config': result.get('config', {}),
            'status': 'success'
        })
    except Exception as e:
        return jsonify({'error': str(e), 'status': 'error'}), 500


# ============================================
# Correlation Analysis Routes
# ============================================

@market_api.route('/correlation', methods=['GET'])
def correlation_analysis():
    """Get correlation between multiple symbols"""
    symbols = request.args.getlist('symbols')
    period = request.args.get('period', '60d')
    
    if len(symbols) < 2:
        return jsonify({'error': 'At least 2 symbols required for correlation'}), 400
    
    try:
        correlations = correlation_service.get_portfolio_correlation(symbols, period)
        diversification_score = correlation_service.get_diversification_score(symbols, period)
        
        return jsonify({
            'correlations': correlations,
            'diversification_score': diversification_score,
            'status': 'success'
        })
    except Exception as e:
        return jsonify({'error': str(e), 'status': 'error'}), 500


# ============================================
# Multiple Assets Route (for portfolio)
# ============================================

@market_api.route('/multi-snapshot', methods=['GET'])
def multi_snapshot():
    """Get snapshots for multiple symbols"""
    symbols = request.args.getlist('symbols')
    
    if not symbols:
        return jsonify({'error': 'No symbols provided'}), 400
    
    results = []
    for symbol in symbols:
        try:
            ticker = yf.Ticker(symbol)
            hist = ticker.history(period='2d')
            
            if not hist.empty:
                current_price = float(hist['Close'].iloc[-1])
                previous_close = float(hist['Close'].iloc[-2]) if len(hist) > 1 else current_price
                change = ((current_price - previous_close) / previous_close) * 100
                
                results.append({
                    'symbol': symbol,
                    'price': current_price,
                    'change_24h': round(change, 2),
                    'volume': int(hist['Volume'].iloc[-1]) if not pd.isna(hist['Volume'].iloc[-1]) else 0,
                    'error': None
                })
            else:
                results.append({'symbol': symbol, 'error': 'No data available'})
        except Exception as e:
            results.append({'symbol': symbol, 'error': str(e)})
    
    return jsonify({
        'results': results,
        'timestamp': datetime.now().isoformat(),
        'status': 'success'
    })