import os
import subprocess
import sys

import pandas as pd

from tools.compare_tv_trades import (
    apply_pine_time_gate,
    check_tv_entry_markers,
    run_python_strategy,
    strategy_stem,
    tv_score_column,
)


REPO = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
DATA_1D = os.path.join(REPO, "data", "mlp", "COINBASE_BTCUSD, 1D.csv")
MLP_PARAMS_1D = os.path.join(
    REPO,
    "results",
    "winners",
    "optimization_winner_strategy_mlp_scores_COINBASE_BTCUSD_1D.csv",
)


def test_strategy_stem_supports_activation_and_mlp_files():
    assert strategy_stem("strategy_activation_scores.py") == "activation_scores"
    assert strategy_stem("strategy_mlp_scores.py") == "mlp_scores"


def test_tv_score_column_prefers_available_export_score():
    assert tv_score_column(pd.DataFrame({"activation_score_poc": [1.0]})) == "activation_score_poc"
    assert tv_score_column(pd.DataFrame({"mlp_score": [1.0]})) == "mlp_score"
    assert tv_score_column(pd.DataFrame({"close": [1.0]})) is None


def test_tv_entry_marker_check_detects_export_mismatch():
    signals = pd.DataFrame({
        "time": pd.to_datetime([
            "2020-01-01 00:00",
            "2020-01-01 06:00",
            "2020-01-01 12:00",
        ]),
        "entry (standard)": [1.0, 0.0, 1.0],
        "missed entry": [0.0, 0.0, 1.0],
    })
    tv_trades = [{
        "trade_num": 1,
        "entry_dt": pd.Timestamp("2020-01-01 12:00"),
        "is_margin": False,
    }]

    result = check_tv_entry_markers(
        tv_trades,
        signals,
        "6H",
        pd.Timestamp("2020-01-01 00:00"),
        pd.Timestamp("2020-01-01 12:00"),
    )

    assert result["tv_with_marker"] == 0
    assert len(result["tv_without_marker"]) == 1
    assert result["chart_exec_count"] == 1
    assert result["chart_without_tv"] == [pd.Timestamp("2020-01-01 00:00")]


def test_pine_time_gate_starts_flat_at_score_start():
    signals = pd.DataFrame({
        "time": pd.to_datetime([
            "2017-11-29 00:00",
            "2017-11-30 00:00",
            "2017-12-01 00:00",
            "2017-12-01 12:00",
            "2017-12-02 00:00",
        ]),
        "activation_score": [100.0, -250.0, 100.0, -250.0, -300.0],
        "close": [100.0, 90.0, 100.0, 110.0, 120.0],
        "high": [100.0, 90.0, 100.0, 110.0, 120.0],
    })

    replayed = apply_pine_time_gate(
        signals,
        {
            "i_long_entry_activation_threshold": -200.0,
            "i_long_exit_activation_threshold": 50.0,
            "i_long_exit_activation_confirmation_threshold": -230.0,
            "i_use_long_exit_confirmation": True,
            "i_use_long_entry_confirmation": False,
            "i_trailing_stop_threshold": 0.0,
        },
        pd.Timestamp("2017-12-01"),
    )

    assert replayed["execute_entry"].tolist() == [False, False, False, True, False]
    assert replayed["execute_exit"].tolist() == [False, False, False, False, True]


def test_pine_time_gate_preserves_mlp_entry_smoothing():
    signals = pd.DataFrame({
        "time": pd.to_datetime([
            "2020-01-01 00:00",
            "2020-01-01 08:00",
            "2020-01-01 16:00",
            "2020-01-02 00:00",
        ]),
        "activation_score": [200.0, 200.0, 0.0, 0.0],
        "close": [100.0, 101.0, 102.0, 103.0],
        "high": [100.0, 101.0, 102.0, 103.0],
        "stoch_peak_norm": [0.0, 0.0, 0.0, 0.0],
    })
    signals.attrs["strategy_stem"] = "mlp_scores"

    replayed = apply_pine_time_gate(
        signals,
        {
            "i_long_entry_activation_threshold": 100.0,
            "i_long_exit_activation_threshold": 900.0,
            "i_long_exit_activation_confirmation_threshold": -900.0,
            "i_use_long_exit_confirmation": True,
            "i_use_long_entry_confirmation": False,
            "i_entry_score_window": 3,
            "i_exit_score_window": 3,
            "i_trailing_stop_threshold": 0.0,
        },
        pd.Timestamp("2020-01-01 16:00"),
    )

    assert replayed["execute_entry"].tolist() == [False, False, False, True]


def test_compare_tv_trades_can_run_mlp_strategy():
    params = pd.read_csv(MLP_PARAMS_1D).iloc[0].to_dict()
    signals = run_python_strategy(
        DATA_1D,
        params,
        strategy_file="strategy_mlp_scores.py",
    )

    assert "activation_score" in signals.columns
    assert "execute_entry" in signals.columns
    assert "execute_exit" in signals.columns
    assert signals["execute_entry"].sum() > 0


def test_validate_strategy_prints_canonical_metrics_section():
    result = subprocess.run(
        [
            sys.executable,
            "strategies/validate_strategy.py",
            "--data",
            DATA_1D,
            "--strategy_file",
            "strategy_mlp_scores.py",
            "--params_file",
            MLP_PARAMS_1D,
        ],
        cwd=REPO,
        capture_output=True,
        text=True,
        timeout=120,
        check=False,
    )

    assert result.returncode == 0, result.stderr
    assert "Trade-walk diagnostics" in result.stdout
    assert "Canonical optimizer metrics" in result.stdout
    assert "Source: strategy.calculate_metrics(signals, score_start=...)" in result.stdout
