from providers.polygon import PolygonProvider
import pandas as pd
import matplotlib.pyplot as plt
from io import BytesIO
import pandas_ta as ta

def get_educational_content(topic):
    """
    Fetch educational content for a given topic.
    :param topic: The concept to learn (e.g., "sma", "fibonacci").
    :return: A dictionary containing the explanation and resources.
    """
    content = {
        "sma": {
            "title": "Simple Moving Average (SMA)",
            "description": (
                "The Simple Moving Average (SMA) is a technical indicator that calculates the average price of an asset "
                "over a specified period. It smooths out price data to identify trends. Traders use SMAs to determine "
                "whether an asset is in an uptrend or downtrend.\n\n"
                "Formula: SMA = Sum of Closing Prices / Number of Periods"
            ),
            "example": "For example, a 50-day SMA calculates the average closing price over the last 50 days.",
            "resources": [
                "[Investopedia - SMA](https://www.investopedia.com/terms/s/sma.asp)",
                "[YouTube Tutorial](https://www.youtube.com/watch?v=example_sma)"
            ]
        },
        "rsi": {
            "title": "Relative Strength Index (RSI)",
            "description": (
                "The Relative Strength Index (RSI) is a momentum oscillator that measures the speed and change of price movements. "
                "It ranges from 0 to 100 and is used to identify overbought or oversold conditions.\n\n"
                "- RSI > 70: Overbought (potential sell signal)\n"
                "- RSI < 30: Oversold (potential buy signal)"
            ),
            "example": "For example, if the RSI of a stock is 75, it may indicate that the stock is overbought.",
            "resources": [
                "[Investopedia - RSI](https://www.investopedia.com/terms/r/rsi.asp)",
                "[YouTube Tutorial](https://www.youtube.com/watch?v=example_rsi)"
            ]
        },
        "fibonacci": {
            "title": "Fibonacci Retracements",
            "description": (
                "Fibonacci retracements are horizontal lines that indicate potential support and resistance levels. "
                "They are based on the Fibonacci sequence and are used to predict where prices might reverse.\n\n"
                "Key Levels:\n"
                "- 23.6%\n"
                "- 38.2%\n"
                "- 50%\n"
                "- 61.8%"
            ),
            "example": "For example, after a strong uptrend, the price may retrace to the 38.2% Fibonacci level before resuming the trend.",
            "resources": [
                "[Investopedia - Fibonacci Retracements](https://www.investopedia.com/terms/f/fibonacciretracement.asp)",
                "[YouTube Tutorial](https://www.youtube.com/watch?v=example_fibonacci)"
            ]
        },
        "support_resistance": {
            "title": "Support and Resistance",
            "description": (
                "Support and resistance are key levels where the price tends to reverse. Support acts as a floor, preventing the price from falling further, "
                "while resistance acts as a ceiling, preventing the price from rising further.\n\n"
                "Traders use these levels to identify entry and exit points."
            ),
            "example": "For example, if a stock repeatedly bounces off $50, this level is considered support.",
            "resources": [
                "[Investopedia - Support and Resistance](https://www.investopedia.com/terms/s/supportandresistance.asp)",
                "[YouTube Tutorial](https://www.youtube.com/watch?v=example_support_resistance)"
            ]
        },
        "candlestick_patterns": {
            "title": "Candlestick Patterns",
            "description": (
                "Candlestick patterns are visual representations of price movements. They provide insights into market sentiment and potential reversals.\n\n"
                "Common Patterns:\n"
                "- Bullish Engulfing: Indicates a potential uptrend reversal.\n"
                "- Bearish Engulfing: Indicates a potential downtrend reversal.\n"
                "- Doji: Indicates indecision in the market."
            ),
            "example": "For example, a Bullish Engulfing pattern forms when a small red candle is followed by a large green candle.",
            "resources": [
                "[Investopedia - Candlestick Patterns](https://www.investopedia.com/terms/c/candlestick.asp)",
                "[YouTube Tutorial](https://www.youtube.com/watch?v=example_candlestick)"
            ]
        }
    }

    return content.get(topic.lower(), None)

def fetch_real_time_example(symbol, topic, custom_params=None):
    """
    Fetch real-time data for a given symbol and calculate the requested indicator.
    :param symbol: Stock or forex pair (e.g., "AAPL", "EURUSD").
    :param topic: Indicator to calculate (e.g., "sma", "rsi").
    :param custom_params: Dictionary of custom parameters (e.g., {"period": 100}).
    :return: A message explaining the example.
    """
    provider = PolygonProvider()
    df = provider.fetch_stock_data(symbol)

    if df.empty:
        return f"No data available for {symbol}."

    # Use default parameters if none are provided
    custom_params = custom_params or {}

    # Calculate the requested indicator with custom parameters
    if topic == "sma":
        period = custom_params.get("period", 50)  # Default period is 50
        df[f'SMA_{period}'] = ta.sma(df['Close'], length=period)
        example_value = df[f'SMA_{period}'].iloc[-1]
        return f"The {period}-day SMA for {symbol} is currently {example_value:.2f}."
    elif topic == "rsi":
        period = custom_params.get("period", 14)  # Default period is 14
        df['RSI'] = ta.rsi(df['Close'], length=period)
        example_value = df['RSI'].iloc[-1]
        return f"The {period}-day RSI for {symbol} is currently {example_value:.2f}."
    elif topic == "fibonacci":
        high = df['High'].max()
        low = df['Low'].min()
        levels = [high - (high - low) * pct for pct in [0.236, 0.382, 0.5, 0.618]]
        levels_str = ", ".join(f"{level:.2f}" for level in levels)
        return f"Fibonacci retracement levels for {symbol}: {levels_str}."
    elif topic == "support_resistance":
        support = df['Low'].min()
        resistance = df['High'].max()
        return f"Support for {symbol}: {support:.2f}, Resistance: {resistance:.2f}."
    elif topic == "candlestick_patterns":
        df['Engulfing'] = ta.cdl_engulfing(df['Open'], df['High'], df['Low'], df['Close'])
        pattern = "Bullish Engulfing" if df['Engulfing'].iloc[-1] > 0 else "Bearish Engulfing"
        return f"Latest candlestick pattern for {symbol}: {pattern}."
    else:
        return f"No real-time example available for {topic}."

def generate_indicator_chart(symbol, topic, custom_params=None):
    """
    Generate a chart for the requested indicator.
    :param symbol: Stock or forex pair (e.g., "AAPL", "EURUSD").
    :param topic: Indicator to visualize (e.g., "sma", "rsi").
    :param custom_params: Dictionary of custom parameters (e.g., {"period": 100}).
    :return: BytesIO buffer containing the chart image.
    """
    provider = PolygonProvider()
    df = provider.fetch_stock_data(symbol)

    if df.empty:
        raise Exception(f"No data available for {symbol}.")

    # Use default parameters if none are provided
    custom_params = custom_params or {}

    # Calculate the requested indicator with custom parameters
    if topic == "sma":
        short_period = custom_params.get("short_period", 50)  # Default short period is 50
        long_period = custom_params.get("long_period", 200)   # Default long period is 200
        df[f'SMA_{short_period}'] = ta.sma(df['Close'], length=short_period)
        df[f'SMA_{long_period}'] = ta.sma(df['Close'], length=long_period)
        plt.figure(figsize=(10, 6))
        plt.plot(df.index, df['Close'], label="Close Price", color="blue")
        plt.plot(df.index, df[f'SMA_{short_period}'], label=f"{short_period}-Day SMA", color="orange")
        plt.plot(df.index, df[f'SMA_{long_period}'], label=f"{long_period}-Day SMA", color="purple")
        plt.title(f"{symbol} - Simple Moving Averages")
        plt.xlabel("Date")
        plt.ylabel("Price")
        plt.legend()
    elif topic == "rsi":
        period = custom_params.get("period", 14)  # Default period is 14
        df['RSI'] = ta.rsi(df['Close'], length=period)
        plt.figure(figsize=(10, 6))
        plt.plot(df.index, df['RSI'], label=f"{period}-Day RSI", color="green")
        plt.axhline(70, color="red", linestyle="--", label="Overbought (70)")
        plt.axhline(30, color="blue", linestyle="--", label="Oversold (30)")
        plt.title(f"{symbol} - Relative Strength Index (RSI)")
        plt.xlabel("Date")
        plt.ylabel("RSI Value")
        plt.legend()
    elif topic == "fibonacci":
        high = df['High'].max()
        low = df['Low'].min()
        levels = [high - (high - low) * pct for pct in [0.236, 0.382, 0.5, 0.618]]
        plt.figure(figsize=(10, 6))
        plt.plot(df.index, df['Close'], label="Close Price", color="blue")
        for level in levels:
            plt.axhline(level, color="gray", linestyle="--")
        plt.title(f"{symbol} - Fibonacci Retracement Levels")
        plt.xlabel("Date")
        plt.ylabel("Price")
        plt.legend()
    elif topic == "support_resistance":
        support = df['Low'].rolling(window=20).min()
        resistance = df['High'].rolling(window=20).max()
        plt.figure(figsize=(10, 6))
        plt.plot(df.index, df['Close'], label="Close Price", color="blue")
        plt.plot(df.index, support, label="Support", color="green")
        plt.plot(df.index, resistance, label="Resistance", color="red")
        plt.title(f"{symbol} - Support and Resistance Levels")
        plt.xlabel("Date")
        plt.ylabel("Price")
        plt.legend()
    elif topic == "candlestick_patterns":
        df['Engulfing'] = ta.cdl_engulfing(df['Open'], df['High'], df['Low'], df['Close'])
        bullish = df[df['Engulfing'] > 0]
        bearish = df[df['Engulfing'] < 0]
        plt.figure(figsize=(10, 6))
        plt.plot(df.index, df['Close'], label="Close Price", color="blue")
        plt.scatter(bullish.index, bullish['Close'], label="Bullish Engulfing", color="green", marker="^")
        plt.scatter(bearish.index, bearish['Close'], label="Bearish Engulfing", color="red", marker="v")
        plt.title(f"{symbol} - Candlestick Patterns")
        plt.xlabel("Date")
        plt.ylabel("Price")
        plt.legend()
    else:
        raise Exception(f"No chart available for {topic}.")

    # Save the plot to a BytesIO buffer
    buffer = BytesIO()
    plt.savefig(buffer, format="png")
    buffer.seek(0)
    plt.close()
    return buffer