"""Guard (Phase 0b Task 7e): Binance is LITERALLY 0% in src/fxhnt — CODE AND COMMENTS. SUBSTRING guard
(mirrors test_no_alpaca.py): `grep -rin binance src/fxhnt` must return 0 hits.

This SUPERSEDES the narrower Task 7b/7c guard that used to live here (which explicitly scoped itself to
CODE, not comments, and intentionally kept historical/documentary Binance mentions). Task 7e closes that
gap: it retires the crypto_pit Binance fetch/panel/ingest/research surface (`crypto_fetch`,
`crypto_pit_panel`, `ts_trend_strategy`, `silver_crypto`, `silver_ingest_helpers`, the `crypto_pit_dir`
setting, the `backtest-funding` CLI, the `--crypto`/`--source crypto` legs of `fetch`/`warehouse-ingest`)
and rewords every remaining Binance-naming comment. No knowledge is lost — the mirage/venue-history
findings are preserved (just not attributed by name) and are banked in memory under
`project_fxhnt_measured_cost_mirage_and_postgres`.

The module/asset/CLI existence checks below are a SECOND, code-level guard against reintroduction —
complementary to the substring grep, not a replacement for it."""
from __future__ import annotations

import importlib
import pathlib
import subprocess

import pytest


def test_no_binance_symbols_in_src() -> None:
    root = pathlib.Path(__file__).parents[2] / "src" / "fxhnt"
    hits = subprocess.run(["grep", "-rin", "binance", str(root)], capture_output=True, text=True).stdout
    assert not hits.strip(), f"residual Binance references:\n{hits}"


_DELETED_MODULES = [
    "fxhnt.adapters.data.binance_funding",
    "fxhnt.adapters.data.binance_xsfunding_live",
    "fxhnt.adapters.exchange.binance_funding_history",
    "fxhnt.adapters.exchange.ccxt_live_price",
    "fxhnt.adapters.data.unlock_calendar_live",
    "fxhnt.application.funding_dispersion_eval",
    "fxhnt.application.bybit_xvenue_funding_eval",
    "fxhnt.application.funding_ingest",
    "fxhnt.application.spot_ingest",
    "fxhnt.application.basis_panel_builder",
    "fxhnt.domain.strategies.funding_carry",
    # Task 7c — the Binance worst_basis Parquet side-store + the dormant vendored VRP PoC.
    "fxhnt.adapters.data.binance_vision_klines",
    "fxhnt.adapters.data.binance_spot_history",
    "fxhnt.application.worst_basis_ingest",
    "fxhnt.adapters.persistence.worst_basis_store",
    "fxhnt.vendor.surfer.surfer_poc",
    # Task 7e — the crypto_pit Binance fetch/panel/ingest/research surface.
    "fxhnt.adapters.data.crypto_fetch",
    "fxhnt.adapters.data.crypto_pit_panel",
    "fxhnt.application.ts_trend_strategy",
    "fxhnt.adapters.warehouse.silver_crypto",
    "fxhnt.application.silver_ingest_helpers",
]

# Binance DATA ingest assets (fed only the retired `features` warehouse funding/spot columns).
_DELETED_INGEST_ASSETS = ("crypto_bars", "crypto_funding", "crypto_spot")

# Binance-specific CLIs (ingest / cross-venue-dispersion / manual delta-neutral-order bridge / crypto_pit
# research).
_DELETED_CLIS = {
    "crypto-funding-ingest", "crypto-spot-ingest", "build-basis-panel", "xsfunding-orders",
    "funding-dispersion-test", "bybit-xvenue-funding-eval",
    "ingest-worst-basis",     # Task 7c — the Binance worst_basis Parquet side-store CLI.
    "backtest-funding",       # Task 7e — its only data source was the crypto_pit panel.
}

# CLIs that MUST survive (Bybit/IBKR paths, Bybit-only measured cost, or the futures-only fetch/ingest).
_KEPT_CLIS = {
    "bybit-carry-revalidate", "bybit-edges-eval", "cross-venue-carry-eval",
    "compare-measured-precompute", "bybit-ingest-worst-basis", "fetch", "warehouse-ingest",
}


@pytest.mark.parametrize("mod", _DELETED_MODULES)
def test_binance_module_gone(mod: str) -> None:
    with pytest.raises(ModuleNotFoundError):
        importlib.import_module(mod)


def test_binance_ingest_assets_gone() -> None:
    from fxhnt.adapters.orchestration import assets
    for a in _DELETED_INGEST_ASSETS:
        assert not hasattr(assets, a), f"{a} Binance ingest asset still present"


def test_binance_clis_gone() -> None:
    from fxhnt.cli import app
    names = {c.name or (c.callback.__name__ if c.callback else None) for c in app.registered_commands}
    assert not (_DELETED_CLIS & names), f"binance CLIs still registered: {_DELETED_CLIS & names}"


def test_bybit_ibkr_and_futures_clis_survive() -> None:
    """No over-deletion: the decoupled Bybit/IBKR commands + the futures-only fetch/warehouse-ingest legs
    are still wired."""
    from fxhnt.cli import app
    names = {c.name or (c.callback.__name__ if c.callback else None) for c in app.registered_commands}
    missing = _KEPT_CLIS - names
    assert not missing, f"a KEPT command was wrongly removed: {missing}"


def test_paper_models_have_no_venue_column() -> None:
    """Guard (Phase 0c): the paper book is single-venue at the SCHEMA level — bybit is fxhnt's sole paper book,
    so the vestigial `venue` discriminator column has been dropped from every paper_* table (Task 7f had already
    hardcoded every `PaperRepo` read/write to bybit; this removes the now-constant column). The invariant is no
    longer 'writes use one hardcoded venue value' but 'the models carry NO venue column at all'."""
    from fxhnt.adapters.persistence.cockpit_models import (
        PaperBookStateRow,
        PaperNavRow,
        PaperNavSummaryRow,
        PaperPositionRow,
        PaperShadowPositionRow,
        PaperSleeveRetRow,
        PaperTradeRow,
    )

    paper_models = (
        PaperPositionRow, PaperTradeRow, PaperNavRow, PaperNavSummaryRow,
        PaperBookStateRow, PaperSleeveRetRow, PaperShadowPositionRow,
    )
    for model in paper_models:
        cols = {c.name for c in model.__table__.columns}
        assert "venue" not in cols, f"{model.__name__} still has a venue column: {sorted(cols)}"
