"""
Crypto price normalization utilities.
Handles decimal precision, pip calculations, and spread computation.
"""

from config import CRYPTO_PAIRS, DEFAULT_PAIR_CONFIG


def get_pair_config(symbol: str) -> dict:
    """
    Get configuration for a crypto pair.

    Args:
        symbol: Trading pair symbol (e.g., 'BTCUSDT')

    Returns:
        Dictionary with pair configuration
    """
    return CRYPTO_PAIRS.get(symbol.upper(), DEFAULT_PAIR_CONFIG)


def normalize_price(price: float, symbol: str) -> float:
    """
    Normalize price to proper decimal precision for the symbol.

    Args:
        price: Raw price value
        symbol: Trading pair symbol

    Returns:
        Price rounded to proper decimal places
    """
    config = get_pair_config(symbol)
    decimals = config["decimals"]
    return round(price, decimals)


def get_pip_size(symbol: str) -> float:
    """
    Get the pip size (minimum price movement) for a symbol.

    Args:
        symbol: Trading pair symbol

    Returns:
        Pip size value
    """
    config = get_pair_config(symbol)
    return config["pip_size"]


def get_spread(bid: float, ask: float) -> float:
    """
    Calculate spread from bid and ask prices.

    Args:
        bid: Current bid price
        ask: Current ask price

    Returns:
        Spread value (ask - bid)
    """
    return ask - bid


def get_spread_in_pips(bid: float, ask: float, symbol: str) -> float:
    """
    Calculate spread in pips for a symbol.

    Args:
        bid: Current bid price
        ask: Current ask price
        symbol: Trading pair symbol

    Returns:
        Spread measured in pips
    """
    spread = get_spread(bid, ask)
    pip_size = get_pip_size(symbol)
    return spread / pip_size if pip_size > 0 else 0


def price_to_pips(price_distance: float, symbol: str) -> float:
    """
    Convert a price distance to pips.

    Args:
        price_distance: Distance in price units
        symbol: Trading pair symbol

    Returns:
        Distance in pips
    """
    pip_size = get_pip_size(symbol)
    return price_distance / pip_size if pip_size > 0 else 0


def pips_to_price(pips: float, symbol: str) -> float:
    """
    Convert pips to price distance.

    Args:
        pips: Distance in pips
        symbol: Trading pair symbol

    Returns:
        Distance in price units
    """
    pip_size = get_pip_size(symbol)
    return pips * pip_size


def normalize_lot_size(lots: float, symbol: str) -> float:
    """
    Normalize lot size to comply with symbol constraints.

    Args:
        lots: Desired lot size
        symbol: Trading pair symbol

    Returns:
        Normalized lot size within min/max bounds and step size
    """
    config = get_pair_config(symbol)
    min_lot = config["min_lot"]
    max_lot = config["max_lot"]
    lot_step = config["lot_step"]

    # Clamp to min/max
    lots = max(min_lot, min(lots, max_lot))

    # Round to lot step
    if lot_step > 0:
        lots = round(lots / lot_step) * lot_step

    # Ensure we don't go below minimum after rounding
    lots = max(min_lot, lots)

    return lots


def calculate_position_value(lots: float, price: float) -> float:
    """
    Calculate the notional value of a position.

    Args:
        lots: Position size in lots
        price: Current price

    Returns:
        Position value in quote currency
    """
    return lots * price


def calculate_profit_loss(entry_price: float, exit_price: float,
                          lots: float, is_buy: bool = True) -> float:
    """
    Calculate profit/loss for a position.

    Args:
        entry_price: Position entry price
        exit_price: Position exit price
        lots: Position size
        is_buy: True for buy position, False for sell

    Returns:
        Profit/loss in quote currency
    """
    if is_buy:
        return lots * (exit_price - entry_price)
    else:
        return lots * (entry_price - exit_price)
