"""Data source and market data tools."""

from typing import Dict, Any, List, Optional
from langchain_core.tools import tool


def _get_datasource_registry():
    """Get the global datasource registry instance."""
    from . import _datasource_registry
    return _datasource_registry


@tool
def list_data_sources() -> List[str]:
    """List all available data sources.

    Returns:
        List of data source names that can be queried for market data
    """
    registry = _get_datasource_registry()
    if not registry:
        return []
    return registry.list_sources()


@tool
async def search_symbols(
    query: str,
    type: Optional[str] = None,
    exchange: Optional[str] = None,
    limit: int = 30,
) -> Dict[str, Any]:
    """Search for trading symbols across all data sources.

    Automatically searches all available data sources and returns aggregated results.
    Use this to find symbols before calling get_symbol_info or get_historical_data.

    Args:
        query: Search query (e.g., "BTC", "AAPL", "EUR")
        type: Optional filter by instrument type (e.g., "crypto", "stock", "forex")
        exchange: Optional filter by exchange (e.g., "binance", "nasdaq")
        limit: Maximum number of results per source (default: 30)

    Returns:
        Dictionary mapping source names to lists of matching symbols.
        Each symbol includes: symbol, full_name, description, exchange, type.
        Use the source name and symbol from results with get_symbol_info or get_historical_data.

    Example response:
        {
            "demo": [
                {
                    "symbol": "BTC/USDT",
                    "full_name": "Bitcoin / Tether USD",
                    "description": "Bitcoin perpetual futures",
                    "exchange": "demo",
                    "type": "crypto"
                }
            ]
        }
    """
    registry = _get_datasource_registry()
    if not registry:
        raise ValueError("DataSourceRegistry not initialized")

    # Always search all sources
    results = await registry.search_all(query, type, exchange, limit)
    return {name: [r.model_dump() for r in matches] for name, matches in results.items()}


@tool
async def get_symbol_info(source_name: str, symbol: str) -> Dict[str, Any]:
    """Get complete metadata for a trading symbol.

    This retrieves full information about a symbol including:
    - Description and type
    - Supported time resolutions
    - Available data columns (OHLCV, volume, funding rates, etc.)
    - Trading session information
    - Price scale and precision

    Args:
        source_name: Name of the data source (use list_data_sources to see available)
        symbol: Symbol identifier (e.g., "BTC/USDT", "AAPL", "EUR/USD")

    Returns:
        Dictionary containing complete symbol metadata including column schema

    Raises:
        ValueError: If source_name or symbol is not found
    """
    registry = _get_datasource_registry()
    if not registry:
        raise ValueError("DataSourceRegistry not initialized")

    symbol_info = await registry.resolve_symbol(source_name, symbol)
    return symbol_info.model_dump()


@tool
async def get_historical_data(
    source_name: str,
    symbol: str,
    resolution: str,
    from_time: int,
    to_time: int,
    countback: Optional[int] = None,
) -> Dict[str, Any]:
    """Get historical bar/candle data for a symbol.

    Retrieves time-series data between the specified timestamps. The data
    includes all columns defined for the symbol (OHLCV + any custom columns).

    Args:
        source_name: Name of the data source
        symbol: Symbol identifier
        resolution: Time resolution (e.g., "1" = 1min, "5" = 5min, "60" = 1hour, "1D" = 1day)
        from_time: Start time as Unix timestamp in seconds
        to_time: End time as Unix timestamp in seconds
        countback: Optional limit on number of bars to return

    Returns:
        Dictionary containing:
        - symbol: The requested symbol
        - resolution: The time resolution
        - bars: List of bar data with 'time' and 'data' fields
        - columns: Schema describing available data columns
        - nextTime: If present, indicates more data is available for pagination

    Raises:
        ValueError: If source, symbol, or resolution is invalid

    Example:
        # Get 1-hour BTC data for the last 24 hours
        import time
        to_time = int(time.time())
        from_time = to_time - 86400  # 24 hours ago
        data = get_historical_data("demo", "BTC/USDT", "60", from_time, to_time)
    """
    registry = _get_datasource_registry()
    if not registry:
        raise ValueError("DataSourceRegistry not initialized")

    source = registry.get(source_name)
    if not source:
        available = registry.list_sources()
        raise ValueError(f"Data source '{source_name}' not found. Available sources: {available}")

    result = await source.get_bars(symbol, resolution, from_time, to_time, countback)
    return result.model_dump()


DATASOURCE_TOOLS = [
    list_data_sources,
    search_symbols,
    get_symbol_info,
    get_historical_data,
]
