import math
from typing import List


def calculate_sharpe_ratio(
    returns: List[float], risk_free_rate: float = 0.02
) -> float:
    """
    Annualised Sharpe ratio.

    Args:
        returns: list of period returns (e.g. daily PnL percentages as decimals).
        risk_free_rate: annual risk-free rate (default 2%).

    Returns:
        Sharpe ratio, or 0.0 if insufficient data.
    """
    if len(returns) < 2:
        return 0.0

    n = len(returns)
    mean_return = sum(returns) / n
    variance = sum((r - mean_return) ** 2 for r in returns) / (n - 1)
    std_dev = math.sqrt(variance)

    if std_dev == 0:
        return 0.0

    # Annualise assuming daily returns (252 trading days)
    daily_rf = risk_free_rate / 252
    sharpe = (mean_return - daily_rf) / std_dev * math.sqrt(252)
    return round(sharpe, 4)


def calculate_max_drawdown(equity_curve: List[float]) -> float:
    """
    Maximum drawdown as a positive percentage (0-100).

    Args:
        equity_curve: list of portfolio values over time.

    Returns:
        Max drawdown percentage, or 0.0 if curve is empty.
    """
    if len(equity_curve) < 2:
        return 0.0

    peak = equity_curve[0]
    max_dd = 0.0

    for value in equity_curve:
        if value > peak:
            peak = value
        drawdown = (peak - value) / peak * 100
        if drawdown > max_dd:
            max_dd = drawdown

    return round(max_dd, 4)


def calculate_profit_factor(gross_profit: float, gross_loss: float) -> float:
    """
    Profit factor = gross_profit / gross_loss.
    Returns 0.0 if gross_loss is zero.
    """
    if gross_loss == 0:
        return 0.0 if gross_profit == 0 else float("inf")
    return round(gross_profit / abs(gross_loss), 4)


def calculate_expectancy(
    win_rate: float, avg_win: float, avg_loss: float
) -> float:
    """
    Expectancy per trade = (win_rate * avg_win) - (loss_rate * avg_loss).

    Args:
        win_rate: fraction 0.0-1.0
        avg_win:  average winning trade PnL (positive)
        avg_loss: average losing trade PnL (positive magnitude)

    Returns:
        Expected PnL per trade.
    """
    loss_rate = 1.0 - win_rate
    expectancy = (win_rate * avg_win) - (loss_rate * avg_loss)
    return round(expectancy, 4)


def calculate_rr_ratio(entry: float, sl: float, tp: float) -> float:
    """
    Risk-to-Reward ratio = |tp - entry| / |entry - sl|.
    Returns 0.0 if risk is zero.
    """
    risk = abs(entry - sl)
    reward = abs(tp - entry)
    if risk == 0:
        return 0.0
    return round(reward / risk, 4)
