"""Shared domain types for opendeviationbar.

``BarKey`` is the time-free identity triple that appears in every ClickHouse
query, write lock, partition lock, and gap-detection call.

``ProcessingOptions`` and ``CacheOptions`` consolidate boolean parameters
on the public API into structured option objects (#338).
"""

from __future__ import annotations

from dataclasses import dataclass


@dataclass(frozen=True)
class ProcessingOptions:
    """Controls how bars are constructed from trades.

    Groups the processing-related boolean flags from
    ``get_open_deviation_bars()`` into a single structured object.
    All defaults match the legacy individual-parameter defaults.

    Parameters
    ----------
    include_microstructure : bool
        Include market microstructure columns (vwap, buy/sell volume, etc.).
    include_incomplete : bool
        Include the final incomplete (forming) bar.
    include_orphaned_bars : bool
        Include incomplete bars from ouroboros boundaries.
    include_exchange_sessions : bool
        Include traditional exchange session flags (Issue #8).
    prevent_same_timestamp_close : bool
        Timestamp gating for flash crash prevention (Issue #36).
    """

    include_microstructure: bool = False
    include_incomplete: bool = False
    include_orphaned_bars: bool = False
    include_exchange_sessions: bool = False
    prevent_same_timestamp_close: bool = True


@dataclass(frozen=True)
class CacheOptions:
    """Controls caching and data-fetch behavior.

    Groups the cache-related boolean flags from
    ``get_open_deviation_bars()`` into a single structured object.
    All defaults match the legacy individual-parameter defaults.

    Parameters
    ----------
    use_cache : bool
        Cache tick data locally and use ClickHouse bar cache.
    fetch_if_missing : bool
        Fetch tick data from source when not available in cache.
    verify_checksum : bool
        Verify SHA-256 checksum of downloaded data (Issue #43).
    materialize : bool
        If True, return a single pd.DataFrame; if False, return
        an Iterator[pl.DataFrame] for streaming.
    """

    use_cache: bool = True
    fetch_if_missing: bool = True
    verify_checksum: bool = True
    materialize: bool = True


@dataclass(frozen=True)
class BarKey:
    """Identity key for a bar series: (symbol, threshold, ouroboros mode).

    This is the *time-free* identity triple that appears in every ClickHouse
    query, write lock, partition lock, and gap-detection call.  Unlike
    ``CacheKey`` (which adds ``start_ts`` / ``end_ts``), ``BarKey`` identifies
    the *series*, not a time window within it.

    Parameters
    ----------
    symbol : str
        Trading symbol (e.g. ``"BTCUSDT"``).
    threshold_decimal_bps : int
        Threshold in decimal basis points (1 dbps = 0.001%).
    ouroboros_mode : str
        Ouroboros reset mode.  Only ``"aion"`` is active.
    """

    symbol: str
    threshold_decimal_bps: int
    ouroboros_mode: str = "aion"


def _resolve_bar_key(
    symbol_or_key: str | BarKey,
    threshold_decimal_bps: int | None = None,
    ouroboros_mode: str | None = None,
) -> BarKey:
    """Resolve expand-contract overloaded args into a BarKey.

    If ``symbol_or_key`` is already a ``BarKey``, returns it (ignoring the
    other two args unless they are explicitly provided as overrides).
    If it is a ``str``, builds a ``BarKey`` from the three individual params.

    Raises
    ------
    TypeError
        If ``symbol_or_key`` is a ``str`` but ``threshold_decimal_bps`` is
        ``None`` (required in the legacy path).
    """
    if isinstance(symbol_or_key, BarKey):
        return symbol_or_key
    # Legacy path -- symbol is a str
    if threshold_decimal_bps is None:
        msg = "threshold_decimal_bps is required when passing symbol as str"
        raise TypeError(msg)
    if ouroboros_mode is None:
        from opendeviationbar.ouroboros import get_operational_ouroboros_mode

        ouroboros_mode = get_operational_ouroboros_mode()
    return BarKey(symbol_or_key, threshold_decimal_bps, ouroboros_mode)
