"""
TOML-based configuration for V2.
"""
from __future__ import annotations
from pathlib import Path
from dataclasses import dataclass, field
import toml


@dataclass
class Config:
    # General
    mode: str = "paper"                   # "paper" or "live"
    interval_seconds: int = 90            # scan interval (was 45, too aggressive)
    universe: str = "top"                 # "top", "all", or comma-separated coins
    max_coins: int = 8
    min_day_volume_usd: float = 5_000_000

    # Account
    equity_usd: float = 100.0
    fixed_margin_usd: float = 20.0
    max_leverage: int = 20
    max_open_positions: int = 2

    # Risk
    max_risk_pct: float = 0.02
    min_rr: float = 1.5
    min_confidence: float = 0.55
    spread_max_bps: float = 5.0
    max_daily_losses: int = 2
    max_daily_trades: int = 6
    fee_bps: float = 4.5
    enable_break_even: bool = False
    enable_profit_lock: bool = False
    profit_lock_trigger_r: float = 1.0
    profit_lock_fraction: float = 0.35
    stop_atr_multiplier: float = 1.2
    min_stop_noise_multiple: float = 1.10
    min_target_pct: float = 0.008
    min_target_atr_multiple: float = 2.50
    prefer_htf_targets: bool = True
    enforce_min_target_distance: bool = False
    runner_target_rr: float = 2.50
    max_target_rr: float = 5.00
    runner_min_confidence: float = 0.65
    ws_book_max_age_s: float = 10.0
    ws_tape_max_age_s: float = 20.0
    loss_cooldown_minutes: int = 180
    flip_cooldown_minutes: int = 180
    deadman_switch_enabled: bool = False
    deadman_cancel_seconds: int = 300
    ioc_slippage_bps: float = 2.0
    ioc_slippage_spread_mult: float = 1.5
    ioc_slippage_max_bps: float = 8.0

    # Shared strategy policy (prompt, trigger_state, and research_gate)
    book_imbalance_threshold: float = 0.15
    tape_delta_threshold: float = 0.15
    vwap_near_pct: float = 0.005
    rsi_min: float = 35.0
    rsi_max: float = 65.0
    absorption_warning_threshold: float = 0.50
    absorption_hard_veto_threshold: float = 0.60
    reversal_absorption_threshold: float = 0.30
    fresh_initiation_book_threshold: float = 0.10
    fresh_initiation_delta_threshold: float = 0.15
    trigger_response_delta_threshold: float = 0.20
    trigger_tolerance_factor: float = 0.25
    funding_crowded_threshold: float = 0.001
    min_alignment_score: int = 5

    # Candles
    candle_hours: int = 24
    depth_levels: int = 10
    book_samples: int = 1
    book_sample_interval: float = 0.5
    tape_seconds: float = 2.0

    # Blocked coins (from V1 analysis: MON, PUMP consistently lose)
    blocked_coins: list[str] = field(default_factory=lambda: ["MON", "PUMP", "FARTCOIN"])

    # Data paths
    journal_path: str = "data/journal.jsonl"
    cvd_state_path: str = "data/cvd_state.json"
    ohlc_lessons_path: str = "data/ohlc_lessons.json"
    session_reset_hour_utc: int = 0

    # API
    api_url: str = "https://api.hyperliquid.xyz"
    coinglass_enabled: bool = True
    coinglass_base_url: str = "https://open-api-v4.coinglass.com"
    coinglass_exchange: str = "Hyperliquid"
    coinglass_range: str = "24h"
    coinglass_cache_seconds: int = 180
    coinglass_timeout: float = 8.0
    coinglass_prefer_pair_heatmap: bool = True
    coinglass_include_coin_liquidations: bool = True
    coinglass_include_funding_snapshot: bool = True
    coinglass_include_long_short_ratio: bool = True

    # LLM
    llm_base_url: str = "https://api.deepseek.com"
    llm_model: str = "deepseek-v4-flash"
    llm_temperature: float = 0.1
    llm_timeout: float = 45.0
    llm_thinking: str = "disabled"

    @classmethod
    def load(cls, path: str) -> Config:
        p = Path(path)
        if not p.exists():
            log_msg = f"Config not found: {path}, using defaults"
            print(log_msg)
            return cls()

        raw = toml.load(p)
        cfg = cls()

        # Map TOML keys to config
        for section_key in ("general", "account", "risk", "strategy", "candles", "data", "llm"):
            section = raw.get(section_key, {})
            for k, v in section.items():
                if hasattr(cfg, k):
                    setattr(cfg, k, v)

        # Blocked coins
        if "blocked_coins" in raw.get("general", {}):
            cfg.blocked_coins = raw["general"]["blocked_coins"]

        return cfg

    def to_dict(self) -> dict:
        return {
            "general": {
                "mode": self.mode,
                "interval_seconds": self.interval_seconds,
                "universe": self.universe,
                "max_coins": self.max_coins,
                "min_day_volume_usd": self.min_day_volume_usd,
                "blocked_coins": self.blocked_coins,
            },
            "account": {
                "equity_usd": self.equity_usd,
                "fixed_margin_usd": self.fixed_margin_usd,
                "max_leverage": self.max_leverage,
                "max_open_positions": self.max_open_positions,
            },
            "risk": {
                "max_risk_pct": self.max_risk_pct,
                "min_rr": self.min_rr,
                "min_confidence": self.min_confidence,
                "spread_max_bps": self.spread_max_bps,
                "max_daily_losses": self.max_daily_losses,
                "max_daily_trades": self.max_daily_trades,
                "fee_bps": self.fee_bps,
                "enable_break_even": self.enable_break_even,
                "enable_profit_lock": self.enable_profit_lock,
                "profit_lock_trigger_r": self.profit_lock_trigger_r,
                "profit_lock_fraction": self.profit_lock_fraction,
                "stop_atr_multiplier": self.stop_atr_multiplier,
                "min_stop_noise_multiple": self.min_stop_noise_multiple,
                "min_target_pct": self.min_target_pct,
                "min_target_atr_multiple": self.min_target_atr_multiple,
                "prefer_htf_targets": self.prefer_htf_targets,
                "enforce_min_target_distance": self.enforce_min_target_distance,
                "runner_target_rr": self.runner_target_rr,
                "max_target_rr": self.max_target_rr,
                "runner_min_confidence": self.runner_min_confidence,
                "ws_book_max_age_s": self.ws_book_max_age_s,
                "ws_tape_max_age_s": self.ws_tape_max_age_s,
                "loss_cooldown_minutes": self.loss_cooldown_minutes,
                "flip_cooldown_minutes": self.flip_cooldown_minutes,
                "deadman_switch_enabled": self.deadman_switch_enabled,
                "deadman_cancel_seconds": self.deadman_cancel_seconds,
                "ioc_slippage_bps": self.ioc_slippage_bps,
                "ioc_slippage_spread_mult": self.ioc_slippage_spread_mult,
                "ioc_slippage_max_bps": self.ioc_slippage_max_bps,
            },
            "strategy": {
                "book_imbalance_threshold": self.book_imbalance_threshold,
                "tape_delta_threshold": self.tape_delta_threshold,
                "vwap_near_pct": self.vwap_near_pct,
                "rsi_min": self.rsi_min,
                "rsi_max": self.rsi_max,
                "absorption_warning_threshold": self.absorption_warning_threshold,
                "absorption_hard_veto_threshold": self.absorption_hard_veto_threshold,
                "reversal_absorption_threshold": self.reversal_absorption_threshold,
                "fresh_initiation_book_threshold": self.fresh_initiation_book_threshold,
                "fresh_initiation_delta_threshold": self.fresh_initiation_delta_threshold,
                "trigger_response_delta_threshold": self.trigger_response_delta_threshold,
                "trigger_tolerance_factor": self.trigger_tolerance_factor,
                "funding_crowded_threshold": self.funding_crowded_threshold,
                "min_alignment_score": self.min_alignment_score,
                "min_stop_noise_multiple": self.min_stop_noise_multiple,
                "min_target_pct": self.min_target_pct,
                "min_target_atr_multiple": self.min_target_atr_multiple,
                "prefer_htf_targets": self.prefer_htf_targets,
                "enforce_min_target_distance": self.enforce_min_target_distance,
                "runner_target_rr": self.runner_target_rr,
                "max_target_rr": self.max_target_rr,
                "runner_min_confidence": self.runner_min_confidence,
            },
            "candles": {
                "candle_hours": self.candle_hours,
                "depth_levels": self.depth_levels,
                "book_samples": self.book_samples,
                "book_sample_interval": self.book_sample_interval,
                "tape_seconds": self.tape_seconds,
            },
            "data": {
                "journal_path": self.journal_path,
                "cvd_state_path": self.cvd_state_path,
                "ohlc_lessons_path": self.ohlc_lessons_path,
                "session_reset_hour_utc": self.session_reset_hour_utc,
                "api_url": self.api_url,
                "coinglass_enabled": self.coinglass_enabled,
                "coinglass_base_url": self.coinglass_base_url,
                "coinglass_exchange": self.coinglass_exchange,
                "coinglass_range": self.coinglass_range,
                "coinglass_cache_seconds": self.coinglass_cache_seconds,
                "coinglass_timeout": self.coinglass_timeout,
                "coinglass_prefer_pair_heatmap": self.coinglass_prefer_pair_heatmap,
                "coinglass_include_coin_liquidations": self.coinglass_include_coin_liquidations,
                "coinglass_include_funding_snapshot": self.coinglass_include_funding_snapshot,
                "coinglass_include_long_short_ratio": self.coinglass_include_long_short_ratio,
            },
            "llm": {
                "llm_base_url": self.llm_base_url,
                "llm_model": self.llm_model,
                "llm_temperature": self.llm_temperature,
                "llm_timeout": self.llm_timeout,
                "llm_thinking": self.llm_thinking,
            },
        }
