"""
Backend module for the Market Dashboard.

Handles data fetching from Yahoo Finance, caching,
and building summary messages for Telegram.
"""

import os
import pickle
from pathlib import Path
import datetime as dt

import yfinance as yf

from backend.telegram import send_message
from data.tickers import (
    TICKERS_Main,
    TICKERS_Ai,
    TICKERS_Forex,
)

# Set to True for development (uses cached data), False for production.
# Override with env var DEV_MODE=false for CI / GitHub Actions.
DEV_MODE = os.getenv("DEV_MODE", "true").lower() != "false" # this means that if DEV_MODE is not set, it defaults to True (development mode). If DEV_MODE is set to "false" (case-insensitive), it will be False (production mode).

# Cache directory lives inside the data folder
CACHE_DIR = Path(__file__).parent.parent / "data" / "cache_data"


def save_cache(data, cache_file: Path) -> None:
    """
    Saves data to a cache file using Python's pickle module.

    Args:
        data:
            Data to save (pandas DataFrame, dict, str, etc.).
        cache_file (Path):
            Path to the cache file.
    """
    os.makedirs(CACHE_DIR, exist_ok=True)
    with open(cache_file, "wb") as f:
        pickle.dump(data, f)
    print(f"💾 Cached data saved to {cache_file}")


def load_cache(cache_file: Path):
    """
    Loads data from a cache file.

    Args:
        cache_file (Path):
            Path to the cache file.

    Returns:
        The cached data, or None if the file does not exist.
    """
    if cache_file.exists():
        with open(cache_file, "rb") as f:
            print(f"📂 Loading cached data from {cache_file}")
            return pickle.load(f)
    return None


def get_daily_changes(tickers: list[str]) -> tuple:
    """
    Downloads market data and calculates the latest daily percentage change.
    In DEV_MODE, uses cached data. In production, fetches live data.

    Args:
        tickers (list[str]):
            List of Yahoo Finance ticker symbols.

    Returns:
        tuple:
            A tuple of (closing_prices DataFrame, daily_changes dict).
    """
    cache_file = CACHE_DIR / f"market_data_{'_'.join(sorted(tickers))}.pkl"

    if DEV_MODE:
        cached_data = load_cache(cache_file)
        if cached_data is not None:
            data = cached_data
            print("✅ Using cached data (DEV_MODE)")
        else:
            print("⚠️ No cache found, fetching from yfinance...")
            data = yf.download(
                tickers,
                period="6mo",
                interval="1d",
                rounding=True,
                auto_adjust=True,
            )
            save_cache(data, cache_file)
    else:
        print("🔴 PRODUCTION MODE: Fetching live data from yfinance")
        data = yf.download(
            tickers,
            period="6mo",
            interval="1d",
            rounding=True,
            auto_adjust=True,
        )
        save_cache(data, cache_file)

    closing_prices = data["Close"]

    daily_changes = {}

    for ticker in tickers:
        prices = closing_prices[ticker].dropna()

        if len(prices) < 2:
            continue

        previous_close = prices.iloc[-2]
        latest_close = prices.iloc[-1]

        percentage_change = (
            (latest_close - previous_close)
            / previous_close
            * 100
        )

        daily_changes[ticker] = percentage_change

    return closing_prices, daily_changes


def get_ticker_name(ticker: str) -> str:
    """
    Gets the full name for a Yahoo Finance ticker.
    In DEV_MODE, uses cached data. In production, fetches live data.

    Args:
        ticker (str):
            Yahoo Finance ticker symbol.

    Returns:
        str:
            Full ticker name, or the ticker symbol itself as fallback.
    """
    cache_file = CACHE_DIR / f"ticker_name_{ticker.replace('=', '_').replace('.', '_')}.pkl"

    if DEV_MODE:
        cached_name = load_cache(cache_file)
        if cached_name is not None:
            return cached_name
        else:
            print(f"⚠️ No cache found for {ticker} name, fetching...")
            ticker_info = yf.Ticker(ticker).info
            name = ticker_info.get("longName", ticker)
            save_cache(name, cache_file)
            return name
    else:
        ticker_info = yf.Ticker(ticker).info
        return ticker_info.get("longName", ticker)

def get_status_emoji(percentage_change: float) -> str:
    """
    Returns an emoji based on the size of the daily price change.

    Args:
        percentage_change (float):
            Daily percentage change.

    Returns:
        str:
            Status emoji.
    """
    if percentage_change <= -1.0:
        return "🔴"

    if percentage_change < 0.5:
        return "🟡"

    return "🟢"

def build_summary_message(closing_prices, daily_changes: dict) -> str:
    """
    Builds a text summary of market data for a single ticker group.

    Args:
        closing_prices:
            DataFrame of closing prices.
        daily_changes (dict):
            Dictionary of ticker → percentage change.

    Returns:
        str:
            Formatted text summary.
    """

    lines = []
    for ticker, change in daily_changes.items():
        latest_price = closing_prices[ticker].dropna().iloc[-1]
        emoji = get_status_emoji(change)
        lines.append(f"{emoji} {ticker}: {latest_price:.2f} ({change:+.2f}%)")
    return "\n".join(lines)


def run_backend() -> None:
    """
    Runs the backend process: fetches data for all ticker groups,
    saves a summary to a file, and sends it via Telegram.
    """
    output_file = CACHE_DIR.parent / "market_summary.txt"

    all_messages = []

    # Add the current date to the summary
    todayDate = dt.datetime.now().strftime("%d-%m-%Y")
    all_messages.append(f"📅 Date: {todayDate}")

    print("📊 Fetching Main ETFs...")
    main_prices, main_changes = get_daily_changes(TICKERS_Main)
    all_messages.append("🌎 Main ETFs:\n" + build_summary_message(main_prices, main_changes))

    print("📊 Fetching AI ETFs...")
    ai_prices, ai_changes = get_daily_changes(TICKERS_Ai)
    all_messages.append("🤖 AI ETFs:\n" + build_summary_message(ai_prices, ai_changes))

    print("📊 Fetching Forex...")
    forex_prices, forex_changes = get_daily_changes(TICKERS_Forex)
    all_messages.append("💱 Forex:\n" + build_summary_message(forex_prices, forex_changes))

    full_summary = "\n\n".join(all_messages)

    # Save summary to file
    os.makedirs(output_file.parent, exist_ok=True)
    with open(output_file, "w", encoding="utf-8") as f:
        f.write(full_summary)
    print(f"📄 Summary saved to {output_file}")

    # Send via Telegram
    print("📨 Sending summary to Telegram...")
    send_message(full_summary)

    print("✅ Backend finished.")
