"""Tests for agent.privacy_filter — PII stripping before remote API calls."""

import pytest
from agent.privacy_filter import (
    PrivacyFilter,
    RedactionReport,
    Sensitivity,
    sanitize_messages,
    quick_sanitize,
)


class TestPrivacyFilterSanitizeText:
    """Test single-text sanitization."""

    def test_no_pii_returns_clean(self):
        pf = PrivacyFilter()
        text = "The weather in Paris is nice today."
        cleaned, redactions = pf.sanitize_text(text)
        assert cleaned == text
        assert redactions == []

    def test_email_redacted(self):
        pf = PrivacyFilter()
        text = "Send report to alice@example.com by Friday."
        cleaned, redactions = pf.sanitize_text(text)
        assert "alice@example.com" not in cleaned
        assert "[REDACTED-EMAIL]" in cleaned
        assert any(r["type"] == "email_address" for r in redactions)

    def test_phone_redacted(self):
        pf = PrivacyFilter()
        text = "Call me at 555-123-4567 when ready."
        cleaned, redactions = pf.sanitize_text(text)
        assert "555-123-4567" not in cleaned
        assert "[REDACTED-PHONE]" in cleaned

    def test_api_key_redacted(self):
        pf = PrivacyFilter()
        text = 'api_key = "sk-proj-abcdefghij1234567890abcdefghij1234567890"'
        cleaned, redactions = pf.sanitize_text(text)
        assert "sk-proj-" not in cleaned
        assert any(r["sensitivity"] == "CRITICAL" for r in redactions)

    def test_github_token_redacted(self):
        pf = PrivacyFilter()
        text = "Use ghp_1234567890abcdefghijklmnopqrstuvwxyz1234 for auth"
        cleaned, redactions = pf.sanitize_text(text)
        assert "ghp_" not in cleaned
        assert any(r["type"] == "github_token" for r in redactions)

    def test_ethereum_address_redacted(self):
        pf = PrivacyFilter()
        text = "Send to 0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18 please"
        cleaned, redactions = pf.sanitize_text(text)
        assert "0x742d" not in cleaned
        assert any(r["type"] == "ethereum_address" for r in redactions)

    def test_user_home_path_redacted(self):
        pf = PrivacyFilter()
        text = "Read file at /Users/alice/Documents/secret.txt"
        cleaned, redactions = pf.sanitize_text(text)
        assert "alice" not in cleaned
        assert "[REDACTED-USER]" in cleaned

    def test_multiple_pii_types(self):
        pf = PrivacyFilter()
        text = (
            "Contact john@test.com or call 555-999-1234. "
            "The API key is sk-abcdefghijklmnopqrstuvwxyz1234567890."
        )
        cleaned, redactions = pf.sanitize_text(text)
        assert "john@test.com" not in cleaned
        assert "555-999-1234" not in cleaned
        assert "sk-abcd" not in cleaned
        assert len(redactions) >= 3


class TestPrivacyFilterSanitizeMessages:
    """Test message-list sanitization."""

    def test_sanitize_user_message(self):
        pf = PrivacyFilter()
        messages = [
            {"role": "system", "content": "You are helpful."},
            {"role": "user", "content": "Email me at bob@test.com with results."},
        ]
        safe, report = pf.sanitize_messages(messages)
        assert report.redacted_messages == 1
        assert "bob@test.com" not in safe[1]["content"]
        assert "[REDACTED-EMAIL]" in safe[1]["content"]
        # System message unchanged
        assert safe[0]["content"] == "You are helpful."

    def test_no_redaction_needed(self):
        pf = PrivacyFilter()
        messages = [
            {"role": "user", "content": "What is 2+2?"},
            {"role": "assistant", "content": "4"},
        ]
        safe, report = pf.sanitize_messages(messages)
        assert report.redacted_messages == 0
        assert not report.had_redactions

    def test_assistant_messages_also_sanitized(self):
        pf = PrivacyFilter()
        messages = [
            {"role": "assistant", "content": "Your email admin@corp.com was found."},
        ]
        safe, report = pf.sanitize_messages(messages)
        assert report.redacted_messages == 1
        assert "admin@corp.com" not in safe[0]["content"]

    def test_tool_messages_not_sanitized(self):
        pf = PrivacyFilter()
        messages = [
            {"role": "tool", "content": "Result: user@test.com found"},
        ]
        safe, report = pf.sanitize_messages(messages)
        assert report.redacted_messages == 0
        assert safe[0]["content"] == "Result: user@test.com found"


class TestShouldUseLocalOnly:
    """Test the local-only routing decision."""

    def test_normal_text_allows_remote(self):
        pf = PrivacyFilter()
        block, reason = pf.should_use_local_only("Summarize this article about Python.")
        assert not block

    def test_critical_secret_blocks_remote(self):
        pf = PrivacyFilter()
        text = "Here is the API key: sk-abcdefghijklmnopqrstuvwxyz1234567890"
        block, reason = pf.should_use_local_only(text)
        assert block
        assert "critical" in reason.lower()

    def test_multiple_high_sensitivity_blocks(self):
        pf = PrivacyFilter()
        # 3+ high-sensitivity patterns
        text = (
            "Card: 4111-1111-1111-1111, "
            "SSN: 123-45-6789, "
            "BTC: 1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa, "
            "ETH: 0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18"
        )
        block, reason = pf.should_use_local_only(text)
        assert block


class TestAggressiveMode:
    """Test aggressive filtering mode."""

    def test_aggressive_redacts_internal_ips(self):
        pf = PrivacyFilter(aggressive_mode=True)
        text = "Server at 192.168.1.100 is responding."
        cleaned, redactions = pf.sanitize_text(text)
        assert "192.168.1.100" not in cleaned
        assert any(r["type"] == "internal_ip" for r in redactions)

    def test_normal_does_not_redact_ips(self):
        pf = PrivacyFilter(aggressive_mode=False)
        text = "Server at 192.168.1.100 is responding."
        cleaned, redactions = pf.sanitize_text(text)
        assert "192.168.1.100" in cleaned  # IP preserved in normal mode


class TestConvenienceFunctions:
    """Test module-level convenience functions."""

    def test_quick_sanitize(self):
        text = "Contact alice@example.com for details"
        result = quick_sanitize(text)
        assert "alice@example.com" not in result
        assert "[REDACTED-EMAIL]" in result

    def test_sanitize_messages_convenience(self):
        messages = [{"role": "user", "content": "Call 555-000-1234"}]
        safe, report = sanitize_messages(messages)
        assert report.redacted_messages == 1


class TestRedactionReport:
    """Test the reporting structure."""

    def test_summary_no_redactions(self):
        report = RedactionReport(total_messages=3, redacted_messages=0)
        assert "No PII" in report.summary()

    def test_summary_with_redactions(self):
        report = RedactionReport(
            total_messages=2,
            redacted_messages=1,
            redactions=[
                {"type": "email_address", "sensitivity": "MEDIUM", "count": 2},
                {"type": "phone_number_us", "sensitivity": "MEDIUM", "count": 1},
            ],
        )
        summary = report.summary()
        assert "1/2" in summary
        assert "email_address" in summary
