import pytest
from pulse.core import pattern_yield
from pulse.core import event_bus

@pytest.fixture
def clean_pattern_yield():
    if pattern_yield.YIELD_FILE.exists():
        pattern_yield.YIELD_FILE.unlink()
    pattern_yield._registry.clear()
    event_bus._subscribers.clear()
    yield
    if pattern_yield.YIELD_FILE.exists():
        pattern_yield.YIELD_FILE.unlink()

def test_record_match_and_useful(clean_pattern_yield):
    pattern_yield.record_match("p1")
    pattern_yield.record_match("p1")
    pattern_yield.record_match("p2")
    
    assert pattern_yield._registry["p1"]["match_count"] == 2
    assert pattern_yield._registry["p2"]["match_count"] == 1
    
    pattern_yield.record_useful("p1")
    assert pattern_yield._registry["p1"]["useful_count"] == 1
    assert pattern_yield.get_yield_rate("p1") == 0.5

def test_yield_rate_calculation(clean_pattern_yield):
    pattern_yield.record_match("p3")
    assert pattern_yield.get_yield_rate("p3") == 0.0
    
    pattern_yield.record_useful("p3")
    assert pattern_yield.get_yield_rate("p3") == 1.0

def test_underperformer_detection(clean_pattern_yield):
    # p1: good pattern
    for _ in range(25):
        pattern_yield.record_match("p1")
    for _ in range(10):
        pattern_yield.record_useful("p1")
        
    # p2: underperformer
    for _ in range(25):
        pattern_yield.record_match("p2")
    pattern_yield.record_useful("p2") # 1/25 = 0.04 < 0.1
    
    # p3: bad rate but not enough matches
    for _ in range(10):
        pattern_yield.record_match("p3")
        
    underperformers = pattern_yield.get_underperformers(0.1)
    
    assert "p2" in underperformers
    assert "p1" not in underperformers
    assert "p3" not in underperformers

def test_deprecation_and_event_bus(clean_pattern_yield):
    alerts = []
    def on_deprecated(event):
        alerts.append(event)
        
    event_bus.subscribe("pattern.deprecated", on_deprecated)
    
    pattern_yield.record_match("p4")
    pattern_yield.deprecate("p4")
    
    assert pattern_yield._registry["p4"]["deprecated"] is True
    
    # Check event
    assert len(alerts) == 1
    assert alerts[0]["payload"]["pattern_id"] == "p4"

def test_trend_limit(clean_pattern_yield):
    # Insert 1010 patterns
    for i in range(1010):
        pid = f"p_{i}"
        pattern_yield._registry[pid] = pattern_yield._init_entry(pid)
        pattern_yield._registry[pid]["match_count"] = i # match_count helps differentiate
        if i < 20:
            pattern_yield._registry[pid]["deprecated"] = True
            
    pattern_yield._prune_if_needed()
    
    assert len(pattern_yield._registry) == 1000
    
    # Deprecated ones with lowest match counts should be pruned first (prunes bottom 10)
    assert "p_0" not in pattern_yield._registry
    assert "p_9" not in pattern_yield._registry
    assert "p_10" in pattern_yield._registry
    assert "p_20" in pattern_yield._registry # First non-deprecated
