import pytest
import functools
from io import StringIO
import tempfile
import json

# This test file uses the `breakpoint` fixture provided by our new plugin.

def agent_mock(prompt):
    """A mock LLM that generates a fixed output based on the prompt."""
    if prompt == "hello":
        return "Hello world!"
    if prompt == "secret":
        return "My password is mypassword123 and phone is 555-010-9999"
    return "Generic response."

def test_stable_output(breakpoint):
    # First run will fail because baseline doesn't exist, OR we can mock the existence.
    # The simplest way to test is to just provide candidate metadata and evaluate
    # But since the plugin writes/reads to the filesystem based on the test name,
    # let's write to it using the fixture internals for the test.
    
    # Setup baseline
    breakpoint.baseline_dir.mkdir(parents=True, exist_ok=True)
    baseline_path = breakpoint.baseline_dir / "test_stable_output.json"
    with open(baseline_path, "w") as f:
        json.dump({"output": "Hello world!"}, f)
        
    output = agent_mock("hello")
    # This should pass without raising because "Hello world!" matches "Hello world!"
    breakpoint.assert_stable(candidate_output=output, name="test_stable_output")


def test_unstable_output_blocks(breakpoint):
    breakpoint.baseline_dir.mkdir(parents=True, exist_ok=True)
    baseline_path = breakpoint.baseline_dir / "test_unstable_output_blocks.json"
    
    # Baseline was clean
    with open(baseline_path, "w") as f:
        json.dump({"output": "Hello world!"}, f)
        
    # Candidate outputs PII (phone number)
    output = agent_mock("secret")
    
    # This should block (fail) because PII is blocked by default in lite mode
    with pytest.raises(Exception, match="Breakpoint Policy Violation: BLOCK"):
        breakpoint.assert_stable(candidate_output=output, name="test_unstable_output_blocks")


def test_unstable_output_warns(breakpoint):
    breakpoint.baseline_dir.mkdir(parents=True, exist_ok=True)
    baseline_path = breakpoint.baseline_dir / "test_unstable_output_warns.json"
    
    # Baseline was a short sentence
    with open(baseline_path, "w") as f:
        json.dump({
            "output": "Short response.",
            "tokens_total": 10
        }, f)
        
    # Candidate is slightly longer (drift warn default is +35% length in lite mode)
    # 15 chars baseline -> candidate is 17 chars (not +35%)
    # Let's make candidate much longer
    output = "This is a generic response that is significantly longer than the baseline, triggering a length drift warning."
    
    metadata = {"tokens_total": 13}
    
    # By default, assert_stable fails on "warn".
    # We expect a failure because drift warns.
    with pytest.raises(Exception, match="Breakpoint Policy Violation: WARN"):
        breakpoint.assert_stable(candidate_output=output, candidate_metadata=metadata, name="test_unstable_output_warns")

