from __future__ import annotations

import json
from typing import Any, cast

from fastapi.testclient import TestClient

from jarvis_gateway.main import app
from jarvis_gateway.services import finance_trader_desk


def _scorecard() -> dict[str, object]:
    return {
        "schema_version": "trader_desk_shadow_scorecard.v1",
        "generated_at": "2026-06-30T12:15:00+00:00",
        "source": {"decisions_path": "/tmp/should-not-leak"},
        "overall": {"decisions": 8, "tiny_live_candidates": 1, "watch_shadow": 5, "blocked": 2, "closed": 3, "wins": 2, "losses": 1, "scratch": 0, "win_rate_pct": "66.67", "realized_r": "1.2500", "avg_r": "0.4167", "closure_rate_pct": "37.50"},
        "open_shadow_positions": 1,
        "open_positions": [{"coin": "ETH", "side": "long", "entry": "100", "stop_loss": "98", "take_profit": {"tp1": "103"}, "score": "78.00", "action": "watch_shadow", "setup": "trend_retest_continuation", "opened_at": "2026-06-30T12:00:00+00:00"}],
        "by_coin": {"ETH": {"decisions": 2, "closed": 1, "wins": 1, "losses": 0, "realized_r": "1.0000"}},
        "by_action": {"watch_shadow": {"decisions": 5, "closed": 2, "wins": 1, "losses": 1, "realized_r": "0.5000"}},
        "by_setup": {"trend_retest_continuation": {"decisions": 6, "closed": 3, "wins": 2, "losses": 1, "realized_r": "1.2500"}},
        "by_score_bucket": {"75_80": {"decisions": 3, "closed": 1, "wins": 1, "losses": 0, "realized_r": "1.0000"}},
        "safety_boundary": {"paper_only": True, "dashboard_executes_orders": True, "execution_allowed": True, "live_order_allowed": True, "mainnet_signed_action": True},
        "paper_only": True,
        "live_order_allowed": True,
        "mainnet_signed_action": True,
    }


def _snapshot() -> dict[str, object]:
    return {
        "schema_version": "finance_crypto_trader_desk_bridge.v1",
        "generated_at": "2026-06-30T12:00:00+00:00",
        "market_regime": "risk_on",
        "summary": {"tiny_live_candidates": 1, "watch_shadow": 2, "blocked": 3, "best_coin": "BTC", "best_action": "tiny_live_candidate", "best_score": "84.00", "next_step": "run_final_preflight_before_any_live_order"},
        "trade_intents": [
            {
                "intent_id": "abc123",
                "coin": "BTC",
                "side": "long",
                "signal": "tiny_live_candidate",
                "mode": "approval",
                "status": "awaiting_final_preflight",
                "confidence_score": "84.00",
                "setup": "trend_retest_continuation",
                "entry_zone": {"low": "100", "high": "101"},
                "stop_loss": "98",
                "take_profit": {"tp1": "103", "tp2": "105"},
                "notional_cap_usdc": "15",
                "blockers": [],
                "reasons": ["research_only"],
                "execution_allowed": True,  # service must force false
                "dashboard_executes_orders": True,
                "mainnet_signed_action": True,
            }
        ],
        "safety_boundary": {},
        "live_order_allowed": True,
        "mainnet_signed_action": True,
    }


def test_trader_desk_endpoint_returns_sanitized_readonly_snapshot(tmp_path, monkeypatch) -> None:
    path = tmp_path / "trader_desk_latest.json"
    path.write_text(json.dumps(_snapshot()), encoding="utf-8")
    monkeypatch.setattr(finance_trader_desk, "DEFAULT_TRADER_DESK_BRIDGE_PATH", path)
    client = TestClient(app)

    response = client.get("/api/finance/trader-desk")

    assert response.status_code == 200
    payload = response.json()
    assert payload["status"] == "ok"
    assert payload["summary"]["tiny_live_candidates"] == 1
    assert payload["safety_boundary"]["dashboard_executes_orders"] is False
    assert payload["safety_boundary"]["execution_allowed"] is False
    assert payload["live_order_allowed"] is False
    assert payload["mainnet_signed_action"] is False
    intent = payload["trade_intents"][0]
    assert intent["coin"] == "BTC"
    assert intent["execution_allowed"] is False
    assert intent["dashboard_executes_orders"] is False
    assert intent["mainnet_signed_action"] is False
    assert str(tmp_path) not in response.text


def test_trader_desk_endpoint_missing_file_is_safe(monkeypatch, tmp_path) -> None:
    monkeypatch.setattr(finance_trader_desk, "DEFAULT_TRADER_DESK_BRIDGE_PATH", tmp_path / "missing.json")
    client = TestClient(app)

    response = client.get("/api/finance/trader-desk")

    assert response.status_code == 200
    payload = response.json()
    assert payload["status"] == "not_configured"
    assert payload["trade_intents"] == []
    assert payload["safety_boundary"]["execution_allowed"] is False


def test_trader_desk_scorecard_endpoint_returns_sanitized_shadow_evidence(tmp_path, monkeypatch) -> None:
    path = tmp_path / "trader_desk_scorecard_latest.json"
    path.write_text(json.dumps(_scorecard()), encoding="utf-8")
    monkeypatch.setattr(finance_trader_desk, "DEFAULT_TRADER_DESK_SCORECARD_PATH", path)
    client = TestClient(app)

    response = client.get("/api/finance/trader-desk/scorecard")

    assert response.status_code == 200
    payload = response.json()
    assert payload["status"] == "ok"
    assert payload["schema_version"] == "trader_desk_shadow_scorecard.v1"
    assert payload["overall"]["decisions"] == 8
    assert payload["overall"]["avg_r"] == "0.4167"
    assert payload["open_shadow_positions"] == 1
    assert payload["open_positions"][0]["coin"] == "ETH"
    assert payload["by_score_bucket"]["75_80"]["decisions"] == 3
    assert payload["safety_boundary"]["dashboard_executes_orders"] is False
    assert payload["safety_boundary"]["execution_allowed"] is False
    assert payload["live_order_allowed"] is False
    assert payload["mainnet_signed_action"] is False
    assert str(tmp_path) not in response.text
    assert "should-not-leak" not in response.text


def test_trader_desk_scorecard_endpoint_missing_file_is_safe(monkeypatch, tmp_path) -> None:
    monkeypatch.setattr(finance_trader_desk, "DEFAULT_TRADER_DESK_SCORECARD_PATH", tmp_path / "missing_scorecard.json")
    client = TestClient(app)

    response = client.get("/api/finance/trader-desk/scorecard")

    assert response.status_code == 200
    payload = response.json()
    assert payload["status"] == "not_configured"
    assert payload["overall"]["decisions"] == 0
    assert payload["open_positions"] == []
    assert payload["safety_boundary"]["execution_allowed"] is False


def test_trader_desk_preflight_missing_file_derives_readonly_gates(tmp_path, monkeypatch) -> None:
    snapshot_path = tmp_path / "trader_desk_latest.json"
    scorecard_path = tmp_path / "trader_desk_scorecard_latest.json"
    preflight_path = tmp_path / "missing_preflight.json"
    snapshot_path.write_text(json.dumps(_snapshot()), encoding="utf-8")
    scorecard = _scorecard()
    overall = dict(cast(dict[str, Any], scorecard["overall"]))
    overall.update({"closed": 10, "win_rate_pct": "30.00", "realized_r": "0.3096"})
    scorecard["overall"] = overall
    scorecard_path.write_text(json.dumps(scorecard), encoding="utf-8")
    monkeypatch.setattr(finance_trader_desk, "DEFAULT_TRADER_DESK_BRIDGE_PATH", snapshot_path)
    monkeypatch.setattr(finance_trader_desk, "DEFAULT_TRADER_DESK_SCORECARD_PATH", scorecard_path)
    monkeypatch.setattr(finance_trader_desk, "DEFAULT_TRADER_DESK_PREFLIGHT_PATH", preflight_path)
    client = TestClient(app)

    response = client.get("/api/finance/trader-desk/preflight")

    assert response.status_code == 200
    payload = response.json()
    assert payload["status"] == "not_configured"
    assert payload["schema_version"] == "trader_desk_tiny_live_preflight.v1"
    assert payload["preflight_status"] == "fail"
    assert payload["current_intent"]["coin"] == "BTC"
    assert "shadow_sample" in payload["blockers"]
    assert "shadow_winrate" in payload["blockers"]
    assert "final_bot_preflight" in payload["blockers"]
    assert payload["safety_boundary"]["dashboard_executes_orders"] is False
    assert payload["execution_allowed"] is False
    assert payload["live_order_allowed"] is False
    assert payload["mainnet_signed_action"] is False
    assert str(tmp_path) not in response.text


def test_trader_desk_preflight_endpoint_sanitizes_runtime_export(tmp_path, monkeypatch) -> None:
    path = tmp_path / "trader_desk_tiny_live_preflight_latest.json"
    path.write_text(json.dumps({
        "schema_version": "trader_desk_tiny_live_preflight.v1",
        "generated_at": "2026-07-01T08:00:00+00:00",
        "preflight_status": "pass",
        "readiness_label": "Tiny-Live Ready",
        "current_intent": {"coin": "SOL", "side": "long", "signal": "tiny_live_candidate", "confidence_score": "81.00", "status": "awaiting_final_preflight", "setup": "trend_retest"},
        "gates": [{"key": "signed_credentials", "label": "Signed Credentials", "status": "pass", "reason": "ok", "severity": "success"}],
        "blockers": [],
        "reason": "all good but dashboard still cannot execute /home/agent/secret",
        "safety_boundary": {"dashboard_executes_orders": True, "execution_allowed": True, "live_order_allowed": True, "mainnet_signed_action": True},
        "execution_allowed": True,
        "live_order_allowed": True,
        "mainnet_signed_action": True,
    }), encoding="utf-8")
    monkeypatch.setattr(finance_trader_desk, "DEFAULT_TRADER_DESK_PREFLIGHT_PATH", path)
    client = TestClient(app)

    response = client.get("/api/finance/trader-desk/preflight")

    assert response.status_code == 200
    payload = response.json()
    assert payload["status"] == "ok"
    assert payload["preflight_status"] == "pass"
    assert payload["current_intent"]["coin"] == "SOL"
    assert payload["safety_boundary"]["dashboard_executes_orders"] is False
    assert payload["execution_allowed"] is False
    assert payload["live_order_allowed"] is False
    assert payload["mainnet_signed_action"] is False
    assert "/home/agent" not in response.text
