"""Ticker-related MCP tools for YFinance.

This module provides tools for fetching various types of data for individual stocks,
including basic info, price history, financial statements, holders, earnings, and more.
"""

import yfinance as yf
from typing import Literal, Optional
from mcp.server.fastmcp import FastMCP

from ..utils.serializers import df_to_json, series_to_json, dict_to_json


def register(mcp: FastMCP):
    """Register all ticker-related tools with the MCP server."""

    @mcp.tool()
    def get_ticker_info(
        symbol: str,
        fast: bool = False
    ) -> dict:
        """Get basic information about a stock/ETF/fund.
        
        Args:
            symbol: Ticker symbol (e.g., AAPL, MSFT, 600519.SS for Chinese stocks)
            fast: If True, return only fast-loading key metrics; if False, return full info
            
        Returns:
            Dictionary containing company info such as name, sector, industry, 
            market cap, PE ratio, etc.
        """
        ticker = yf.Ticker(symbol)
        if fast:
            fast_info = ticker.fast_info
            return {
                "symbol": symbol,
                "currency": fast_info.get("currency"),
                "exchange": fast_info.get("exchange"),
                "market_cap": fast_info.get("market_cap"),
                "last_price": fast_info.get("last_price"),
                "previous_close": fast_info.get("previous_close"),
                "open": fast_info.get("open"),
                "day_high": fast_info.get("day_high"),
                "day_low": fast_info.get("day_low"),
                "fifty_day_average": fast_info.get("fifty_day_average"),
                "two_hundred_day_average": fast_info.get("two_hundred_day_average"),
                "year_high": fast_info.get("year_high"),
                "year_low": fast_info.get("year_low"),
                "shares": fast_info.get("shares"),
            }
        return dict_to_json(ticker.info)

    @mcp.tool()
    def get_price_history(
        symbol: str,
        period: str = "1mo",
        interval: str = "1d",
        start: Optional[str] = None,
        end: Optional[str] = None,
        include_actions: bool = False
    ) -> dict:
        """Get historical price data for a stock.
        
        Args:
            symbol: Ticker symbol (e.g., AAPL, MSFT)
            period: Data period - 1d,5d,1mo,3mo,6mo,1y,2y,5y,10y,ytd,max
            interval: Data interval - 1m,2m,5m,15m,30m,60m,90m,1h,1d,5d,1wk,1mo,3mo
            start: Start date in YYYY-MM-DD format (overrides period)
            end: End date in YYYY-MM-DD format
            include_actions: Include dividends and stock splits in the data
            
        Returns:
            Historical OHLCV (Open, High, Low, Close, Volume) data
        """
        ticker = yf.Ticker(symbol)
        df = ticker.history(
            period=period,
            interval=interval,
            start=start,
            end=end,
            actions=include_actions
        )
        return df_to_json(df)

    @mcp.tool()
    def get_financials(
        symbol: str,
        statement: Literal["income", "balance", "cashflow"] = "income",
        period: Literal["yearly", "quarterly", "ttm"] = "yearly"
    ) -> dict:
        """Get financial statements for a company.
        
        Args:
            symbol: Ticker symbol (e.g., AAPL, MSFT)
            statement: Type of financial statement
                - income: Income statement (revenue, expenses, net income)
                - balance: Balance sheet (assets, liabilities, equity)
                - cashflow: Cash flow statement (operating, investing, financing)
            period: Time period
                - yearly: Annual financial statements
                - quarterly: Quarterly financial statements
                - ttm: Trailing twelve months (not available for balance sheet)
                
        Returns:
            Financial statement data with line items as rows and periods as columns
        """
        ticker = yf.Ticker(symbol)
        
        if statement == "income":
            if period == "yearly":
                df = ticker.income_stmt
            elif period == "quarterly":
                df = ticker.quarterly_income_stmt
            else:  # ttm
                df = ticker.ttm_income_stmt
        elif statement == "balance":
            if period == "ttm":
                # Balance sheet doesn't have TTM, fallback to yearly
                df = ticker.balance_sheet
            elif period == "quarterly":
                df = ticker.quarterly_balance_sheet
            else:  # yearly
                df = ticker.balance_sheet
        else:  # cashflow
            if period == "yearly":
                df = ticker.cash_flow
            elif period == "quarterly":
                df = ticker.quarterly_cash_flow
            else:  # ttm
                df = ticker.ttm_cash_flow
        
        return df_to_json(df)

    @mcp.tool()
    def get_holders(
        symbol: str,
        holder_type: Literal[
            "major", "institutional", "mutualfund",
            "insider_purchases", "insider_transactions", "insider_roster"
        ] = "major"
    ) -> dict:
        """Get shareholder information for a stock.
        
        Args:
            symbol: Ticker symbol (e.g., AAPL, MSFT)
            holder_type: Type of holders to retrieve
                - major: Major holders (% breakdown)
                - institutional: Institutional holders (hedge funds, etc.)
                - mutualfund: Mutual fund holders
                - insider_purchases: Recent insider purchase activity
                - insider_transactions: All insider transactions
                - insider_roster: List of insiders with their holdings
                
        Returns:
            Holder information based on the selected type
        """
        ticker = yf.Ticker(symbol)
        
        holder_map = {
            "major": ticker.major_holders,
            "institutional": ticker.institutional_holders,
            "mutualfund": ticker.mutualfund_holders,
            "insider_purchases": ticker.insider_purchases,
            "insider_transactions": ticker.insider_transactions,
            "insider_roster": ticker.insider_roster_holders,
        }
        
        df = holder_map[holder_type]
        return df_to_json(df)

    @mcp.tool()
    def get_earnings(
        symbol: str,
        period: Literal["yearly", "quarterly"] = "yearly",
        include_dates: bool = False
    ) -> dict:
        """Get earnings data for a stock.
        
        Args:
            symbol: Ticker symbol (e.g., AAPL, MSFT)
            period: Time period - yearly or quarterly
            include_dates: If True, include upcoming/past earnings dates
            
        Returns:
            Earnings data including revenue, earnings, and optional earnings dates
        """
        ticker = yf.Ticker(symbol)
        
        if period == "yearly":
            df = ticker.earnings
        else:
            df = ticker.quarterly_earnings
        
        result = df_to_json(df)
        
        if include_dates:
            earnings_dates = ticker.earnings_dates
            result["earnings_dates"] = df_to_json(earnings_dates)
        
        return result

    @mcp.tool()
    def get_analyst_data(
        symbol: str,
        data_type: Literal[
            "recommendations", "price_targets", "estimates",
            "eps_trend", "growth", "upgrades_downgrades"
        ] = "recommendations"
    ) -> dict:
        """Get analyst-related data for a stock.
        
        Args:
            symbol: Ticker symbol (e.g., AAPL, MSFT)
            data_type: Type of analyst data to retrieve
                - recommendations: Buy/Hold/Sell recommendations summary
                - price_targets: Target price from analysts (current, low, high, mean)
                - estimates: Earnings and revenue estimates
                - eps_trend: EPS trend over different periods
                - growth: Growth estimates (stock vs industry/sector)
                - upgrades_downgrades: Recent rating changes
                
        Returns:
            Analyst data based on the selected type
        """
        ticker = yf.Ticker(symbol)
        
        if data_type == "recommendations":
            return df_to_json(ticker.recommendations)
        elif data_type == "price_targets":
            return dict_to_json(ticker.analyst_price_targets)
        elif data_type == "estimates":
            return {
                "earnings_estimate": df_to_json(ticker.earnings_estimate),
                "revenue_estimate": df_to_json(ticker.revenue_estimate),
                "earnings_history": df_to_json(ticker.earnings_history)
            }
        elif data_type == "eps_trend":
            return {
                "eps_trend": df_to_json(ticker.eps_trend),
                "eps_revisions": df_to_json(ticker.eps_revisions)
            }
        elif data_type == "growth":
            return df_to_json(ticker.growth_estimates)
        else:  # upgrades_downgrades
            return df_to_json(ticker.upgrades_downgrades)

    @mcp.tool()
    def get_options(
        symbol: str,
        expiration_date: Optional[str] = None
    ) -> dict:
        """Get options chain data for a stock.
        
        Args:
            symbol: Ticker symbol (e.g., AAPL, MSFT)
            expiration_date: Options expiration date (YYYY-MM-DD format).
                           If not provided, returns list of available expiration dates.
                           
        Returns:
            If expiration_date provided: calls and puts options data
            If not provided: list of available expiration dates
        """
        ticker = yf.Ticker(symbol)
        
        if expiration_date is None:
            # Return available expiration dates
            return {
                "symbol": symbol,
                "expiration_dates": list(ticker.options)
            }
        
        # Get option chain for specific date
        chain = ticker.option_chain(expiration_date)
        return {
            "symbol": symbol,
            "expiration_date": expiration_date,
            "calls": df_to_json(chain.calls),
            "puts": df_to_json(chain.puts)
        }

    @mcp.tool()
    def get_dividends_splits(
        symbol: str,
        data_type: Literal["dividends", "splits", "capital_gains", "actions"] = "dividends"
    ) -> dict:
        """Get dividend and stock split history.
        
        Args:
            symbol: Ticker symbol (e.g., AAPL, MSFT)
            data_type: Type of data to retrieve
                - dividends: Historical dividend payments
                - splits: Historical stock splits
                - capital_gains: Capital gains distributions (for funds)
                - actions: Combined dividends and splits
                
        Returns:
            Historical data for the selected type
        """
        ticker = yf.Ticker(symbol)
        
        if data_type == "dividends":
            return series_to_json(ticker.dividends)
        elif data_type == "splits":
            return series_to_json(ticker.splits)
        elif data_type == "capital_gains":
            return series_to_json(ticker.capital_gains)
        else:  # actions
            return df_to_json(ticker.actions)

    @mcp.tool()
    def get_sustainability(symbol: str) -> dict:
        """Get ESG (Environmental, Social, Governance) sustainability data.
        
        Args:
            symbol: Ticker symbol (e.g., AAPL, MSFT)
            
        Returns:
            ESG scores and sustainability metrics including environment score,
            social score, governance score, and controversy level
        """
        ticker = yf.Ticker(symbol)
        return df_to_json(ticker.sustainability)

    @mcp.tool()
    def get_ticker_calendar(
        symbol: str,
        data_type: Literal["calendar", "news", "sec_filings"] = "calendar"
    ) -> dict:
        """Get calendar events, news, or SEC filings for a stock.
        
        Args:
            symbol: Ticker symbol (e.g., AAPL, MSFT)
            data_type: Type of data to retrieve
                - calendar: Upcoming events (earnings, dividends, splits)
                - news: Recent news articles
                - sec_filings: SEC filing documents
                
        Returns:
            Calendar events, news articles, or SEC filings
        """
        ticker = yf.Ticker(symbol)
        
        if data_type == "calendar":
            return dict_to_json(ticker.calendar)
        elif data_type == "news":
            return {"news": ticker.news}
        else:  # sec_filings
            return {"sec_filings": ticker.sec_filings}
