from __future__ import annotations

import sys
import subprocess
from pathlib import Path

ROOT = Path(__file__).resolve().parents[2]
if str(ROOT) not in sys.path:
    sys.path.insert(0, str(ROOT))

from src.quant_engine.execution_slippage_store_v1 import (
    ASSUMED_SLIPPAGE_BPS,
    MIN_SAMPLE_FOR_COMPARISON,
    build_slippage_comparison_report,
    fetch_all_samples,
    insert_realized_slippage_sample,
)


def test_report_is_data_gated_below_minimum_sample(tmp_path):
    db_path = tmp_path / "execution_slippage.db"
    report = build_slippage_comparison_report(db_path)
    assert report["status"] == "DATA_GATED"
    assert report["sample_n"] == 0
    assert report["actual_mean_slippage_bps"] is None


def test_buy_slippage_sign_is_positive_when_filled_worse(tmp_path):
    db_path = tmp_path / "execution_slippage.db"
    result = insert_realized_slippage_sample(
        db_path,
        ticker="005930",
        side="buy",
        intended_price=70000,
        actual_fill_price=70070,
        recorded_at="2026-06-21",
    )
    # BUY 체결가가 의도가보다 비싸게 체결됐으면 양수 슬리피지(불리)
    assert result["slippage_bps_actual"] > 0
    assert abs(result["slippage_bps_actual"] - 10.0) < 1e-6  # 70/70000 = 10bps


def test_sell_slippage_sign_is_positive_when_filled_worse(tmp_path):
    db_path = tmp_path / "execution_slippage.db"
    result = insert_realized_slippage_sample(
        db_path,
        ticker="000660",
        side="SELL",
        intended_price=200000,
        actual_fill_price=199900,
        recorded_at="2026-06-21",
    )
    # SELL 체결가가 의도가보다 싸게 체결됐으면 양수 슬리피지(불리)
    assert result["slippage_bps_actual"] > 0


def test_report_compares_against_assumed_bps_once_min_sample_reached(tmp_path):
    db_path = tmp_path / "execution_slippage.db"
    for i in range(MIN_SAMPLE_FOR_COMPARISON):
        insert_realized_slippage_sample(
            db_path,
            ticker="005930",
            side="BUY",
            intended_price=70000,
            actual_fill_price=70070,  # 항상 10bps 불리하게 체결
            recorded_at=f"2026-06-{21 + i}",
        )

    samples = fetch_all_samples(db_path)
    assert len(samples) == MIN_SAMPLE_FOR_COMPARISON

    report = build_slippage_comparison_report(db_path)
    assert report["status"] == "OK"
    assert abs(report["actual_mean_slippage_bps"] - 10.0) < 1e-6
    assert abs(report["gap_bps"] - abs(10.0 - ASSUMED_SLIPPAGE_BPS)) < 1e-6
    assert report["recommendation"]


def test_intended_price_must_be_positive(tmp_path):
    db_path = tmp_path / "execution_slippage.db"
    import pytest

    with pytest.raises(ValueError):
        insert_realized_slippage_sample(
            db_path,
            ticker="005930",
            side="BUY",
            intended_price=0,
            actual_fill_price=100,
            recorded_at="2026-06-21",
        )


def test_cli_report_is_data_gated_below_minimum_sample(tmp_path):
    db_path = tmp_path / "execution_slippage.db"
    report_path = ROOT / "Temp" / "execution_slippage_report_v1.json"
    if report_path.exists():
        report_path.unlink()

    result = subprocess.run(
        [
            sys.executable,
            "tools/evaluate_execution_slippage_v1.py",
            "--db",
            str(db_path),
            "report",
        ],
        cwd=ROOT,
        check=True,
        capture_output=True,
        text=True,
        encoding="utf-8",
    )

    assert "DATA_GATED" in result.stdout
    payload = report_path.read_text(encoding="utf-8")
    assert '"status": "DATA_GATED"' in payload
