from __future__ import annotations

from pathlib import Path

import pytest

from crypto_spot_bot.config import Settings


@pytest.fixture
def make_settings():
    def factory(tmp_path: Path, **overrides) -> Settings:
        values = dict(
            trading_mode="paper",
            host="127.0.0.1",
            port=8787,
            bybit_testnet=False,
            bybit_api_key="",
            bybit_api_secret="",
            starting_balance_usdt=100.0,
            auto_select_symbols=True,
            top_symbols_count=6,
            symbols=(),
            strategy_mode="legacy",
            base_interval="60",
            kline_limit=240,
            trend_interval="D",
            trend_kline_limit=260,
            loop_interval_seconds=5,
            fast_trading_enabled=False,
            fast_loop_interval_seconds=1.0,
            fast_entry_cooldown_seconds=20,
            max_entries_per_minute=12,
            websocket_enabled=False,
            min_signal_confidence=0.64,
            max_spread_percent=0.18,
            min_24h_turnover_usdt=1_000_000.0,
            pattern_analysis_enabled=True,
            pattern_score_weight=0.18,
            learning_enabled=True,
            learning_lookback_trades=120,
            learning_min_samples=3,
            learning_max_adjustment=0.12,
            learning_max_position_multiplier=1.6,
            llm_advisor_enabled=False,
            ollama_base_url="http://192.168.0.210:11434",
            ollama_model="gemma4:e4b",
            llm_advisor_min_interval_seconds=180,
            llm_advisor_timeout_seconds=45,
            llm_advisor_max_adjustment=0.06,
            min_position_usdt=1.0,
            max_position_usdt=20.0,
            max_symbol_exposure_usdt=20.0,
            max_total_exposure_usdt=80.0,
            max_open_positions=6,
            max_positions_per_symbol=1,
            grid_trading_enabled=True,
            grid_entry_confidence=0.58,
            grid_buy_zone=0.45,
            grid_max_position_usdt=8.0,
            rebound_trading_enabled=True,
            rebound_entry_confidence=0.58,
            rebound_min_probability=0.58,
            rebound_max_position_usdt=6.0,
            kelly_sizing_enabled=True,
            kelly_fraction=0.25,
            kelly_max_fraction=0.20,
            risk_per_trade_percent=0.01,
            risk_guard_enabled=True,
            risk_symbol_guard_enabled=True,
            risk_recent_trade_window=20,
            risk_max_consecutive_losses=4,
            risk_min_recent_profit_factor=0.85,
            risk_reduce_multiplier=0.50,
            atr_trailing_multiplier=2.2,
            trend_rsi_min=45.0,
            trend_rsi_max=65.0,
            time_series_forecast_enabled=True,
            time_series_min_candles=120,
            time_series_forecast_horizon=3,
            time_series_min_edge_percent=0.08,
            time_series_min_probability_up=0.58,
            time_series_min_confidence=0.4,
            time_series_max_adjustment=0.08,
            time_series_lstm_enabled=True,
            time_series_lstm_model_path=tmp_path / "lstm_forecaster.json",
            time_series_probe_enabled=True,
            time_series_probe_min_edge_percent=0.02,
            time_series_probe_min_probability_up=0.55,
            time_series_probe_size_multiplier=0.40,
            time_series_rebound_fallback_enabled=True,
            stop_loss_percent=0.02,
            stop_loss_exit_enabled=True,
            take_profit_percent=0.035,
            trailing_stop_percent=0.015,
            min_hold_seconds=180,
            min_exit_net_percent=0.20,
            entry_cooldown_seconds=180,
            max_daily_drawdown_usdt=6.0,
            min_cash_reserve_usdt=5.0,
            taker_fee_rate=0.001,
            slippage_rate=0.0003,
            enable_live_trading=False,
            live_trading_confirm="",
            live_order_max_usdt=10.0,
            database_path=tmp_path / "tradebot.sqlite3",
            log_path=tmp_path / "tradebot.log",
            env_file_path=tmp_path / ".env",
        )
        values.update(overrides)
        return Settings(**values)

    return factory
