from decimal import Decimal

from src.execution.hyperliquid_testnet_executor import HyperliquidTestnetExecutor
from src.execution.order_intent import OrderIntent
from src.hyperliquid.rounding import HyperliquidAssetMeta


def _intent(**overrides):
    base = dict(
        strategy_id="candidate_v76_hl_confirmed_squeeze_hybrid",
        symbol="BTC/USDC:USDC",
        coin="BTC",
        side="buy",
        reduce_only=False,
        order_type="limit",
        tif="Alo",
        size=Decimal("0.010009"),
        price=Decimal("99999.9876"),
        trigger_price=None,
        stop_loss=Decimal("99000"),
        take_profit=Decimal("105000"),
        client_order_id="v76-BTC-1",
        reason="payload_smoke",
        risk_usd=Decimal("1.25"),
        estimated_notional_usd=Decimal("1000"),
    )
    base.update(overrides)
    return OrderIntent(**base)


def test_testnet_executor_builds_rounded_payload_without_exchange_call(monkeypatch):
    monkeypatch.setenv("CTB_HL_ENV", "testnet")
    executor = HyperliquidTestnetExecutor(exchange=None, expected_confirmation="TESTNET OK", dry_run=True)

    result = executor.prepare_payload(_intent(), HyperliquidAssetMeta("BTC", 0, 5), min_notional_usd=Decimal("10"))

    assert result.accepted is True
    assert result.payload["coin"] == "BTC"
    assert result.payload["size"] == "0.01000"
    assert result.payload["price"] == "99999"
    assert result.payload["order_type"] == "limit"
    assert result.payload["tif"] == "Alo"
    assert result.stop_loss_payload["reduce_only"] is True
    assert result.take_profit_payload["reduce_only"] is True


def test_testnet_executor_rejects_mainnet_env(monkeypatch):
    monkeypatch.setenv("CTB_HL_ENV", "mainnet")
    executor = HyperliquidTestnetExecutor(exchange=None, expected_confirmation="TESTNET OK", dry_run=True)

    result = executor.prepare_payload(_intent(), HyperliquidAssetMeta("BTC", 0, 5), min_notional_usd=Decimal("10"))

    assert result.accepted is False
    assert "testnet_env_required" in result.reasons


def test_testnet_executor_rejects_min_notional(monkeypatch):
    monkeypatch.setenv("CTB_HL_ENV", "testnet")
    executor = HyperliquidTestnetExecutor(exchange=None, expected_confirmation="TESTNET OK", dry_run=True)

    result = executor.prepare_payload(_intent(size=Decimal("0.00001")), HyperliquidAssetMeta("BTC", 0, 5), min_notional_usd=Decimal("10"))

    assert result.accepted is False
    assert "min_notional" in result.reasons
