# polars-exception: backtesting.py requires Pandas DataFrames for OHLCV data
"""opendeviationbar: Python bindings for open deviation bar construction.

This package provides high-performance open deviation bar construction for cryptocurrency
trading backtesting, with non-lookahead bias guarantees and temporal integrity.

Examples
--------
Basic usage:

>>> from opendeviationbar import process_trades_to_dataframe
>>> import pandas as pd
>>>
>>> # Load Binance aggTrades data
>>> trades = pd.read_csv("BTCUSDT-aggTrades-2024-01.csv")
>>>
>>> # Convert to open deviation bars (25 basis points = 0.25%)
>>> df = process_trades_to_dataframe(trades, threshold_decimal_bps=250)
>>>
>>> # Use with backtesting.py
>>> from backtesting import Backtest, Strategy
>>> bt = Backtest(df, MyStrategy, cash=10000, commission=0.0002)
>>> stats = bt.run()
"""

from __future__ import annotations

# Anti-fragile .pth guard: detect editable install shadowing the wheel.
# Root cause: `maturin develop` creates a .pth file that makes Python import
# from the repo's python/ directory instead of the installed wheel. This
# survives venv swaps (hard links) and causes version drift on production.
# Learned 2026-03-28: 3 incidents in one session, 1100+ overlaps from stale code.
import pathlib as _pathlib
import warnings as _warnings

_site_pkg = _pathlib.Path(__file__).parent.parent
_pth_file = _site_pkg / "opendeviationbar.pth"
if _pth_file.exists():
    _pth_content = _pth_file.read_text().strip()
    _warnings.warn(
        f"CRITICAL: opendeviationbar.pth detected at {_pth_file} "
        f"(content: {_pth_content!r}). This shadows the installed wheel with "
        f"repo code. Remove it: rm {_pth_file}",
        RuntimeWarning,
        stacklevel=1,
    )
del _pathlib, _warnings, _site_pkg, _pth_file

from ._core import PositionVerification, __version__

__all__ = [
    # Sorted alphabetically for RUF022 compliance
    "ALL_OPTIONAL_COLUMNS",
    "ASSET_CLASS_MULTIPLIERS",
    "BAR_FLAG_COLUMNS",  # Issue #101: is_liquidation_cascade and future bar flags
    "BINANCE_VISION_AGGTRADES_URL",  # Issue #88: Binance Vision probe
    "EXCHANGE_SESSION_COLUMNS",
    "INTER_BAR_FEATURE_COLUMNS",  # Issue #59 (lookback window BEFORE bar)
    "INTRA_BAR_FEATURE_COLUMNS",  # Issue #59 (trades WITHIN bar)
    "LONG_RANGE_DAYS",  # Issue #69: MEM-013 threshold (30 days)
    "MICROSTRUCTURE_COLUMNS",
    "MIN_VERSION_FOR_MICROSTRUCTURE",
    "MIN_VERSION_FOR_OUROBOROS",
    "SCHEMA_VERSION_MICROSTRUCTURE",
    "SCHEMA_VERSION_OHLCV_ONLY",
    "SCHEMA_VERSION_OUROBOROS",
    "THRESHOLD_DECIMAL_MAX",
    "THRESHOLD_DECIMAL_MIN",
    "THRESHOLD_PRESETS",
    "TIER1_SYMBOLS",
    "TRADE_ID_RANGE_COLUMNS",  # Issue #72: agg_trade_id for data integrity
    "VALIDATION_PRESETS",
    "AssetClass",
    "AsyncStreamingProcessor",
    "BackfillResult",  # Issue #92: gap backfill
    "BinanceLiveStream",
    "ContinuityError",
    "ContinuityWarning",
    "CryptoThresholdError",  # Issue #62: backward compat alias
    "GapInfo",
    "GapTier",
    "OpenDeviationBarProcessor",
    "OuroborosBoundary",
    "OuroborosMode",
    "PositionVerification",
    "PrecomputeProgress",
    "PrecomputeResult",
    "ReconnectionConfig",
    "SidecarConfig",  # Issue #91: streaming sidecar
    "StalenessResult",
    "StreamingConfig",
    "StreamingError",
    "StreamingMetrics",
    "StreamingOpenDeviationBarProcessor",
    "SymbolEntry",  # Issue #79: symbol registry
    "SymbolNotRegisteredError",  # Issue #79: mandatory gate
    "SymbolTransition",  # Issue #79: symbol transitions
    "ThresholdError",  # Issue #62: crypto minimum threshold
    "TierSummary",
    "TierThresholds",
    "TieredValidationResult",
    "ValidationPreset",
    "__version__",
    "auto_memory_guard",
    "backfill_all_gaps",  # Issue #92: gap backfill
    "backfill_gap",  # Issue #92: gap backfill
    "clear_symbol_registry_cache",  # Issue #79: runtime registry refresh
    "clear_threshold_cache",  # Issue #62: runtime config changes
    "detect_asset_class",
    "detect_staleness",
    "discover_providers",  # Issue #98: FeatureProvider plugin discovery
    "ensure_memory_limit",
    "get_available_symbols",  # Issue #95: alpha-forge compat
    "get_cache_coverage",  # Issue #95: alpha-forge compat
    "get_effective_start_date",  # Issue #79: symbol effective start
    "get_feature_groups",  # Issue #95: alpha-forge compat
    "get_feature_manifest",  # Issue #95: alpha-forge compat
    "get_min_threshold",  # Issue #62: asset-class default
    "get_min_threshold_for_symbol",  # Issue #62: per-symbol lookup
    "get_n_open_deviation_bars",
    "get_open_deviation_bars",
    "get_open_deviation_bars_pandas",
    "get_open_deviation_bars_panel",  # Issue #95: alpha-forge compat
    "get_ouroboros_boundaries",
    "get_registered_symbols",  # Issue #79: filtered symbol listing
    "get_symbol_entries",  # Issue #79: all symbol metadata
    "get_symbol_market",  # Issue #158: market type lookup
    "get_transitions",  # Issue #79: symbol rename history
    "normalize_arrow_dtypes",
    "normalize_temporal_precision",
    "populate_cache_multi_threshold",
    "populate_cache_resumable",
    "precompute_open_deviation_bars",
    "probe_latest_available_date",  # Issue #88: Binance Vision probe
    "process_trades_chunked",
    "process_trades_polars",
    "process_trades_polars_lazy",  # Task #94: Lazy evaluation for predicate pushdown
    "process_trades_to_dataframe",
    "resolve_and_validate_threshold",  # Issue #62: central validation
    "resolve_market",  # Issue #158: market type resolution
    "run_sidecar",  # Issue #91: streaming sidecar
    "stream_binance_live",
    "to_panel_format",  # Issue #95: alpha-forge compat
    "validate_and_clamp_start_date",  # Issue #79: start date clamping
    "validate_continuity",
    "validate_continuity_tiered",
    "validate_symbol_registered",  # Issue #79: mandatory gate
]

# Binance Vision availability probe (Issue #88)
# Re-export Layer 2 backfill API (Issue #92)
from .backfill import (
    BackfillResult,
    backfill_all_gaps,
    backfill_gap,
)
from .binance_vision import BINANCE_VISION_AGGTRADES_URL, probe_latest_available_date

# Re-export checkpoint API per plan (#40)
from .checkpoint import populate_cache_multi_threshold, populate_cache_resumable

# Import constants from centralized module (SSoT)
from .constants import (
    ALL_OPTIONAL_COLUMNS,
    BAR_FLAG_COLUMNS,  # Issue #101: is_liquidation_cascade
    EXCHANGE_SESSION_COLUMNS,
    INTER_BAR_FEATURE_COLUMNS,  # Issue #59 (lookback window BEFORE bar)
    INTRA_BAR_FEATURE_COLUMNS,  # Issue #59 (trades WITHIN bar)
    LONG_RANGE_DAYS,  # Issue #69: MEM-013 threshold (30 days)
    MICROSTRUCTURE_COLUMNS,
    MIN_VERSION_FOR_MICROSTRUCTURE,
    MIN_VERSION_FOR_OUROBOROS,
    SCHEMA_VERSION_MICROSTRUCTURE,
    SCHEMA_VERSION_OHLCV_ONLY,
    SCHEMA_VERSION_OUROBOROS,
    THRESHOLD_DECIMAL_MAX,
    THRESHOLD_DECIMAL_MIN,
    THRESHOLD_PRESETS,
    TIER1_SYMBOLS,
    TRADE_ID_RANGE_COLUMNS,  # Issue #72: agg_trade_id for data integrity
)

# Import conversion utilities from centralized module (SSoT)
from .conversion import normalize_arrow_dtypes, normalize_temporal_precision

# Import orchestration functions from extracted module (M4 modularization)
from .orchestration.count_bounded import get_n_open_deviation_bars
from .orchestration.models import PrecomputeProgress, PrecomputeResult
from .orchestration.open_deviation_bars import (
    get_open_deviation_bars,
    get_open_deviation_bars_pandas,
)
from .orchestration.precompute import precompute_open_deviation_bars

# Re-export ouroboros API (cyclical reset boundaries for reproducibility)
from .ouroboros import (
    OuroborosBoundary,
    OuroborosMode,
    get_ouroboros_boundaries,
)

# Import OpenDeviationBarProcessor from extracted module (M2 modularization)
# Import process_trades_* functions from extracted module (M3 modularization)
from .processors.api import (
    process_trades_chunked,
    process_trades_polars,
    process_trades_polars_lazy,
    process_trades_to_dataframe,
    process_trades_to_dataframe_cached,
)
from .processors.core import OpenDeviationBarProcessor

# Memory safety guards (Issue #49, MEM-011)
# ensure_memory_limit() provides idempotent memory cap with env var support
# auto_memory_guard() is called at import to enable default 70% RAM limit
from .resource_guard import auto_memory_guard, ensure_memory_limit

# Re-export Layer 3 streaming sidecar API (Issue #91)
from .sidecar import SidecarConfig, run_sidecar

# Enable memory guard by default on import (can be disabled with OPENDEVIATIONBAR_NO_MEMORY_GUARD=1)
auto_memory_guard()

# Streaming API (ADR: docs/adr/2026-01-31-realtime-streaming-api.md)
# Import symbol registry (Issue #79: Unified Symbol Registry with mandatory gating)
# Alpha-forge compatibility layer (Issue #95)
from .compat import (
    get_available_symbols,
    get_cache_coverage,
    get_feature_groups,
    get_feature_manifest,
    get_open_deviation_bars_panel,
    to_panel_format,
)
from .exceptions import SymbolNotRegisteredError
from .streaming import (
    AsyncStreamingProcessor,
    BinanceLiveStream,
    ReconnectionConfig,
    StreamingConfig,
    StreamingError,
    StreamingMetrics,
    StreamingOpenDeviationBarProcessor,
    stream_binance_live,
)
from .symbol_registry import (
    SymbolEntry,
    SymbolTransition,
    clear_symbol_registry_cache,
    get_effective_start_date,
    get_registered_symbols,
    get_symbol_entries,
    get_symbol_market,
    get_transitions,
    resolve_market,
    validate_and_clamp_start_date,
    validate_symbol_registered,
)

# Import threshold validation utilities (Issue #62: crypto minimum threshold)
from .threshold import (
    CryptoThresholdError,
    ThresholdError,
    clear_threshold_cache,
    get_min_threshold,
    get_min_threshold_for_symbol,
    resolve_and_validate_threshold,
)

# Import staleness detection for cache validation (Issue #39: Schema Evolution)
from .validation.cache_staleness import StalenessResult, detect_staleness

# Import continuity validation from extracted module (M1 modularization)
from .validation.continuity import (
    ASSET_CLASS_MULTIPLIERS,
    VALIDATION_PRESETS,
    AssetClass,
    ContinuityError,
    ContinuityWarning,
    GapInfo,
    GapTier,
    TieredValidationResult,
    TierSummary,
    TierThresholds,
    ValidationPreset,
    detect_asset_class,
    validate_continuity,
    validate_continuity_tiered,
    validate_junction_continuity,
)

# Re-export ClickHouse components for convenience
# NOTE: TIER1_SYMBOLS, THRESHOLD_PRESETS, THRESHOLD_DECIMAL_MIN/MAX
# are imported from constants.py (SSoT) at the top of this file


# =============================================================================
# Tiered Validation System (Issue #19 - v6.2.0+)
# =============================================================================
# MOVED to opendeviationbar.validation.continuity (M1 modularization)
# All types, presets, and functions are imported at the top of this file.


# The following block was removed during M1 modularization.
# detect_asset_class, GapTier, AssetClass, TierThresholds, ValidationPreset,
# VALIDATION_PRESETS, ASSET_CLASS_MULTIPLIERS, GapInfo, TierSummary,
# TieredValidationResult, _resolve_validation, _classify_gap,
# validate_continuity_tiered are now imported from opendeviationbar.validation.continuity.

# The following blocks were removed during M4 modularization:
# PrecomputeProgress, PrecomputeResult → opendeviationbar.orchestration.models
# get_open_deviation_bars, get_open_deviation_bars_pandas → opendeviationbar.orchestration.open_deviation_bars
# precompute_open_deviation_bars → opendeviationbar.orchestration.precompute
# get_n_open_deviation_bars, _fill_gap_and_cache, _fetch_and_compute_bars → opendeviationbar.orchestration.count_bounded
# _stream_open_deviation_bars_binance, _fetch_binance, _fetch_exness → opendeviationbar.orchestration.helpers
# _process_binance_trades, _process_exness_ticks → opendeviationbar.orchestration.helpers


def __getattr__(name: str) -> object:
    """Lazy attribute access for ClickHouse and Exness components."""
    if name in {
        "OpenDeviationBarCache",
        "CacheKey",
        "get_available_clickhouse_host",
        "detect_clickhouse_state",
        "ClickHouseNotConfiguredError",
    }:
        from . import clickhouse

        return getattr(clickhouse, name)

    if name == "is_exness_available":
        from .exness import is_exness_available

        return is_exness_available

    # Issue #98: Plugin system lazy loading
    if name == "discover_providers":
        from .plugins.loader import discover_providers

        return discover_providers

    msg = f"module {__name__!r} has no attribute {name!r}"
    raise AttributeError(msg)
