"""Smoke ESECUZIONE REALE a 2 gambe (PairsExecutionClient) su Deribit testnet.

Apre e chiude una posizione pair micro (ETH/BTC lineari USDC) come farebbe il
PairsWorker, esercitando: open_pair (2 market simultanei long A/short B), verifica
per-gamba, close_pair (2 reduce-only), riconciliazione PnL/fee a 2 gambe.
Verifica finale: conto flat su ENTRAMBI gli strumenti.

Costo testnet = €0. Non tocca lo stato di produzione (data_dir temporanea).

    uv run python scripts/analysis/live_pairs_smoke.py
"""
from __future__ import annotations

import tempfile
from pathlib import Path

from src.live.cerbero_client import CerberoClient
from src.live.execution import ExecutionClient, PairsExecutionClient
from src.live.pairs_worker import PairsWorker


def main() -> None:
    client = CerberoClient()
    acct = client.get_account_summary(currency="USDC")
    print(f"Account testnet equity={acct.get('equity')} USDC testnet={acct.get('testnet')}")
    if not acct.get("testnet"):
        raise SystemExit("ABORT: non testnet")

    pex = PairsExecutionClient(leg=ExecutionClient(client=client))
    inst = {"ETH": "ETH_USDC-PERPETUAL", "BTC": "BTC_USDC-PERPETUAL"}
    pex.ensure_specs(*inst.values())
    print(f"strumenti: {inst}")

    # GUARDIA: questo conto e' condiviso col runner di produzione (fade reali su
    # BTC/ETH_USDC). Se ci sono posizioni aperte, ABORT: lo smoke userebbe lo stesso
    # strumento e la verifica "conto flat" sarebbe falsata (e un eventuale
    # close_position flatterebbe le quote del runner). Mai eseguire close_position qui.
    for i in inst.values():
        sz = pex.leg._position_size(i)
        if sz != 0:
            raise SystemExit(f"ABORT: posizione di produzione aperta su {i} (size={sz}). "
                             f"Eseguire lo smoke solo a conto flat.")

    with tempfile.TemporaryDirectory() as tmp:
        # capitale piccolo -> notional micro per gamba (capital*pos*lev)
        w = PairsWorker("ETH", "BTC", "1h", capital=60.0, position_size=0.15, leverage=2.0,
                        data_dir=Path(tmp), executor=pex, exec_instruments=inst)
        print(f"execution_enabled={w.execution_enabled}  notional/gamba atteso=${60*0.15*2:.0f}")

        # prezzi sim plausibili (il ramo sim del worker li usa per il suo ledger;
        # il reale usa i fill veri). Niente zeri -> niente divisione per zero.
        pa = pex.leg._mark_price(inst["ETH"]) or 1668.0
        pb = pex.leg._mark_price(inst["BTC"]) or 63000.0
        print("\n[A] OPEN long ratio (long ETH / short BTC)")
        w._open(1, pa, pb, -2.5)
        print(f"  real_in_position={w.real_in_position} dir={w.real_dir}")
        print(f"  gamba A {w.real_side_a} {w.real_amount_a} @ {w.real_entry_a} (notional ${w.real_notional_a:.2f})")
        print(f"  gamba B {w.real_side_b} {w.real_amount_b} @ {w.real_entry_b} (notional ${w.real_notional_b:.2f})")
        print(f"  entry_fee ${w.real_entry_fee:.5f}")
        assert w.real_in_position, "open pair non verificato"
        assert w.real_side_a == "buy" and w.real_side_b == "sell"

        print("\n[B] CLOSE (richiude entrambe le gambe reduce-only)")
        cap0 = w.real_capital
        pa2 = pex.leg._mark_price(inst["ETH"]) or pa
        pb2 = pex.leg._mark_price(inst["BTC"]) or pb
        w._close(pa2, pb2, 0.3, "mean_revert")
        print(f"  real_capital {cap0:.4f} -> {w.real_capital:.4f} (Δ {w.real_capital-cap0:+.4f}) trades={w.real_trades}")
        assert not w.real_in_position, "close pair non azzera la posizione"

        # verifica conto flat su entrambi gli strumenti
        pa = pex.leg._position_size(inst["ETH"])
        pb = pex.leg._position_size(inst["BTC"])
        print(f"\n  posizione netta ETH={pa} BTC={pb}")
        print("✓ catena pairs OK — open 2 gambe verificate, close 2 gambe, fee reali, conto flat"
              if pa == 0 and pb == 0 else
              f"⚠ residuo sul book (ETH={pa} BTC={pb}) — verificare manualmente")


if __name__ == "__main__":
    main()
