import importlib
import json
import os
from pathlib import Path

import pytest


def test_config_loads_strategy_parameters_and_env_overrides(tmp_path, monkeypatch):
    config_path = tmp_path / "strategy_config.json"
    config_path.write_text(json.dumps({
        "parameters": {
            "max_total_trades": 2,
            "default_leverage": 4,
            "trade_size_usd": 25,
            "wallet_equity_usdc": 500,
            "risk_per_trade_pct": 0.75,
            "position_sizing_mode": "risk",
            "max_position_margin_pct": 20,
            "max_position_notional_pct": 60,
            "min_order_notional_usd": 12,
            "flash_crash_trigger_pct": 3.5,
            "cooldown_minutes": 45,
            "dry_run": False,
            "runtime_dir": str(tmp_path / "runtime-from-config"),
        },
        "filters": {"min_volume_24h": 12345},
        "blacklist": ["BAD"]
    }))
    monkeypatch.setenv("CTB_DRY_RUN", "true")
    monkeypatch.setenv("CTB_RUNTIME_DIR", str(tmp_path / "runtime-from-env"))

    from config import BotConfig

    cfg = BotConfig.from_file(config_path)

    assert cfg.max_total_trades == 2
    assert cfg.default_leverage == 4
    assert cfg.trade_size_usd == 25
    assert cfg.wallet_equity_usdc == 500
    assert cfg.risk_per_trade_pct == 0.75
    assert cfg.position_sizing_mode == "risk"
    assert cfg.max_position_margin_pct == 20
    assert cfg.max_position_notional_pct == 60
    assert cfg.min_order_notional_usd == 12
    assert cfg.flash_crash_trigger_pct == 3.5
    assert cfg.cooldown_minutes == 45
    assert cfg.min_volume_24h == 12345
    assert cfg.blacklist == ("BAD",)
    assert cfg.dry_run is True
    assert cfg.runtime_dir == tmp_path / "runtime-from-env"


def test_runtime_paths_are_created_outside_repo(tmp_path):
    from config import BotConfig, RuntimePaths

    cfg = BotConfig(runtime_dir=tmp_path / "runtime")
    paths = RuntimePaths.from_config(cfg)
    paths.ensure_dirs()

    assert paths.runtime_dir == tmp_path / "runtime"
    assert paths.tradeanalyse_dir.exists()
    assert paths.reports_dir.exists()
    assert paths.trading_log.parent == paths.tradeanalyse_dir
    assert paths.trade_journal.parent == paths.tradeanalyse_dir


def test_dry_run_executor_records_without_calling_exchange(tmp_path):
    from execution import TradingExecutor

    calls = []

    class FakeExchange:
        def set_leverage(self, *args, **kwargs):
            calls.append(("set_leverage", args, kwargs))

        def create_order(self, *args, **kwargs):
            calls.append(("create_order", args, kwargs))

    executor = TradingExecutor(FakeExchange(), dry_run=True)

    assert executor.set_leverage(5, "BTC/USDC:USDC")["dry_run"] is True
    assert executor.create_order("BTC/USDC:USDC", "market", "buy", 0.01, 100.0)["dry_run"] is True
    assert calls == []


def test_live_executor_delegates_to_exchange(monkeypatch):
    from execution import TradingExecutor
    monkeypatch.setenv("CTB_ALLOW_LEGACY_EXECUTION", "true")

    calls = []

    class FakeExchange:
        def set_leverage(self, *args, **kwargs):
            calls.append(("set_leverage", args, kwargs))
            return {"status": "ok"}

        def create_order(self, *args, **kwargs):
            calls.append(("create_order", args, kwargs))
            return {"status": "ok"}

    executor = TradingExecutor(FakeExchange(), dry_run=False)

    assert executor.set_leverage(5, "BTC/USDC:USDC") == {"status": "ok"}
    assert executor.create_order("BTC/USDC:USDC", "market", "buy", 0.01, 100.0) == {"status": "ok"}
    assert calls[0][0] == "set_leverage"
    assert calls[1][0] == "create_order"
