from __future__ import annotations

import json
from pathlib import Path

from src.tools.tradingview_paper_bridge import process_pending_tradingview_signals, summarize_tradingview_paper_bridge


def _append(path: Path, row: dict) -> None:
    path.parent.mkdir(parents=True, exist_ok=True)
    with path.open("a", encoding="utf-8") as fh:
        fh.write(json.dumps(row) + "\n")


def _signal(signal_id: str = "tv-1", **overrides) -> dict:
    row = {
        "source": "tradingview",
        "signal_id": signal_id,
        "strategy_id": "gaussian_channel_v1",
        "coin": "BTC",
        "side": "long",
        "action": "entry",
        "timeframe": "1h",
        "price": "60000",
        "timestamp": "2026-06-28T18:00:00Z",
        "execution_mode": "paper_signal",
        "live_order_allowed": False,
        "mainnet_signed_action": False,
        "order_intent_created": False,
    }
    row.update(overrides)
    return row


def test_process_pending_tradingview_signal_creates_paper_trade(tmp_path):
    _append(tmp_path / "signals" / "signal_journal.jsonl", _signal())

    result = process_pending_tradingview_signals(runtime_dir=tmp_path)

    assert result["processed"] == 1
    assert result["paper_trades"] == 1
    trade_rows = [json.loads(line) for line in (tmp_path / "experiments" / "tradingview_paper_bridge" / "trade_journal.jsonl").read_text(encoding="utf-8").splitlines()]
    assert len(trade_rows) == 1
    trade = trade_rows[0]
    assert trade["event"] == "paper_entry"
    assert trade["source"] == "tradingview"
    assert trade["coin"] == "BTC"
    assert trade["paper_trading"] is True
    assert trade["mainnet_signed_action"] is False
    assert trade["live_order_allowed"] is False
    assert trade["estimated_notional_usd"] == "11.25"


def test_bridge_is_idempotent_for_processed_signal(tmp_path):
    _append(tmp_path / "signals" / "signal_journal.jsonl", _signal())

    first = process_pending_tradingview_signals(runtime_dir=tmp_path)
    second = process_pending_tradingview_signals(runtime_dir=tmp_path)

    assert first["paper_trades"] == 1
    assert second["processed"] == 0
    trade_rows = (tmp_path / "experiments" / "tradingview_paper_bridge" / "trade_journal.jsonl").read_text(encoding="utf-8").splitlines()
    assert len(trade_rows) == 1


def test_bridge_blocks_unexpected_live_flag(tmp_path):
    _append(tmp_path / "signals" / "signal_journal.jsonl", _signal(live_order_allowed=True))

    result = process_pending_tradingview_signals(runtime_dir=tmp_path)

    assert result["paper_trades"] == 0
    assert result["blocked"]["unexpected_live_flag"] == 1
    decision_rows = [json.loads(line) for line in (tmp_path / "experiments" / "tradingview_paper_bridge" / "signal_decision_journal.jsonl").read_text(encoding="utf-8").splitlines()]
    assert decision_rows[0]["final_decision"] == "blocked:unexpected_live_flag"
    assert decision_rows[0]["mainnet_signed_action"] is False


def test_bridge_blocks_exit_without_open_position(tmp_path):
    _append(tmp_path / "signals" / "signal_journal.jsonl", _signal(action="exit"))

    result = process_pending_tradingview_signals(runtime_dir=tmp_path)

    assert result["paper_trades"] == 0
    assert result["paper_exits"] == 0
    assert result["blocked"]["exit_without_paper_position"] == 1


def test_bridge_closes_open_paper_position_and_records_pnl(tmp_path):
    _append(tmp_path / "signals" / "signal_journal.jsonl", _signal("entry-1", price="60000"))
    _append(tmp_path / "signals" / "signal_journal.jsonl", _signal("exit-1", action="exit", price="60600"))

    result = process_pending_tradingview_signals(runtime_dir=tmp_path)

    assert result["paper_trades"] == 1
    assert result["paper_exits"] == 1
    trade_rows = [json.loads(line) for line in (tmp_path / "experiments" / "tradingview_paper_bridge" / "trade_journal.jsonl").read_text(encoding="utf-8").splitlines()]
    assert [row["event"] for row in trade_rows] == ["paper_entry", "paper_exit"]
    exit_row = trade_rows[1]
    assert exit_row["coin"] == "BTC"
    assert exit_row["exit_price"] == "60600"
    assert float(exit_row["net_pnl_usd"]) > 0
    state = json.loads((tmp_path / "experiments" / "tradingview_paper_bridge" / "state.json").read_text(encoding="utf-8"))
    assert state["open_positions"] == {}


def test_summarize_tradingview_paper_bridge_counts_trades_and_blockers(tmp_path):
    _append(tmp_path / "signals" / "signal_journal.jsonl", _signal("tv-1"))
    _append(tmp_path / "signals" / "signal_journal.jsonl", _signal("tv-2", live_order_allowed=True))
    process_pending_tradingview_signals(runtime_dir=tmp_path)

    summary = summarize_tradingview_paper_bridge(tmp_path)

    assert summary["paper_entries"] == 1
    assert summary["paper_exits"] == 0
    assert summary["closed_net_pnl_usd"] == "0"
    assert summary["blocked"] == {"unexpected_live_flag": 1}
    assert summary["by_strategy"] == {"gaussian_channel_v1": 1}
    assert summary["by_coin"] == {"BTC": 1}
    assert summary["live_order_allowed_count"] == 0
