from __future__ import annotations

import sys
import unittest
from pathlib import Path

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

# Python Port of calcAlphaLeadRow_'s lateChaseRisk calculation
def calculate_late_chase_risk(
    close: float,
    ma20: float,
    val_surge_pct: float | None,
    anti_distribution_state: str | None,
    dart_risk_status: str | None,
    high_52w: float | None,
    volume: float | None,
    avg_volume_5d: float | None
) -> int:
    close_vs_ma20_pct = (close / ma20 - 1.0) * 100.0 if close > 0 and ma20 > 0 else None
    
    late_chase_risk = 0
    
    if close_vs_ma20_pct is not None:
        if close_vs_ma20_pct > 10.0:
            late_chase_risk += 60
        elif close_vs_ma20_pct > 6.0:
            late_chase_risk += 25
        elif close_vs_ma20_pct > 3.0:
            late_chase_risk += 10
            
    val_surge_pct = float(val_surge_pct) if val_surge_pct not in (None, "") else None
    if val_surge_pct is not None:
        if val_surge_pct >= 60.0:
            late_chase_risk += 25
        elif val_surge_pct >= 35.0:
            late_chase_risk += 10
            
    if anti_distribution_state == "BLOCK_BUY":
        late_chase_risk += 40
        
    if dart_risk_status is not None and dart_risk_status != "OK":
        late_chase_risk += 30
        
    # N2: Volume breakout unconfirmed check (+15)
    n2_high52w = float(high_52w) if high_52w not in (None, "") and float(high_52w) > 0 else 0.0
    n2_vol = float(volume) if volume not in (None, "") else 0.0
    n2_avg_vol = float(avg_volume_5d) if avg_volume_5d not in (None, "") else 0.0
    
    if n2_high52w > 0.0 and close > 0.0 and close >= n2_high52w * 0.97:
        if n2_avg_vol > 0.0 and n2_vol < n2_avg_vol * 1.2:
            late_chase_risk += 15
            
    return min(100, max(0, late_chase_risk))


class TestLateChaseRiskParity(unittest.TestCase):

    def test_close_vs_ma20_ranges_parity(self):
        # close=11100, ma20=10000 -> 11% extension (expected +60)
        score_11pct = calculate_late_chase_risk(
            close=11100, ma20=10000, val_surge_pct=0, anti_distribution_state="PASS",
            dart_risk_status="OK", high_52w=None, volume=None, avg_volume_5d=None
        )
        self.assertEqual(score_11pct, 60)

        # close=10700, ma20=10000 -> 7% extension (expected +25)
        score_7pct = calculate_late_chase_risk(
            close=10700, ma20=10000, val_surge_pct=0, anti_distribution_state="PASS",
            dart_risk_status="OK", high_52w=None, volume=None, avg_volume_5d=None
        )
        self.assertEqual(score_7pct, 25)

    def test_multi_factor_late_chase_cap_parity(self):
        # 11% extension (+60) + Value surge extreme (+25) + Distribution block (+40) = 125 -> capped at 100
        score_extreme = calculate_late_chase_risk(
            close=11100, ma20=10000, val_surge_pct=65.0, anti_distribution_state="BLOCK_BUY",
            dart_risk_status="OK", high_52w=None, volume=None, avg_volume_5d=None
        )
        self.assertEqual(score_extreme, 100)

    def test_unconfirmed_volume_breakout_chase_parity(self):
        # close=9800, high52w=10000 (close >= 97%), volume=100, avg_vol=100 (volume < 1.2*avg_vol -> expected +15)
        # close=10100, ma20=10000 (1% extension -> 0)
        score_breakout = calculate_late_chase_risk(
            close=9800, ma20=10000, val_surge_pct=10.0, anti_distribution_state="PASS",
            dart_risk_status="OK", high_52w=10000, volume=100, avg_volume_5d=100
        )
        self.assertEqual(score_breakout, 15)


if __name__ == "__main__":
    unittest.main()
