"""T7 — hook PaperBookService.derive_and_persist into the daily book rebalance.

STATUS (honest): the daily forward/book advance path carries ONLY daily fractional returns
(`ForwardStrategy.advance(...) -> list[(date, return)]`); it never exposes the per-sleeve
allocation weights, per-symbol target weights, or the day's prices that `derive_and_persist`
requires. So the *automatic* hook from the live advance is BLOCKED on the book code exposing
those three things (see the test module docstring in the report).

What IS wired + tested here:
  * a `paper_enabled` config guard (so the hook can be toggled off), and
  * `persist_paper_book(...)` — the one honest call site: given the three inputs the book WOULD
    need to expose, it runs `derive_and_persist` and populates `paper_repo.latest_positions()`.
    This is the exact code the advance path will call once the book exposes weights+prices.
"""
from __future__ import annotations

import datetime as dt

from fxhnt.adapters.persistence.paper_repo import PaperRepo
from fxhnt.application.paper_book import persist_paper_book
from fxhnt.config import Settings


def test_paper_enabled_default_true() -> None:
    assert Settings().paper_enabled is True


def test_persist_paper_book_populates_positions() -> None:
    repo = PaperRepo("sqlite://")
    repo.migrate()
    n = persist_paper_book(
        repo,
        capital=100_000.0,
        run_date="2026-06-21",
        sleeve_weights={"stablecoin_rotation": 0.5},
        symbol_weights_by_sleeve={"stablecoin_rotation": {"USDTUSD": -1.0}},
        prices={"USDTUSD": 2.0},
        at=dt.datetime(2026, 6, 21, tzinfo=dt.UTC),
    )
    pos = repo.latest_positions()
    assert n == 1
    assert pos and pos[0].symbol == "USDTUSD"
    assert pos[0].qty == -25_000.0


def test_persist_paper_book_disabled_returns_zero() -> None:
    repo = PaperRepo("sqlite://")
    repo.migrate()
    n = persist_paper_book(
        repo,
        capital=100_000.0,
        run_date="2026-06-21",
        sleeve_weights={"stablecoin_rotation": 0.5},
        symbol_weights_by_sleeve={"stablecoin_rotation": {"USDTUSD": -1.0}},
        prices={"USDTUSD": 2.0},
        at=dt.datetime(2026, 6, 21, tzinfo=dt.UTC),
        enabled=False,
    )
    assert n == 0
    assert repo.latest_positions() == []


def test_persist_paper_book_leverage_scales_notional():
    import datetime as dt
    from fxhnt.adapters.persistence.paper_repo import PaperRepo
    from fxhnt.application.paper_book import persist_paper_book
    repo = PaperRepo("sqlite://"); repo.migrate()
    at = dt.datetime(2026, 1, 1, tzinfo=dt.UTC)
    kw = dict(capital=100_000.0, run_date="2026-01-01",
              sleeve_weights={"ts": 1.0}, symbol_weights_by_sleeve={"ts": {"BTCUSDT": 1.0}},
              prices={"BTCUSDT": 100.0}, at=at)
    persist_paper_book(repo, **kw, leverage=2.0)
    pos = repo.positions_at("2026-01-01")
    assert len(pos) == 1 and pos[0].qty == 2.0 * 100_000.0 / 100.0    # notional doubled
    nav = repo.nav_history()[-1]
    assert nav.equity == 100_000.0                                    # equity base unscaled (no pnl yet)


def test_persist_paper_book_caps_realized_gross():
    """Raw gross 5x equity (leverage=5) is scaled down so realized gross == max_gross x equity (3x)."""
    import datetime as dt
    from fxhnt.adapters.persistence.paper_repo import PaperRepo
    from fxhnt.application.paper_book import persist_paper_book
    repo = PaperRepo("sqlite://"); repo.migrate()
    at = dt.datetime(2026, 1, 1, tzinfo=dt.UTC)
    kw = dict(capital=100_000.0, run_date="2026-01-01",
              sleeve_weights={"ts": 1.0}, symbol_weights_by_sleeve={"ts": {"BTCUSDT": 1.0}},
              prices={"BTCUSDT": 100.0}, at=at)
    persist_paper_book(repo, **kw, leverage=5.0, max_gross=3.0)
    pos = repo.positions_at("2026-01-01")
    gross = sum(abs(p.qty * p.entry_price) for p in pos)
    assert gross == 3.0 * 100_000.0                                   # capped to 3x equity
    nav = repo.nav_history()[-1]
    assert nav.equity == 100_000.0                                    # equity base unchanged


def test_persist_paper_book_normal_gross_untouched():
    """A book with gross <= max_gross x equity (leverage=2, gross=2x) is NOT scaled."""
    import datetime as dt
    from fxhnt.adapters.persistence.paper_repo import PaperRepo
    from fxhnt.application.paper_book import persist_paper_book
    repo = PaperRepo("sqlite://"); repo.migrate()
    at = dt.datetime(2026, 1, 1, tzinfo=dt.UTC)
    kw = dict(capital=100_000.0, run_date="2026-01-01",
              sleeve_weights={"ts": 1.0}, symbol_weights_by_sleeve={"ts": {"BTCUSDT": 1.0}},
              prices={"BTCUSDT": 100.0}, at=at)
    persist_paper_book(repo, **kw, leverage=2.0, max_gross=3.0)
    pos = repo.positions_at("2026-01-01")
    assert len(pos) == 1 and pos[0].qty == 2.0 * 100_000.0 / 100.0    # untouched
