"""
Parity test for late_chase_gate_v1.py against GAS source.

F15: is_late_chase_blocked() checks if late-chase gate should block entry.
Method: Extract GAS function source, run in Node, compare against Python port.

Source: src/gas_adapter_parts/gdf_04_execution_quality.gs lines 482
Test case: if (bqRow.breakout_quality_gate === 'BLOCKED_LATE_CHASE' || alphaRow["late_chase_risk_score"] >= 70)
"""

import pytest
from formulas.late_chase_gate_v1 import is_late_chase_blocked


class TestLateChaseBreakerParity:
    """F15: is_late_chase_blocked(breakout_quality_gate, late_chase_risk_score)"""

    def test_explicit_gate_block_returns_true(self):
        """When breakout_quality_gate === 'BLOCKED_LATE_CHASE', return True"""
        assert is_late_chase_blocked('BLOCKED_LATE_CHASE', 0) is True
        assert is_late_chase_blocked('BLOCKED_LATE_CHASE', 50) is True
        assert is_late_chase_blocked('BLOCKED_LATE_CHASE', 99) is True
        assert is_late_chase_blocked('BLOCKED_LATE_CHASE', None) is True

    def test_score_threshold_70_returns_true(self):
        """When late_chase_risk_score >= 70, return True"""
        assert is_late_chase_blocked('FRESH_PILOT', 70) is True
        assert is_late_chase_blocked('FRESH_PILOT', 75) is True
        assert is_late_chase_blocked('FRESH_PILOT', 100) is True
        assert is_late_chase_blocked('SOME_OTHER_GATE', 85) is True

    def test_score_below_70_with_open_gate_returns_false(self):
        """When score < 70 and gate != BLOCKED_LATE_CHASE, return False"""
        assert is_late_chase_blocked('FRESH_PILOT', 0) is False
        assert is_late_chase_blocked('FRESH_PILOT', 50) is False
        assert is_late_chase_blocked('FRESH_PILOT', 69) is False
        assert is_late_chase_blocked('PULLBACK_WAIT', 30) is False

    def test_none_score_with_open_gate_returns_false(self):
        """When late_chase_risk_score is None/NaN and gate is open, return False"""
        assert is_late_chase_blocked('FRESH_PILOT', None) is False
        assert is_late_chase_blocked('FRESH_PILOT', float('nan')) is False

    def test_empty_gate_with_score_70_returns_true(self):
        """Score threshold applies regardless of gate state (empty string)"""
        assert is_late_chase_blocked('', 70) is True
        assert is_late_chase_blocked('', 75) is True

    def test_explicit_gate_takes_precedence(self):
        """If gate is BLOCKED_LATE_CHASE, result is True even with low score"""
        assert is_late_chase_blocked('BLOCKED_LATE_CHASE', 0) is True
        assert is_late_chase_blocked('BLOCKED_LATE_CHASE', -10) is True


class TestLateChaseBreakerEdgeCases:
    """Edge cases matching GAS JavaScript semantics"""

    def test_boundary_score_exactly_70(self):
        """Score exactly 70 should return True (>= comparison)"""
        assert is_late_chase_blocked('FRESH_PILOT', 70) is True
        assert is_late_chase_blocked('ANY_GATE', 70.0) is True

    def test_boundary_score_exactly_69(self):
        """Score exactly 69 should return False (not >= 70)"""
        assert is_late_chase_blocked('FRESH_PILOT', 69) is False
        assert is_late_chase_blocked('ANY_GATE', 69.99) is False

    def test_negative_score_returns_false(self):
        """Negative scores never trigger the >= 70 check"""
        assert is_late_chase_blocked('FRESH_PILOT', -100) is False
        assert is_late_chase_blocked('FRESH_PILOT', -1) is False

    def test_infinity_returns_true(self):
        """Infinity scores should return True (infinity >= 70)"""
        assert is_late_chase_blocked('FRESH_PILOT', float('inf')) is True

    def test_case_sensitive_gate_matching(self):
        """Gate string comparison is case-sensitive (JavaScript ===)"""
        assert is_late_chase_blocked('blocked_late_chase', 0) is False  # lowercase
        assert is_late_chase_blocked('Blocked_Late_Chase', 0) is False  # mixed case
        assert is_late_chase_blocked('BLOCKED_LATE_CHASE', 0) is True   # exact match
