# source: https://raw.githubusercontent.com/4tie/fortiesr/d5cc40760e3cbaff381058a0ea8733d2be469578/backend/tests/test_helpers.py
"""backend/tests/test_helpers.py — Shared test helpers for Auto-Quant tests.

This file contains common test utilities used across all test files to avoid
duplication and provide a consistent testing environment.
"""

from __future__ import annotations

import asyncio
import uuid
from pathlib import Path

import backend.services.auto_quant.pipeline as pl
from backend.services.auto_quant.pipeline import (
    PipelineState,
    STAGE_NAMES,
    StageState,
    _cancel_flags,
    _queues,
    _states,
)

from backend.services.auto_quant.pipeline_modules.helpers import _extract_per_pair_results


def _run(coro):
    """Execute an async coroutine synchronously in a fresh event loop."""
    loop = asyncio.new_event_loop()
    try:
        return loop.run_until_complete(coro)
    finally:
        loop.close()


def _make_state(tmp_dir: str, **overrides) -> PipelineState:
    """Create and register a minimal PipelineState."""
    run_id = str(uuid.uuid4())
    stages = [StageState(index=i + 1, name=STAGE_NAMES[i]) for i in range(len(STAGE_NAMES))]
    
    # Create strategies directory and strategy file
    strategies_dir = Path(tmp_dir) / "strategies"
    strategies_dir.mkdir(parents=True, exist_ok=True)
    strategy_name = overrides.get("strategy", "AuditStrategy")
    strategy_file = strategies_dir / f"{strategy_name}.py"
    strategy_file.write_text("# fake strategy", encoding="utf-8")
    
    state = PipelineState(
        run_id=run_id,
        strategy=strategy_name,
        timeframe="1h",
        in_sample_range="20230101-20230601",
        out_sample_range="20230601-20231201",
        exchange="binance",
        config_file="/fake/config.json",
        freqtrade_path="freqtrade",
        user_data_dir=tmp_dir,
        stages=stages,
        created_at="2024-01-01T00:00:00+00:00",
    )
    for k, v in overrides.items():
        setattr(state, k, v)
    _states[run_id] = state
    _queues[run_id] = []
    _cancel_flags[run_id] = False
    return state


def _backtest_result(
    strategy: str,
    *,
    profit: float = 0.05,
    max_dd: float = 0.10,
    trades: int = 40,
    wins: int = 22,
    losses: int = 18,
    profit_factor: float = 1.4,
    sharpe: float = 1.2,
) -> dict:
    """Return a minimal Freqtrade-style backtest result dict."""
    return {
        "strategy": {
            strategy: {
                "profit_total": profit,
                "profit_total_abs": profit * 1000,
                "profit_mean": profit / max(trades, 1),
                "max_drawdown_account": max_dd,
                "total_trades": trades,
                "wins": wins,
                "losses": losses,
                "draws": 0,
                "win_rate": wins / max(trades, 1),
                "profit_factor": profit_factor,
                "sharpe_ratio": sharpe,
                "calmar_ratio": 1.1,
                "sortino_ratio": 1.2,
                "stake_currency": "USDT",
                "results_per_pair": [
                    {
                        "key": pair,
                        "profit_total": 0.03,
                        "profit_total_abs": 30.0,
                        "profit_mean": 0.002,
                        "trades": 2,
                        "wins": 1,
                        "losses": 1,
                        "profit_factor": 1.2,
                    }
                    for pair in pl.DEFAULT_STRESS_PAIRS
                ],
                "trades": [
                    {"close_date": f"2023-07-{(i % 28) + 1:02d}", "profit_ratio": 0.01 - (i % 5) * 0.005}
                    for i in range(trades)
                ],
            }
        }
    }


def _hyperopt_best(stoploss: float = -0.08) -> dict:
    return {
        "loss": -0.42,
        "params_dict": {
            "stoploss": stoploss,
            "trailing_stop": True,
            "trailing_stop_positive": 0.02,
            "trailing_stop_positive_offset": 0.03,
            "trailing_only_offset_is_reached": False,
            "minimal_roi": {"0": 0.10, "30": 0.05, "60": 0.02},
            "entry_logic": "macd_cross",
        },
        "params_details": {},
    }


def _write_strategy(strategies_dir: Path, name: str) -> Path:
    """Write a minimal strategy file that Stage 3 can patch."""
    src = strategies_dir / f"Github_4tie_fortiesr__test_helpers__20260709_213639.py"
    src.write_text(
        f"""
from freqtrade.strategy import IStrategy
from pandas import DataFrame


class Github_4tie_fortiesr__test_helpers__20260709_213639(IStrategy):
    INTERFACE_VERSION = 3
    minimal_roi = {{"0": 0.10, "60": 0.02}}
    stoploss = -0.10
    trailing_stop = False
    timeframe = "5m"

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        return dataframe

    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        return dataframe

    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        return dataframe
""",
        encoding="utf-8",
    )
    return src
