import datetime as dt

import pytest
from sqlalchemy.orm import Session

from fxhnt.adapters.persistence.cockpit_models import BacktestSummaryRow, ForwardNavRow, ForwardSummaryRow
from fxhnt.adapters.persistence.forward_nav import ForwardNavRepo
from fxhnt.application.allocation_ingest import record_allocation
from fxhnt.registry import STRATEGY_REGISTRY

_DSN = None
_SID = "positioning"   # registry tier==deploy, gate_type reconciliation, min_forward_days 14
                       # (bybit_4edge demoted to tier==research 2026-07-16; `positioning` is the sole
                       # remaining hardcoded deploy-tier crypto sleeve — see registry.py)


def _mk_repo(tmp_path):
    global _DSN
    _DSN = f"sqlite:///{tmp_path/'c.db'}"
    repo = ForwardNavRepo(_DSN)
    repo.migrate()
    return repo


def _seed(repo, sid, navs, cagr, at, start="2026-01-01"):
    """Seed a forward record (consecutive daily rows), a summary, and a backtest_summary (the recon ref)."""
    d0 = dt.date.fromisoformat(start)
    with Session(repo._engine) as s:
        for i, v in enumerate(navs):
            ret = (navs[i] / navs[i - 1] - 1.0) if i else (v - 1.0)
            s.add(ForwardNavRow(strategy_id=sid, date=d0 + dt.timedelta(days=i), ret=ret, nav=v, src_updated_at=at))
        last = (d0 + dt.timedelta(days=len(navs) - 1)).isoformat()
        s.add(ForwardSummaryRow(strategy_id=sid, as_of=last, days=len(navs), nav=navs[-1],
                                total_return=navs[-1] - 1.0, sharpe=1.0, maxdd=-0.05,
                                gate_status="WAIT", gate_reason="", src_updated_at=at))
        s.add(BacktestSummaryRow(strategy_id=sid, as_of=last, cagr=cagr, ann_vol=0.2, sharpe=1.0,
                                 max_drawdown=-0.1, passed=True, dsr=0.9, is_sharpe=1.0, oos_sharpe=1.0,
                                 pvalue=0.01, src_updated_at=at))
        s.commit()


@pytest.mark.skipif(_SID not in STRATEGY_REGISTRY or STRATEGY_REGISTRY.get(_SID, {}).get("tier") != "deploy",
                    reason="needs a tier==deploy reconciliation edge (see _SID)")
def test_healthy_deploy_edge_stays_funded_and_allocated(tmp_path):
    repo = _mk_repo(tmp_path)
    at = dt.datetime(2026, 7, 10)
    # 65 days steadily climbing (>= B2a min_history_days=60, positive Sharpe), modest backtest cagr -> reconciles.
    _seed(repo, _SID, [1.0 + 0.0015 * i for i in range(65)], cagr=0.6, at=at)
    dollars = record_allocation(_DSN, equity=35_000.0)
    assert repo.current_funding().get(_SID) == "funded"
    assert dollars.get(_SID, 0.0) > 0.0


@pytest.mark.skipif(_SID not in STRATEGY_REGISTRY or STRATEGY_REGISTRY.get(_SID, {}).get("tier") != "deploy",
                    reason="needs a tier==deploy reconciliation edge (see _SID)")
def test_decayed_deploy_edge_is_defunded_and_absent(tmp_path):
    repo = _mk_repo(tmp_path)
    at = dt.datetime(2026, 7, 10)
    # Days 0..22 climb to +7.7% (first PASS once days >= min_forward_days 14), then 11 days flat at -15%
    # (sustained DIVERGENCE >= defund_window 10 -> de-funded). cagr 2.0 keeps the backtest expectation clearly
    # positive so the -15% forward is an unambiguous divergence.
    navs = [1.0 + 0.0035 * i for i in range(23)] + [0.85] * 11
    _seed(repo, _SID, navs, cagr=2.0, at=at)
    dollars = record_allocation(_DSN, equity=35_000.0)
    assert repo.current_funding().get(_SID) == "de-funded"
    assert _SID not in dollars                          # de-funded -> absent from B2a's input -> no dollars
