from __future__ import annotations

import os
from pathlib import Path

from pydantic import BaseModel, Field


class StorageConfig(BaseModel):
    root: Path = Path("data")
    manifest_name: str = "manifest.json"


class DatabaseConfig(BaseModel):
    enabled: bool = False
    dsn: str | None = None
    schema_name: str = "uforia"
    read_mode: str = "db"
    write_mode: str = "db"


class IngestionConfig(BaseModel):
    stale_quote_threshold_ms: int = 5 * 60 * 1000
    max_relative_spread: float = 3.0
    max_absolute_spread: float = 0.25
    min_options_per_expiry: int = 4
    request_timeout_seconds: float = 20.0
    archive_grace_seconds: int = 90
    archive_poll_seconds: int = 5
    funding_resolution: str = "3600"


class ModelingConfig(BaseModel):
    supported_underlyings: tuple[str, ...] = ("BTC", "ETH")
    rvvix_windows_days: tuple[int, ...] = (7, 14, 30)
    qvvix_history_days: int = 180
    qvvix_horizon_days: int = 30
    qvvix_paths: int = 10_000
    bootstrap_seed: int = 7
    qvvix_ewma_lambda: float = 0.94
    razor_reference_tenor_days: int = 7
    razor_zscore_lookback_days: int = 30
    razor_long_vol_threshold: float = 1.25
    razor_short_vol_threshold: float = -1.0
    razor_source: str = "synthetic_7d_atm"
    vol_cone_lookback_days: int = 90
    funding_zscore_lookback_days: int = 30
    regime_transition_lookback_days: int = 30
    options_signal_threshold_lookback_days: int = 7
    options_signal_threshold_min_history_hours: int = 24
    options_signal_long_quantile: float = 0.8
    options_signal_short_quantile: float = 0.2
    microstructure_assets: tuple[str, ...] = ("BTC", "ETH")
    microstructure_horizons: tuple[str, ...] = ("30s", "1m", "2m", "5m")
    microstructure_bar_seconds: tuple[int, ...] = (1, 5, 60)
    microstructure_import_root: Path = Path("/Users/mubaris/dev/crypto-microstructure")
    microstructure_tau_bps: float = 2.5
    microstructure_eval_train_days: int = 30
    microstructure_eval_val_days: int = 3
    microstructure_eval_test_days: int = 3
    microstructure_regime_lookback_hours: int = 168


class ExecutionConfig(BaseModel):
    enabled: bool = False
    default_mode: str = "dry_run"
    accounts_config_path: Path = Path("config/execution_accounts.json")
    audit_root: Path = Path("data/execution")
    global_kill_switch: bool = True
    max_order_notional_usd: float = 50_000.0
    max_position_notional_usd: float = 250_000.0
    derive_api_base: str = "https://api.derive.xyz"
    hyperliquid_api_base: str = "https://api.hyperliquid.xyz"
    lighter_api_base: str = "https://mainnet.zklighter.elliot.ai"
    bebop_api_base: str = "https://api.bebop.xyz"


class AppConfig(BaseModel):
    deribit_api_base: str = "https://www.deribit.com/api/v2"
    storage: StorageConfig = Field(default_factory=StorageConfig)
    database: DatabaseConfig = Field(default_factory=DatabaseConfig)
    ingestion: IngestionConfig = Field(default_factory=IngestionConfig)
    modeling: ModelingConfig = Field(default_factory=ModelingConfig)
    execution: ExecutionConfig = Field(default_factory=ExecutionConfig)


def get_config() -> AppConfig:
    return AppConfig(
        storage=StorageConfig(
            root=Path(os.getenv("UFORIA_DATA_ROOT", "data")),
        ),
        database=DatabaseConfig(
            enabled=os.getenv("UFORIA_DB_ENABLED", "false").lower() == "true",
            dsn=os.getenv("UFORIA_DB_DSN"),
            schema_name=os.getenv("UFORIA_DB_SCHEMA", "uforia"),
            read_mode=os.getenv("UFORIA_DB_READ_MODE", "db"),
            write_mode=os.getenv("UFORIA_DB_WRITE_MODE", "db"),
        ),
        execution=ExecutionConfig(
            enabled=os.getenv("UFORIA_EXECUTION_ENABLED", "false").lower() == "true",
            default_mode=os.getenv("UFORIA_EXECUTION_DEFAULT_MODE", "dry_run"),
            accounts_config_path=Path(
                os.getenv("UFORIA_EXECUTION_ACCOUNTS_PATH", "config/execution_accounts.json")
            ),
            audit_root=Path(os.getenv("UFORIA_EXECUTION_AUDIT_ROOT", "data/execution")),
            global_kill_switch=os.getenv("UFORIA_EXECUTION_KILL_SWITCH", "true").lower()
            == "true",
            max_order_notional_usd=float(
                os.getenv("UFORIA_EXECUTION_MAX_ORDER_NOTIONAL_USD", "50000")
            ),
            max_position_notional_usd=float(
                os.getenv("UFORIA_EXECUTION_MAX_POSITION_NOTIONAL_USD", "250000")
            ),
            derive_api_base=os.getenv("UFORIA_DERIVE_API_BASE", "https://api.derive.xyz"),
            hyperliquid_api_base=os.getenv(
                "UFORIA_HYPERLIQUID_API_BASE", "https://api.hyperliquid.xyz"
            ),
            lighter_api_base=os.getenv(
                "UFORIA_LIGHTER_API_BASE", "https://mainnet.zklighter.elliot.ai"
            ),
            bebop_api_base=os.getenv("UFORIA_BEBOP_API_BASE", "https://api.bebop.xyz"),
        ),
    )
