#!/usr/bin/env python3 
import matplotlib
matplotlib.use('Agg')  # Use non-interactive backend to avoid GUI issues

from flask import Flask, request, jsonify
import logging
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
import datetime
import json
import threading

# Configure logging
logging.basicConfig(
    level=logging.DEBUG,
    format='%(asctime)s %(levelname)s: %(message)s',
    handlers=[
        logging.FileHandler("server.log"),
        logging.StreamHandler()
    ]
)

app = Flask(__name__)

# -------------------------------------------------------------------
# Helper Function to Plot VWAP & Fibonacci Against Price
# -------------------------------------------------------------------

def plot_vwap_fib_vs_price(symbol: str, vwap: float, swingHigh: float, swingLow: float, fibLevels: list, price_data: pd.Series) -> str:
    """
    Plots VWAP, Fibonacci retracement levels, and price on a single chart.
    """
    sns.set(style="whitegrid")
    fig, ax = plt.subplots(figsize=(7.5, 5), dpi=100)
    
    # Plot price data
    ax.plot(price_data.index, price_data.values, label="Price", color='blue', marker='o', markersize=4)

    # Draw Fibonacci retracement levels
    for level in fibLevels:
        level_price = swingLow + (swingHigh - swingLow) * level
        ax.axhline(y=level_price, linestyle='--', linewidth=1.5, label=f'Fib {level*100:.1f}%: {level_price:.5f}')
    
    # Draw VWAP as a horizontal line
    ax.axhline(y=vwap, color='yellow', linestyle='-', linewidth=2, label=f'VWAP: {vwap:.5f}')

    ax.set_title(f'VWAP & Fibonacci vs Price for {symbol}')
    ax.set_xlabel('Time Index')
    ax.set_ylabel('Price')
    ax.legend()

    # Save plot
    timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
    filename = f"vwap_fib_plot_{symbol}_{timestamp}.png"
    plt.savefig(filename)
    plt.close(fig)

    logging.debug(f"VWAP & Fibonacci vs Price graph saved as {filename}")
    return filename

# -------------------------------------------------------------------
# Flask Route for Signal and Analysis
# -------------------------------------------------------------------

@app.route('/getSignal', methods=['POST'])
def get_signal():
    try:
        # Get the raw data from the request
        raw_data = request.data.decode('utf-8').strip()
        logging.debug("Raw data received: " + raw_data)

        # Parse JSON
        decoder = json.JSONDecoder()
        data, idx = decoder.raw_decode(raw_data)
        if idx != len(raw_data):
            logging.error(f"Extra data found after valid JSON: index {idx} of {len(raw_data)}")

        logging.info("Data received from MQL5: " + json.dumps(data, indent=2))

    except Exception as e:
        logging.error("Error parsing JSON: " + str(e))
        return jsonify({"signal": "None", "error": str(e)})

    try:
        # Extract parameters
        symbol = data.get('symbol', 'Unknown')
        swingHigh = float(data.get('swingHigh', 0))
        swingLow = float(data.get('swingLow', 0))
        vwap = float(data.get('vwap', 0))
        fibLevels = data.get('fibLevels', [0.236, 0.382, 0.5, 0.618, 1.618])  # Default levels if not provided

        # Convert priceData list into a pandas Series
        price_data = pd.Series(data.get('priceData', []))

        # Start thread for visualization
        threading.Thread(target=plot_vwap_fib_vs_price, args=(symbol, vwap, swingHigh, swingLow, fibLevels, price_data)).start()

        # Determine signal: "Buy" if VWAP is below mid price, otherwise "Sell"
        mid_price = np.mean([swingHigh, swingLow])
        signal = "Buy" if vwap < mid_price else "Sell"

        explanation = f"Signal: {signal} based on VWAP and Fibonacci analysis."

    except Exception as e:
        logging.error("Error processing data: " + str(e))
        signal = "None"
        explanation = "Error processing the signal."

    # Build response
    response = {
        "signal": signal,
        "explanation": explanation,
        "received_data": data
    }

    logging.debug("Sending response to MQL5: " + json.dumps(response))
    return jsonify(response)

# -------------------------------------------------------------------
# Main Entry Point
# -------------------------------------------------------------------

if __name__ == '__main__':
    port = 5110
    logging.info(f"Starting Flask server on 127.0.0.1:{port} (debug mode ON)")
    app.run(host="127.0.0.1", port=port, debug=True, use_reloader=False)
