"""Filter logic for Trades analysis."""

from __future__ import annotations

from datetime import datetime

import polars as pl


def apply_filters(
    df: pl.DataFrame,
    *,
    exit_reason: int | list[int] | None = None,
    entry_reason: int | list[int] | None = None,
    is_adv_triggered: bool | None = None,
    strategy: str | list[str] | None = None,
    blueprint: str | list[str] | None = None,
    direction: int | None = None,
    profitable: bool | None = None,
    period: tuple[str | datetime, str | datetime] | None = None,
    min_holding_bars: int | None = None,
    max_holding_bars: int | None = None,
) -> pl.DataFrame:
    """Apply filters to trades DataFrame.

    Args:
        df: Input DataFrame.
        exit_reason: Filter by exit reason code(s). Single int or list of ints.
        entry_reason: Filter by entry reason code(s). Single int or list of ints.
        is_adv_triggered: Filter by advanced trigger status.
        strategy: Filter by strategy name(s).
        blueprint: Filter by blueprint name(s).
        direction: Filter by direction (1=Long, -1=Short).
        profitable: Filter by profitability (True=winners, False=losers).
        period: Filter by date range (start, end) as ISO strings or datetime.
        min_holding_bars: Minimum holding period in bars.
        max_holding_bars: Maximum holding period in bars.

    Returns:
        Filtered DataFrame.
    """
    result = df

    # Exit reason filter
    if exit_reason is not None:
        if "exit_reason" not in df.columns:
            raise ValueError("exit_reason column not found for filtering")
        if isinstance(exit_reason, int):
            result = result.filter(pl.col("exit_reason") == exit_reason)
        else:
            result = result.filter(pl.col("exit_reason").is_in(exit_reason))

    # Entry reason filter
    if entry_reason is not None:
        if "entry_reason" not in df.columns:
            raise ValueError("entry_reason column not found for filtering")
        if isinstance(entry_reason, int):
            result = result.filter(pl.col("entry_reason") == entry_reason)
        else:
            result = result.filter(pl.col("entry_reason").is_in(entry_reason))

    # Advanced trigger filter
    if is_adv_triggered is not None:
        if "is_adv_triggered" not in df.columns:
            raise ValueError("is_adv_triggered column not found for filtering")
        result = result.filter(pl.col("is_adv_triggered") == is_adv_triggered)

    # Strategy filter
    if strategy is not None:
        if "strategy_name" not in df.columns:
            raise ValueError("strategy_name column not found for filtering")
        if isinstance(strategy, str):
            result = result.filter(pl.col("strategy_name") == strategy)
        else:
            result = result.filter(pl.col("strategy_name").is_in(strategy))

    # Blueprint filter
    if blueprint is not None:
        if "blueprint_name" not in df.columns:
            raise ValueError("blueprint_name column not found for filtering")
        if isinstance(blueprint, str):
            result = result.filter(pl.col("blueprint_name") == blueprint)
        else:
            result = result.filter(pl.col("blueprint_name").is_in(blueprint))

    # Direction filter
    if direction is not None:
        result = result.filter(pl.col("direction") == direction)

    # Profitability filter
    if profitable is not None:
        if profitable:
            result = result.filter(pl.col("pnl") > 0)
        else:
            result = result.filter(pl.col("pnl") <= 0)

    # Period filter
    if period is not None:
        if "exit_time" not in df.columns:
            raise ValueError("exit_time column required for period filtering")
        start, end = period
        if isinstance(start, str):
            start = datetime.fromisoformat(start)
        if isinstance(end, str):
            end = datetime.fromisoformat(end)
        result = result.filter((pl.col("exit_time") >= start) & (pl.col("exit_time") <= end))

    # Holding bars filters
    if min_holding_bars is not None:
        if "holding_bars" not in df.columns:
            raise ValueError("holding_bars column required for filtering")
        result = result.filter(pl.col("holding_bars") >= min_holding_bars)

    if max_holding_bars is not None:
        if "holding_bars" not in df.columns:
            raise ValueError("holding_bars column required for filtering")
        result = result.filter(pl.col("holding_bars") <= max_holding_bars)

    return result
