from __future__ import annotations

from decimal import Decimal
from typing import Any

from src.ctb_copy.models import PositionCopySignal, SignalDecision
from src.ctb_copy.risk.copy_pretrade_gate import evaluate_copy_signal


def _signal(**overrides: Any) -> PositionCopySignal:
    data: dict[str, Any] = dict(
        leader_id="leader-a",
        coin="BTC",
        side="long",
        position_age_hours=Decimal("12"),
        leader_profit_r=Decimal("0.2"),
        distance_to_leader_entry_pct=Decimal("0.2"),
        spread_pct=Decimal("0.02"),
        depth_ok=True,
        leader_liquidation_distance_pct=Decimal("20"),
        funding_rate_hourly_pct=Decimal("0.005"),
        duplicate_exposure=False,
        is_position_level=True,
    )
    data.update(overrides)
    return PositionCopySignal(**data)


def test_allows_clean_position_level_signal_for_shadow_only() -> None:
    decision = evaluate_copy_signal(_signal())
    assert decision.decision == SignalDecision.ALLOW_SHADOW
    assert decision.reasons == ("ok_for_shadow_only",)


def test_blocks_fill_level_and_young_position() -> None:
    decision = evaluate_copy_signal(_signal(is_position_level=False, position_age_hours=Decimal("1")))
    assert decision.decision == SignalDecision.BLOCK
    assert "fill_level_copying_disabled" in decision.reasons
    assert "position_age_below_6h" in decision.reasons


def test_blocks_chasing_bad_funding_and_duplicate_exposure() -> None:
    decision = evaluate_copy_signal(
        _signal(
            leader_profit_r=Decimal("0.8"),
            distance_to_leader_entry_pct=Decimal("1.2"),
            funding_rate_hourly_pct=Decimal("0.05"),
            duplicate_exposure=True,
        )
    )
    assert decision.decision == SignalDecision.BLOCK
    assert "leader_already_above_0_5r_profit" in decision.reasons
    assert "distance_to_leader_entry_too_large" in decision.reasons
    assert "funding_extreme" in decision.reasons
    assert "duplicate_exposure_already_present" in decision.reasons
