"""
Commission-awareness of tools/compare_tv_trades.py
===================================================

Guards the parity comparator's P&L against the "no commission" footgun: TV's
per-trade Net PnL % is commission-inclusive, so the Python side must pay the
same 0.5%/side commission or the constant ~1%/trade offset compounds into a
misleading multi-x cumulative gap (BTC 6H once read 7,649% gross vs 2,553% TV).

The model must stay identical to strategies/validate_strategy.py.
"""

import os
import sys

import pytest

REPO = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
sys.path.insert(0, REPO)

from tools.compare_tv_trades import COMMISSION_RATE, net_pnl_pct, extract_python_trades  # noqa: E402


def _validate_strategy_model(entry_px, exit_px, rate):
    """Re-implementation of the exact formula in validate_strategy.py:210-213."""
    eff_entry = entry_px * (1 + rate)
    eff_exit = exit_px * (1 - rate)
    return (eff_exit - eff_entry) / eff_entry * 100


def test_default_rate_matches_pine_and_validate_strategy():
    # Pine commission_value=0.5 (percent) and validate_strategy COMMISSION_RATE=0.005
    assert COMMISSION_RATE == 0.005


def test_net_pnl_matches_validate_strategy_formula():
    # Given a winning and a losing trade
    # When net P&L is computed
    # Then it equals the validate_strategy.py model exactly
    for entry_px, exit_px in [(100.0, 110.0), (200.0, 150.0), (15170.53, 15709.95)]:
        assert net_pnl_pct(entry_px, exit_px) == pytest.approx(
            _validate_strategy_model(entry_px, exit_px, COMMISSION_RATE)
        )


def test_net_is_below_gross_by_roughly_round_trip_commission():
    entry_px, exit_px = 100.0, 110.0
    gross = (exit_px - entry_px) / entry_px * 100  # +10%
    net = net_pnl_pct(entry_px, exit_px)
    assert net < gross
    # round-trip cost ≈ 2 * 0.5% = ~1 percentage point on this trade
    assert (gross - net) == pytest.approx(1.045, abs=0.05)


def test_flat_trade_loses_round_trip_commission():
    # A break-even price move still pays both commission legs → ~ -1%
    net = net_pnl_pct(100.0, 100.0)
    assert net == pytest.approx(-0.995, abs=0.01)


def test_zero_commission_equals_gross():
    entry_px, exit_px = 100.0, 137.5
    gross = (exit_px - entry_px) / entry_px * 100
    assert net_pnl_pct(entry_px, exit_px, commission_rate=0.0) == pytest.approx(gross)


def test_extract_python_trades_stores_net_and_gross():
    import pandas as pd

    # Two-bar trade: enter at close=100, exit at close=110
    signals = pd.DataFrame({
        'time': pd.to_datetime(['2020-01-01', '2020-01-02', '2020-01-03']),
        'close': [100.0, 105.0, 110.0],
        'execute_entry': [True, False, False],
        'execute_exit':  [False, False, True],
    })
    trades = extract_python_trades(signals)
    assert len(trades) == 1
    t = trades[0]
    # gross is the raw close-to-close move; pnl_pct is net of commission
    assert t['gross_pnl_pct'] == pytest.approx(10.0)
    assert t['pnl_pct'] == pytest.approx(net_pnl_pct(100.0, 110.0))
    assert t['pnl_pct'] < t['gross_pnl_pct']
