from __future__ import annotations

import json
from datetime import datetime, timedelta, timezone

from src.strategies.trend_retest_anti_chase_v2 import STRATEGY_VERSION
from src.tools.v77_promotion_report import build_report


def _append(path, row):
    with path.open("a", encoding="utf-8") as handle:
        handle.write(json.dumps(row) + "\n")


def _healthy(runtime, strategy_id: str, version: str = STRATEGY_VERSION):
    _append(runtime / "runtime_health.jsonl", {
        "timestamp": datetime.now(timezone.utc).isoformat(),
        "status": "ok",
        "strategy_id": strategy_id,
        "strategy_version": version,
        "paper_trading": True,
        "live_order_allowed": False,
        "mainnet_signed_action": False,
    })


def test_v77_promotion_report_blocks_empty_or_legacy_only_runtime(tmp_path):
    runtime = tmp_path / "runtime"
    runtime.mkdir()
    _append(runtime / "trade_journal.jsonl", {"event": "exit", "strategy_version": "legacy", "net_pnl_usd": "999"})
    report = build_report(runtime)
    assert report["closed_lifecycles"] == 0
    assert report["promotion_eligible"] is False
    assert report["live_order_allowed"] is False
    assert "fresh_lifecycle_exits_50" in report["blockers"]
    assert "state_valid" in report["blockers"]
    assert "runtime_health_valid_and_fresh" in report["blockers"]


def test_v77_promotion_report_requires_and_accepts_diversified_net_evidence(tmp_path):
    runtime = tmp_path / "candidate_v77_trend_retest_anti_chase_long"
    runtime.mkdir()
    journal = runtime / "trade_journal.jsonl"
    start = datetime(2026, 6, 1, tzinfo=timezone.utc)
    coins = ["BTC", "ETH", "SOL", "LINK"]
    for idx in range(52):
        coin = coins[idx % len(coins)]
        stamp = start + timedelta(days=idx // 2)
        window = f"window-{idx}"
        common = {"strategy_id": runtime.name, "strategy_version": STRATEGY_VERSION, "run_id": "run-1", "data_window_id": window, "coin": coin, "proxy_inputs_used": False, "timestamp": stamp.isoformat()}
        _append(journal, {**common, "event": "entry", "stop_loss": "99", "entry_price": "100"})
        pnl = "1.0" if idx % 5 else "-0.5"
        gross = "1.1" if idx % 5 else "-0.4"
        _append(journal, {**common, "event": "exit", "gross_pnl_usd": gross, "net_pnl_usd": pnl, "exit_reason": "test"})
    (runtime / "state.json").write_text(json.dumps({"strategy_version": STRATEGY_VERSION, "open_positions": {}}), encoding="utf-8")
    _healthy(runtime, runtime.name)
    report = build_report(runtime)
    assert report["closed_lifecycles"] == 52
    assert report["unique_data_windows"] == 52
    assert report["profitable_weeks"] >= 3
    assert report["promotion_eligible"] is True
    assert report["recommendation"] == "eligible_for_manual_paper_evidence_review"
    assert report["execution_allowed"] is False
    assert report["schema_version"] == "v77_promotion_report.v2"
    (runtime / "state.json").write_text(json.dumps({"strategy_version": STRATEGY_VERSION, "open_positions": {}, "pending_orders": {"ETH": {"order": "pending"}}}), encoding="utf-8")
    pending_report = build_report(runtime)
    assert pending_report["pending_orders"] == 1
    assert pending_report["gates"]["no_open_positions_for_promotion"] is False
    assert pending_report["promotion_eligible"] is False
    (runtime / "state.json").write_text(json.dumps({"strategy_version": STRATEGY_VERSION, "open_positions": ["malformed"], "pending_orders": []}), encoding="utf-8")
    malformed_report = build_report(runtime)
    assert malformed_report["gates"]["lifecycle_state_containers_valid"] is False
    assert malformed_report["promotion_eligible"] is False


def test_report_blocks_duplicate_or_orphan_lifecycles_and_bad_json(tmp_path):
    runtime = tmp_path / "research_v77_bear_trend_retest_short"
    runtime.mkdir()
    common = {"strategy_id": runtime.name, "strategy_version": STRATEGY_VERSION, "run_id": "r", "data_window_id": "w", "coin": "BTC", "proxy_inputs_used": False, "timestamp": datetime.now(timezone.utc).isoformat()}
    _append(runtime / "trade_journal.jsonl", {**common, "event": "entry", "stop_loss": "101"})
    _append(runtime / "trade_journal.jsonl", {**common, "event": "entry", "stop_loss": "101"})
    _append(runtime / "trade_journal.jsonl", {**common, "event": "exit", "net_pnl_usd": "1"})
    with (runtime / "trade_journal.jsonl").open("a", encoding="utf-8") as handle:
        handle.write("{broken\n")
    (runtime / "state.json").write_text(json.dumps({"strategy_version": STRATEGY_VERSION, "open_positions": {}}), encoding="utf-8")
    _healthy(runtime, runtime.name)
    report = build_report(runtime)
    assert report["promotion_eligible"] is False
    assert report["integrity"]["invalid_trade_rows"] == 1
    assert report["integrity"]["duplicate_entries"] == 1
    assert "trade_jsonl_valid" in report["blockers"]
    assert "one_entry_one_final_exit" in report["blockers"]


def test_report_blocks_corrupt_state_stale_health_and_foreign_strategy(tmp_path):
    runtime = tmp_path / "candidate_v77_trend_retest_anti_chase_long"
    runtime.mkdir()
    common = {"strategy_id": "foreign", "strategy_version": STRATEGY_VERSION, "run_id": "r", "data_window_id": "w", "coin": "BTC", "proxy_inputs_used": False, "timestamp": datetime.now(timezone.utc).isoformat()}
    _append(runtime / "trade_journal.jsonl", {**common, "event": "entry", "stop_loss": "99"})
    _append(runtime / "trade_journal.jsonl", {**common, "event": "exit", "net_pnl_usd": "1"})
    (runtime / "state.json").write_text("{broken", encoding="utf-8")
    _append(runtime / "runtime_health.jsonl", {"timestamp": "2020-01-01T00:00:00+00:00", "status": "ok", "strategy_id": runtime.name, "strategy_version": STRATEGY_VERSION, "paper_trading": True, "live_order_allowed": False, "mainnet_signed_action": False})
    report = build_report(runtime)
    assert "strategy_identity_valid" in report["blockers"]
    assert "state_valid" in report["blockers"]
    assert "runtime_health_valid_and_fresh" in report["blockers"]
    assert "runtime_health_stale" in report["blockers"]


def test_report_quantifies_cost_efficiency_and_high_drag_winners(tmp_path):
    runtime = tmp_path / "research_v78_regime_router"
    runtime.mkdir()
    now = datetime.now(timezone.utc).isoformat()
    trades = [
        ("SOL", "w1", "0.130", "0.116"),
        ("ETH", "w2", "0.020", "0.007"),
        ("ETH", "w3", "-0.100", "-0.115"),
    ]
    for coin, window, gross, net in trades:
        common = {"strategy_id": runtime.name, "strategy_version": "v78.1.0", "run_id": "r", "data_window_id": window, "coin": coin, "timestamp": now, "proxy_inputs_used": False}
        _append(runtime / "trade_journal.jsonl", {**common, "event": "entry", "stop_loss": "99"})
        _append(runtime / "trade_journal.jsonl", {**common, "event": "exit", "gross_pnl_usd": gross, "net_pnl_usd": net})
    (runtime / "state.json").write_text(json.dumps({"strategy_version": "v78.1.0", "open_positions": {}}), encoding="utf-8")
    _healthy(runtime, runtime.name, version="v78.1.0")
    report = build_report(runtime, strategy_version="v78.1.0")
    assert report["cost_efficiency"]["coverage"] == "3/3"
    assert report["cost_efficiency"]["effective_costs_usd"] == "0.042"
    assert report["cost_efficiency"]["high_cost_drag_winners"] == 1
    assert report["cost_efficiency"]["winner_count"] == 2
    assert report["cost_efficiency"]["high_cost_drag_winner_share_pct"] == "50.0"
    assert report["gates"]["cost_efficiency_coverage_100pct"] is True
    assert report["gates"]["high_cost_drag_winner_share_max_20pct"] is False
