from __future__ import annotations

from decimal import Decimal
from typing import Any

from src.ctb_copy.models import CandidateStatus, LeaderMetrics
from src.ctb_copy.scoring.leader_scorecard import score_leader


def _metrics(**overrides: Any) -> LeaderMetrics:
    data: dict[str, Any] = dict(
        leader_id="leader-a",
        age_days=120,
        closed_shadow_trades=80,
        shadow_days=95,
        realized_pnl_usd=Decimal("250"),
        unrealized_pnl_share=Decimal("0.10"),
        max_drawdown_pct=Decimal("8"),
        profit_factor_after_costs=Decimal("1.45"),
        net_pnl_after_costs_usd=Decimal("120"),
        top_leader_pnl_share=Decimal("0.25"),
        top_coin_pnl_share=Decimal("0.30"),
        top_trade_pnl_share=Decimal("0.10"),
        single_coin_pnl_share=Decimal("0.30"),
        avg_liquidation_distance_pct=Decimal("25"),
        market_phases_observed=2,
        leader_correlation=Decimal("0.30"),
        coin_overlap=Decimal("0.25"),
        direction_overlap=Decimal("0.35"),
        regime_overlap=Decimal("0.40"),
        drawdown_overlap=Decimal("0.20"),
        crowding_score=Decimal("0.35"),
    )
    data.update(overrides)
    return LeaderMetrics(**data)


def test_live_preview_ready_requires_hard_90_day_and_75_trade_gates() -> None:
    score = score_leader(_metrics())
    assert score.status == CandidateStatus.LIVE_PREVIEW_READY


def test_candidate_not_live_when_only_one_market_phase_observed() -> None:
    score = score_leader(_metrics(market_phases_observed=1))
    assert score.status == CandidateStatus.CANDIDATE
    assert "less_than_two_market_phases_observed" in score.reasons


def test_blocks_survivor_like_concentration_and_hidden_hedge_risk() -> None:
    score = score_leader(_metrics(hidden_hedge_risk=True, single_coin_pnl_share=Decimal("0.70")))
    assert score.status == CandidateStatus.BLOCKED
    assert "hidden_hedge_risk_research_only" in score.reasons
    assert "single_coin_pnl_share_above_50pct" in score.reasons


def test_research_status_after_30_shadow_trades_but_before_candidate_sample() -> None:
    score = score_leader(_metrics(closed_shadow_trades=35, shadow_days=20, age_days=40))
    assert score.status == CandidateStatus.RESEARCH
