"""
Slow acceptance test: verifies the full train_mlp → validate_strategy pipeline.

Marked @pytest.mark.slow — skipped by default in quick test runs.
Run with: /usr/bin/python3 -m pytest tests/test_acceptance_mlp.py -m slow -s

What it checks:
  1. train_mlp.py --smoke produces a valid weights artifact.
  2. The artifact loads, has the expected structure, and feature_cols match FEATURE_COLS.
  3. validate_strategy.py with the artifact's recommended_thresholds runs successfully
     and returns finite (non-NaN, non-None) metrics.
"""
import json
import os
import subprocess
import sys

import numpy as np
import pytest

REPO = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
PYTHON = "/usr/bin/python3"
DATA_6H = os.path.join(REPO, "data", "COINBASE_BTCUSD-6H.csv")


def _run(cmd, cwd=REPO, timeout=300):
    result = subprocess.run(
        cmd, cwd=cwd, capture_output=True, text=True, timeout=timeout
    )
    return result


@pytest.mark.slow
@pytest.mark.skipif(not os.path.exists(DATA_6H), reason="data CSV not found")
class TestAcceptanceMLP:
    def test_smoke_train_produces_valid_artifact(self, tmp_path):
        out = str(tmp_path / "mlp_weights_TEST_6H.json")
        result = _run([PYTHON, "tools/train_mlp.py",
                       "--data", DATA_6H, "--smoke", "--out", out])
        assert result.returncode == 0, (
            f"train_mlp --smoke failed:\n{result.stdout}\n{result.stderr}"
        )
        assert os.path.exists(out), "Artifact not written"

        with open(out) as f:
            payload = json.load(f)

        assert payload.get("version") == 1
        assert "layers" in payload and len(payload["layers"]) >= 2
        assert payload.get("arch") == [49, 8, 4, 1], (
            f"Smoke arch should be [49,8,4,1], got {payload.get('arch')}"
        )
        assert "recommended_thresholds" in payload.get("training", {})

        sys.path.insert(0, REPO)
        from strategies.strategy_mlp_scores import FEATURE_COLS, load_mlp_artifact
        art = load_mlp_artifact(out)
        assert art["feature_cols"] == FEATURE_COLS, "Artifact feature_cols mismatch"
        for W, b in art["layers"]:
            assert np.all(np.isfinite(W)), "W contains non-finite values"
            assert np.all(np.isfinite(b)), "b contains non-finite values"

    def test_validate_strategy_runs_with_artifact(self, tmp_path):
        out = str(tmp_path / "mlp_weights_TEST_6H.json")
        train_result = _run([PYTHON, "tools/train_mlp.py",
                             "--data", DATA_6H, "--smoke", "--out", out])
        assert train_result.returncode == 0, (
            f"train_mlp failed:\n{train_result.stderr}"
        )

        with open(out) as f:
            payload = json.load(f)
        rec = payload["training"]["recommended_thresholds"]
        params = {
            "mlp_weights_file": out,
            "i_long_entry_activation_threshold": rec.get("i_long_entry_activation_threshold", 0.0),
            "i_long_exit_activation_threshold": rec.get("i_long_exit_activation_threshold", 0.0),
            "i_long_exit_activation_confirmation_threshold": rec.get("i_long_exit_activation_confirmation_threshold", 0.0),
            "i_use_long_exit_confirmation": rec.get("i_use_long_exit_confirmation", 1.0),
            "i_use_long_entry_confirmation": rec.get("i_use_long_entry_confirmation", False),
            "i_trailing_stop_threshold": rec.get("i_trailing_stop_threshold", 0.0),
            "i_regime_window": 0,
            "i_regime_entry_min_score": -1000.0,
            "i_mvrv_suppress_bear": False,
        }
        params_file = str(tmp_path / "test_params.json")
        with open(params_file, "w") as f:
            json.dump(params, f)

        validate_result = _run([
            PYTHON, "strategies/validate_strategy.py",
            "--data", DATA_6H,
            "--strategy_file", "strategy_mlp_scores.py",
            "--params_file", params_file,
        ], timeout=120)
        assert validate_result.returncode == 0, (
            f"validate_strategy failed:\n{validate_result.stdout}\n{validate_result.stderr}"
        )
        out_text = validate_result.stdout
        assert "Total Trades" in out_text, (
            f"Expected metrics in output, got:\n{out_text[:2000]}"
        )
        # Verify no NaN in the numeric metrics reported
        for line in out_text.splitlines():
            if "nan" in line.lower() and any(kw in line for kw in ("Calmar", "Sharpe", "P&L")):
                pytest.fail(f"NaN found in metric line: {line}")
