from __future__ import annotations

import json

from src.tools import trader_desk_shadow_scorecard as scorecard


def _write_jsonl(path, rows):
    path.parent.mkdir(parents=True, exist_ok=True)
    path.write_text("\n".join(json.dumps(row, sort_keys=True) for row in rows) + "\n", encoding="utf-8")


def test_shadow_scorecard_summarizes_decisions_outcomes_and_open_positions(tmp_path):
    runtime = tmp_path / "shadow"
    decisions = runtime / "decision_journal.jsonl"
    outcomes = runtime / "outcome_journal.jsonl"
    state = runtime / "state.json"
    _write_jsonl(decisions, [
        {"event": "desk_decision", "coin": "BTC", "action": "tiny_live_candidate", "score": "84.5", "setup": "trend_retest_continuation"},
        {"event": "desk_decision", "coin": "ETH", "action": "watch_shadow", "score": "78.0", "setup": "trend_retest_continuation"},
        {"event": "desk_decision", "coin": "SOL", "action": "no_trade", "score": "65.0", "setup": "no_trade"},
    ])
    _write_jsonl(outcomes, [
        {"event": "shadow_open", "coin": "BTC"},
        {"event": "shadow_close", "coin": "BTC", "side": "long", "bucket": "win", "r_multiple": "1.2500"},
        {"event": "shadow_close", "coin": "ETH", "side": "long", "bucket": "loss", "r_multiple": "-0.5000"},
    ])
    state.write_text(json.dumps({
        "positions": {
            "LINK": {
                "side": "long",
                "entry": "10",
                "stop_loss": "9.8",
                "take_profit": {"tp1": "10.5"},
                "score": "76",
                "action": "watch_shadow",
                "setup": "trend_retest_continuation",
                "opened_at": "2026-06-30T00:00:00+00:00",
            }
        },
        "paper_only": True,
        "live_order_allowed": False,
        "mainnet_signed_action": False,
    }), encoding="utf-8")

    payload = scorecard.build_scorecard(decisions_path=decisions, outcomes_path=outcomes, state_path=state)

    assert payload["schema_version"] == "trader_desk_shadow_scorecard.v1"
    assert payload["safety_boundary"]["paper_only"] is True
    assert payload["live_order_allowed"] is False
    assert payload["mainnet_signed_action"] is False
    assert payload["overall"]["decisions"] == 3
    assert payload["overall"]["tiny_live_candidates"] == 1
    assert payload["overall"]["watch_shadow"] == 1
    assert payload["overall"]["blocked"] == 1
    assert payload["overall"]["closed"] == 2
    assert payload["overall"]["wins"] == 1
    assert payload["overall"]["losses"] == 1
    assert payload["overall"]["realized_r"] == "0.7500"
    assert payload["overall"]["avg_r"] == "0.3750"
    assert payload["by_score_bucket"]["80_85"]["decisions"] == 1
    assert payload["by_score_bucket"]["75_80"]["decisions"] == 1
    assert payload["by_score_bucket"]["below_70"]["decisions"] == 1
    assert payload["open_shadow_positions"] == 1
    assert payload["open_positions"][0]["coin"] == "LINK"


def test_shadow_scorecard_cli_writes_runtime_and_finance_outputs(tmp_path, capsys):
    runtime = tmp_path / "shadow"
    _write_jsonl(runtime / "decision_journal.jsonl", [
        {"event": "desk_decision", "coin": "BTC", "action": "watch_shadow", "score": "77", "setup": "trend_retest_continuation"},
    ])
    (runtime / "state.json").write_text(json.dumps({"positions": {}}), encoding="utf-8")
    output = tmp_path / "scorecard.json"
    finance_output = tmp_path / "finance" / "trader_desk_scorecard_latest.json"

    assert scorecard.main([
        "--runtime-dir", str(runtime),
        "--output", str(output),
        "--finance-output", str(finance_output),
        "--json",
    ]) == 0

    result = json.loads(capsys.readouterr().out)
    assert result["status"] == "ok"
    assert result["paper_only"] is True
    assert output.exists()
    assert finance_output.exists()
    payload = json.loads(finance_output.read_text())
    assert payload["overall"]["decisions"] == 1
    assert payload["safety_boundary"]["dashboard_executes_orders"] is False
