"""Der Systemzustand im Tagesreport — sagt er die Wahrheit, und faellt er nie aus?

ANLASS (2026-08-11). Das Projekt hat sieben Waechter, und sie funktionieren. Was
fehlte, war der letzte Meter: die Marker-Datei `cfg_auto_sr_close` traegt den
Zeitstempel **06.08. 18:10** und wurde danach NIE wieder gemeldet — fuenf Tage
lang stand ein Exit aus, der am 11.08. mit **+350,81 EUR ueber 43 Trades**
gemessen wurde. Ursache ist ein Kategorienfehler: die Marker-Logik behandelt
einen DAUERZUSTAND wie ein EINMAL-EREIGNIS.

Deshalb die Trennung: Popup = „etwas Neues", Tagesreport = „so steht es gerade".

⚠ Die wichtigste Eigenschaft dieses Blocks ist, dass er NIE den Report sprengt.
Ein Report, der wegen der Statuszeile gar nicht ankommt, waere schlimmer als
gar keine Statuszeile — deshalb prueft der Test vor allem die Ausfallpfade.
"""
from __future__ import annotations

import pytest

from core.engine import TradingEngine
from core.history import HistoryLogger


class _Hist:
    def __init__(self, puls):
        self._puls = puls

    def telemetrie_puls(self):
        if isinstance(self._puls, Exception):
            raise self._puls
        return self._puls


class _Stub:
    _system_status = TradingEngine._system_status

    def __init__(self, *, brk=False, src=True, flip=False, puls=None):
        self._auto_squeeze = brk
        self._auto_sr_close = src
        self._flip_close = flip
        self.history = _Hist(puls if puls is not None else [])


def _text(z):
    return "\n".join(z)


def test_automatik_zeile_nennt_alle_schalter():
    """⚠ Seit dem 2026-08-12 sind es DREI — der Auto-Signal-Pfad (SIG) ist
    entfernt. Der Test zaehlt sie bewusst einzeln auf: verschwindet einer
    stillschweigend aus der Zeile, faellt es hier auf und nicht erst, wenn
    monatelang niemand merkt, dass ein Schalter aus ist (real geschehen:
    `auto_sr_close` stand 5 Tage aus, gemessener Wert +350,81 EUR)."""
    z = _text(_Stub(brk=True, src=True, flip=False)._system_status())
    assert "BRK AN" in z and "S/R-Close AN" in z and "Flip aus" in z
    assert "SIG" not in z, "der entfernte Pfad darf nicht wieder auftauchen"


def test_toter_logger_wird_gemeldet():
    """Der reale Fund: rec_outcomes stand 5 Tage bei 0 Zeilen."""
    z = _text(_Stub(puls=["rec_outcomes: 0 Zeilen — Logger hat NIE geschrieben"])
              ._system_status())
    assert "⚠ Puls:" in z and "rec_outcomes" in z


def test_stiller_puls_wird_ausdruecklich_bestaetigt():
    """⚠ Kein Befund muss SICHTBAR sein — eine fehlende Zeile liest sich sonst
    wie „nicht geprueft"."""
    z = _text(_Stub(puls=[])._system_status())
    assert "alle Telemetrie-Tabellen schreiben" in z


def test_puls_fehler_wird_gemeldet_nicht_verschluckt():
    """⚠ Genau die Fehlerklasse, die rec_outcomes 5 Tage verbarg: ein stiller
    Fallback saehe aus wie „alles gut"."""
    z = _text(_Stub(puls=RuntimeError("DB weg"))._system_status())
    assert "⚠ Puls: Prüfung fehlgeschlagen" in z and "DB weg" in z


def test_ohne_history_kein_absturz():
    s = _Stub()
    s.history = None
    z = _text(s._system_status())
    assert "Automatik:" in z            # der Rest laeuft weiter


def test_liefert_immer_zeilen_und_wirft_nie():
    """Die Kern-Invariante: der Tagesreport darf an dieser Zeile nicht scheitern."""
    for kw in ({}, {"brk": True}, {"puls": RuntimeError("x")}):
        z = _Stub(**kw)._system_status()
        assert isinstance(z, list) and z, "muss immer mindestens eine Zeile liefern"
        assert all(isinstance(x, str) for x in z)


def test_puls_tabellenliste_ist_vollstaendig():
    """Jede Telemetrie-Tabelle, die das Projekt schreibt, muss ueberwacht sein —
    sonst entsteht genau die Luecke wieder, die rec_outcomes hatte."""
    ueberwacht = {t for t, *_ in HistoryLogger.PULS}
    for t in ("recommendations", "candles_m1", "verdict_votes", "m15_states",
              "cone_checks", "pbreak_predictions", "rec_outcomes"):
        assert t in ueberwacht, f"{t} wird nicht ueberwacht"


if __name__ == "__main__":
    raise SystemExit(pytest.main([__file__, "-v"]))
