"""Gemeinsame Fixtures für die Szenario-Tests.

⚠⚠ DREI HARTE REGELN, damit diese Suite jederzeit gefahrlos läuft:
  1. **Nie die Live-DB anfassen.** Jeder Test bekommt eine frische Temp-Datei;
     `HistoryLogger.__init__` ruft `_init_db()` und legt das komplette Schema an.
     Die 15,7-MB-Live-DB zu kopieren wäre nicht nur langsam, sondern auch
     unzuverlässig — echte Zeilen haben mir am 06.08. einen Test verfälscht
     (echte `candles_m1` im vermeintlich leeren Fenster).
  2. **Kein MT5, kein laufender Server.** Alles, was den Broker berührt, wird
     gestubbt. Die Tests prüfen die LOGIK, nicht die Anbindung.
  3. **Keine Netzwerkzugriffe.**

Die Engine wird über `__new__` ohne `__init__` erzeugt: der echte Konstruktor
baut MT5-Verbindung, Threads und Config auf. Für die geprüften Methoden reichen
wenige Attribute — was fehlt, fällt im Test sofort als AttributeError auf und ist
damit dokumentiert, statt still zu passieren.
"""
import sys
import types
import logging
from pathlib import Path

import pytest

sys.path.insert(0, str(Path(__file__).resolve().parents[1]))

from core.candle_logger import CandleLogger    # noqa: E402
from core.engine import TradingEngine          # noqa: E402
from core.history import HistoryLogger         # noqa: E402


@pytest.fixture(autouse=True, scope="session")
def _kein_produktions_log():
    """VIERTE Grundregel der Suite: Tests schreiben NICHT ins Produktions-Log.

    ⚠⚠ ANLASS (2026-08-14, real passiert): beim Bau des M15-Alerts standen nach
    den Testläufen **über 150** `📨 M15-Alert`-Zeilen in `oil_widget.log` — dazu
    `Close-Push #4711` mit dem synthetischen Ticket aus `test_close_buchung.py`.
    Ich habe daraufhin zuerst geglaubt, die Entprellung sei live defekt, und
    musste die Herkunft mühsam an der Level-Folge (82.00, 82.01, …) nachweisen.
    In einem Projekt, dessen Forensik am Log hängt (der 18-h-Ausfall des
    Copiloten, der stille `positions_get`-Fehlbuchung), sind erfundene Zeilen
    im Produktions-Log ein echtes Risiko — nicht nur Unordnung.

    `core/logger.py` haengt einen `RotatingFileHandler` an den Logger `oil`,
    sobald `core.engine` importiert wird. Hier wird er fuer die Dauer der
    Sitzung entfernt und danach zurueckgegeben — die Log-AUFRUFE laufen weiter
    (sie gehoeren zum getesteten Code), nur ihr Ziel entfaellt.
    """
    lg = logging.getLogger("oil")
    weg = [h for h in lg.handlers if isinstance(h, logging.FileHandler)]
    for h in weg:
        lg.removeHandler(h)
    yield
    for h in weg:
        lg.addHandler(h)


@pytest.fixture
def db(tmp_path):
    """Frische, vollständig angelegte Test-Datenbank.

    ⚠ `candles_m1` gehört NICHT zum `HistoryLogger`-Schema, sondern wird vom
    `CandleLogger` angelegt (`core/candle_logger.py`). Beide werden hier über
    ihre ECHTEN Konstruktoren aufgerufen — ein von Hand nachgebautes Test-Schema
    würde irgendwann vom Produktivstand abweichen, und der Test prüfte dann etwas
    anderes als das, was live läuft.
    """
    p = tmp_path / "test.db"
    HistoryLogger(p)          # legt trades, recommendations, rec_outcomes, …
    CandleLogger(str(p))      # legt candles_m1
    return p


@pytest.fixture
def history(db):
    return HistoryLogger(db)


class FakeTrader:
    """Minimaler Trader-Ersatz: liefert genau den Snapshot, den der Test setzt."""

    def __init__(self):
        self.snap: dict = {}
        self.offset = 3 * 3600

    def snapshot(self):
        return self.snap

    def _broker_offset_s(self, sym=None):
        return self.offset


@pytest.fixture
def engine(history):
    """Nackte Engine ohne `__init__` — nur die Attribute, die geprüft werden."""
    e = TradingEngine.__new__(TradingEngine)
    e.history = history
    e.trader = FakeTrader()
    e.data = types.SimpleNamespace(symbol="XTIUSD")
    e.cfg = {"telegram": {"enabled": "false"}}
    # Zustand der geprüften Pfade
    e._pending_tickets = {}
    e._pending_tagged = set()
    e._bot_open_ticket = None
    e._bot_open_source = None
    e._squeeze_entry_count = 0
    e._signal_entry_count = 0
    e._rec_epi_sig = None
    e._rec_eval_ts = 0.0
    return e


@pytest.fixture
def db_umleiten(db, monkeypatch):
    """Leitet das modulweite `HISTORY_DB_FILE` der Engine auf die Test-DB um.

    ⚠ Nötig, weil `_evaluate_rec_outcomes` eine EIGENE sqlite3-Verbindung öffnet
    (bewusst — die Auswertung läuft außerhalb des HistoryLogger-Locks).
    """
    import core.engine as CE
    monkeypatch.setattr(CE, "HISTORY_DB_FILE", str(db))
    return db
