import requests
import json
import websocket
import time
import pandas as pd
import datetime

# MEXC API Endpoints
MEXC_BASE_URL = "https://contract.mexc.com/api/v1/contract"
MEXC_WS_URL = "wss://contract.mexc.com/edge"

# Strategy parameters (example: simple moving average crossover)
SMA_SHORT_PERIOD = 5  # Short-term SMA period (5-minute candles)
SMA_LONG_PERIOD = 20  # Long-term SMA period (5-minute candles)


def fetch_usdt_futures():
    """Fetches all USDT perpetual futures contracts from MEXC."""
    try:
        response = requests.get(f"{MEXC_BASE_URL}/detail")
        response.raise_for_status()  # Raise HTTPError for bad responses (4xx or 5xx)
        data = response.json()

        if data["success"]:
            usdt_futures = [
                item["symbol"]
                for item in data["data"]
                if item["quoteCoin"] == "USDT" and item["displayNameEn"].endswith("SWAP")  # Filter for USDT and Perpetual
            ]
            return usdt_futures
        else:
            print(f"Error fetching USDT futures: {data.get('message', 'Unknown error')}")
            return []

    except requests.exceptions.RequestException as e:
        print(f"Error fetching USDT futures: {e}")
        return []


def fetch_historical_data(symbol, interval="Min5", limit=100):
    """Fetches historical kline data for a given symbol."""
    try:
        response = requests.get(
            f"{MEXC_BASE_URL}/kline/{symbol}", params={"interval": interval, "limit": limit}
        )
        response.raise_for_status()
        data = response.json()

        if data["success"]:
            df = pd.DataFrame(data["data"])
            df["time"] = pd.to_datetime(df["time"], unit="s")  # Convert to datetime objects
            return df
        else:
            print(f"Error fetching historical data for {symbol}: {data.get('message', 'Unknown error')}")
            return None

    except requests.exceptions.RequestException as e:
        print(f"Error fetching historical data for {symbol}: {e}")
        return None




def on_message(ws, message):
    """Handles incoming websocket messages."""
    data = json.loads(message)
    if data.get("channel") == "push.kline":
        candle_data = data["data"]
        symbol = candle_data["symbol"]

        # Fetch historical data (consider caching for efficiency)
        historical_data = fetch_historical_data(symbol, interval="Min5", limit=100)  # Or retrieve from cache
        if historical_data is None:  # Handle potential errors
            return



        # Convert the incoming candle data to a DataFrame and append it to the historical data:
        new_candle_df = pd.DataFrame([candle_data])
        new_candle_df['time'] = pd.to_datetime(new_candle_df['t'], unit='s')

        historical_data = pd.concat([historical_data, new_candle_df], ignore_index=True)
        historical_data = historical_data.tail(100) # Keep only the last 100



        # Calculate SMAs
        historical_data["SMA_short"] = historical_data["c"].rolling(window=SMA_SHORT_PERIOD).mean()
        historical_data["SMA_long"] = historical_data["c"].rolling(window=SMA_LONG_PERIOD).mean()


        # Generate signals (example SMA crossover)
        if (
            historical_data["SMA_short"].iloc[-2] < historical_data["SMA_long"].iloc[-2]  # Previous candle
            and historical_data["SMA_short"].iloc[-1] > historical_data["SMA_long"].iloc[-1]  # Current candle
        ):
            print(f"BUY signal for {symbol} at price {candle_data['c']}")  # Using closing price
        elif (
            historical_data["SMA_short"].iloc[-2] > historical_data["SMA_long"].iloc[-2]  # Previous candle
            and historical_data["SMA_short"].iloc[-1] < historical_data["SMA_long"].iloc[-1]  # Current candle
        ):
            print(f"SELL signal for {symbol} at price {candle_data['c']}") # Using closing price





def on_error(ws, error):
    """Handles websocket errors."""
    print(f"Websocket error: {error}")


def on_close(ws, close_status_code, close_msg):
    """Handles websocket close events."""
    print("Websocket connection closed")


def on_open(ws):
    """Handles websocket open events."""
    print("Websocket connection opened")

    usdt_futures = fetch_usdt_futures()
    if usdt_futures:
        for symbol in usdt_futures:
            subscribe_message = {
                "method": "sub.kline",
                "param": {"symbol": symbol, "interval": "Min5"},
            }
            ws.send(json.dumps(subscribe_message))



def main():
    """Main function to run the bot."""
    ws = websocket.WebSocketApp(
        MEXC_WS_URL,
        on_open=on_open,
        on_message=on_message,
        on_error=on_error,
        on_close=on_close,
    )

    # Keep the websocket connection alive
    while True:
        try:
            ws.run_forever()

        except Exception as e:  # Catch general exceptions to prevent the bot from crashing
            print(f"An error occurred: {e}")
            time.sleep(10)  # Reconnect after 10 seconds

        finally:
            ws.close()  # Close the existing connection before retrying



if __name__ == "__main__":
    main()