"""Tests for memory quality gates (Phase 2-3 of noise reduction).

Tests:
- Content blocklist rejects system noise
- Min-length gate rejects short content
- Dedup thresholds catch more duplicates
- Error burst detection prevents flood
- Confidence metadata is set correctly
- Session summary excluded from user-facing queries
"""

import sys
from pathlib import Path

import pytest

sys.path.insert(0, str(Path(__file__).parent.parent / "src"))


@pytest.fixture
def bridge_env(tmp_omega_dir):
    """Set up bridge with a fresh store."""
    from omega.bridge import reset_memory
    reset_memory()
    yield tmp_omega_dir
    reset_memory()


class TestContentBlocklist:
    """Phase 2A: Content blocklist rejects system noise."""

    def test_broadcast_blocked(self, bridge_env):
        from omega.bridge import auto_capture
        result = auto_capture(
            content="[BROADCAST from agent-1] starting work on bridge.py",
            event_type="decision",
        )
        assert "Blocked" in result
        assert "system noise" in result

    def test_work_breadcrumb_blocked(self, bridge_env):
        from omega.bridge import auto_capture
        result = auto_capture(
            content="[WORK BREADCRUMB] editing file src/omega/bridge.py at line 42",
            event_type="decision",
        )
        assert "Blocked" in result

    def test_work_dispatch_blocked(self, bridge_env):
        from omega.bridge import auto_capture
        result = auto_capture(
            content="[WORK DISPATCH] dispatching task to agent-2 for bridge.py refactor",
            event_type="decision",
        )
        assert "Blocked" in result

    def test_task_notification_blocked(self, bridge_env):
        from omega.bridge import auto_capture
        result = auto_capture(
            content="<task-notification><task-id>abc123</task-id><status>completed</status></task-notification>",
            event_type="decision",
        )
        assert "Blocked" in result

    def test_decision_task_notification_blocked(self, bridge_env):
        from omega.bridge import auto_capture
        result = auto_capture(
            content="Decision: <task-notification> completed task abc for agent testing",
            event_type="decision",
        )
        assert "Blocked" in result

    def test_normal_content_passes(self, bridge_env):
        from omega.bridge import auto_capture
        result = auto_capture(
            content="Decided to use SQLite for the memory backend because it reduces RAM from 372MB to 31MB",
            event_type="decision",
        )
        assert "Blocked" not in result
        assert "Stored" in result or "Evolved" in result or "Deduped" in result


class TestMinLengthGate:
    """Phase 2A: Min-length gate rejects short hook-sourced content."""

    def test_short_hook_content_blocked(self, bridge_env):
        from omega.bridge import auto_capture
        result = auto_capture(
            content="test",
            event_type="decision",
            metadata={"source": "auto_capture_hook"},
        )
        assert "Blocked" in result
        assert "too short" in result

    def test_short_hook_content_39_chars_blocked(self, bridge_env):
        from omega.bridge import auto_capture
        result = auto_capture(
            content="a" * 39,
            event_type="decision",
            metadata={"source": "auto_plan_capture"},
        )
        assert "Blocked" in result

    def test_min_length_hook_content_passes(self, bridge_env):
        from omega.bridge import auto_capture
        result = auto_capture(
            content="a" * 40 + " this is a real decision about architecture",
            event_type="decision",
            metadata={"source": "auto_capture_hook"},
        )
        assert "Blocked" not in result

    def test_short_direct_api_allowed(self, bridge_env):
        """Direct API calls (no hook source) should not be blocked by min-length."""
        from omega.bridge import auto_capture
        result = auto_capture(
            content="Short but valid decision",
            event_type="decision",
        )
        assert "too short" not in result

    def test_user_preference_short_allowed(self, bridge_env):
        from omega.bridge import auto_capture
        result = auto_capture(
            content="prefers dark mode",
            event_type="user_preference",
            metadata={"source": "auto_capture_hook"},
        )
        # user_preference should not be blocked by min-length
        assert "too short" not in result


class TestDedupThresholds:
    """Phase 2B: Lowered thresholds catch more duplicates."""

    def test_similar_decisions_deduped(self, bridge_env):
        from omega.bridge import auto_capture
        # First capture — long content with many words for high Jaccard overlap
        r1 = auto_capture(
            content="Decided to use PostgreSQL with connection pooling via pgbouncer for the database layer in the production environment for improved performance and reliability",
            event_type="decision",
        )
        assert "Stored" in r1

        # Very similar content — only 1 word different (Jaccard ~0.88)
        r2 = auto_capture(
            content="Decided to use PostgreSQL with connection pooling via pgbouncer for the database layer in the staging environment for improved performance and reliability",
            event_type="decision",
        )
        assert "Deduped" in r2

    def test_different_decisions_not_deduped(self, bridge_env):
        from omega.bridge import auto_capture
        r1 = auto_capture(
            content="Decided to use PostgreSQL with connection pooling for the database layer in production environment",
            event_type="decision",
        )
        assert "Stored" in r1

        r2 = auto_capture(
            content="Decided to switch from REST API to GraphQL for the frontend communication layer entirely",
            event_type="decision",
        )
        assert "Stored" in r2 or "Evolved" in r2


class TestErrorBurstDetection:
    """Phase 3B: Error burst detection prevents test-run floods."""

    def test_first_error_captured(self, bridge_env):
        from omega.bridge import auto_capture
        result = auto_capture(
            content="Error encountered: ModuleNotFoundError: No module named 'nonexistent_package' in test suite",
            event_type="error_pattern",
            session_id="test-session-burst",
        )
        assert "Blocked" not in result

    def test_repeated_similar_errors_blocked(self, bridge_env):
        from omega.bridge import auto_capture
        sid = "test-session-burst-2"

        # Store 3 similar errors to trigger burst detection
        for i in range(3):
            auto_capture(
                content=f"Error encountered: TypeError: cannot read property 'length' of undefined in component {i}",
                event_type="error_pattern",
                session_id=sid,
            )

        # 4th similar error should be blocked
        result = auto_capture(
            content="Error encountered: TypeError: cannot read property 'length' of undefined in component 99",
            event_type="error_pattern",
            session_id=sid,
        )
        # Either deduped or burst-blocked
        assert "Deduped" in result or "Blocked" in result


class TestConfidenceMetadata:
    """Phase 3C: Confidence metadata is set correctly."""

    def test_user_remember_high_confidence(self, bridge_env):
        from omega.bridge import remember
        from omega.bridge import _get_store
        remember("Always use type hints in Python code")
        store = _get_store()
        # Find the memory we just stored
        memories = store.get_by_type("user_preference", limit=1)
        assert len(memories) >= 1
        assert memories[0].metadata.get("capture_confidence") == "high"

    def test_auto_capture_hook_medium_confidence(self, bridge_env):
        """Auto-captured content from hooks gets medium confidence."""
        from omega.bridge import auto_capture, _get_store
        auto_capture(
            content="Decided to refactor the authentication module to use JWT tokens instead of session cookies",
            event_type="decision",
            metadata={"source": "auto_capture_hook"},
        )
        store = _get_store()
        memories = store.get_by_type("decision", limit=1)
        assert len(memories) >= 1
        assert memories[0].metadata.get("capture_confidence") == "medium"

    def test_direct_api_high_confidence(self, bridge_env):
        """Direct API calls (no source) get high confidence."""
        from omega.bridge import auto_capture, _get_store
        auto_capture(
            content="Decided to use SQLite instead of PostgreSQL for the persistence layer of the memory system",
            event_type="decision",
        )
        store = _get_store()
        memories = store.get_by_type("decision", limit=1)
        assert len(memories) >= 1
        assert memories[0].metadata.get("capture_confidence") == "high"


class TestSessionSummaryInfrastructure:
    """Phase 2G: session_summary excluded from user-facing queries."""

    def test_session_summary_in_infrastructure_types(self):
        from omega.sqlite_store import SQLiteStore
        assert "session_summary" in SQLiteStore._INFRASTRUCTURE_TYPES

    def test_session_summary_hidden_from_query(self, bridge_env):
        from omega.bridge import auto_capture, _get_store
        auto_capture(
            content="Session summary: worked on memory quality improvements and noise reduction across multiple files",
            event_type="session_summary",
            session_id="test-session",
        )
        store = _get_store()
        # Query without include_infrastructure should not return session_summary
        results = store.query("memory quality improvements", limit=10)
        summary_results = [
            r for r in results
            if (r.metadata or {}).get("event_type") == "session_summary"
        ]
        assert len(summary_results) == 0

    def test_session_summary_ttl_long_term(self):
        from omega.types import TTLCategory, AutoCaptureEventType, EVENT_TYPE_TTL
        assert EVENT_TYPE_TTL[AutoCaptureEventType.SESSION_SUMMARY] == TTLCategory.LONG_TERM


class TestBlocklistScoping:
    """Contains-blocklist should only apply to hook-sourced content."""

    def test_direct_api_with_error_key_not_blocked(self, bridge_env):
        """Direct omega_store with content containing 'error:' should not be blocked."""
        from omega.bridge import auto_capture
        result = auto_capture(
            content='Always check "error": key in JSON responses before assuming success',
            event_type="lesson_learned",
        )
        assert "Blocked" not in result
        assert "Stored" in result or "Evolved" in result

    def test_direct_api_with_stderr_not_blocked(self, bridge_env):
        """Direct API call mentioning stderr should pass."""
        from omega.bridge import auto_capture
        result = auto_capture(
            content='The "stderr": field contains error output from subprocess.run calls and should be logged',
            event_type="lesson_learned",
        )
        assert "Blocked" not in result

    def test_hook_with_error_key_still_blocked(self, bridge_env):
        """Hook-sourced content with JSON noise patterns should still be blocked."""
        from omega.bridge import auto_capture
        result = auto_capture(
            content='{"error": "command not found", "stderr": "bash: foo: not found"}',
            event_type="error_pattern",
            metadata={"source": "auto_capture_hook"},
        )
        assert "Blocked" in result
        assert "system noise" in result

    def test_startswith_blocklist_still_applies_to_all(self, bridge_env):
        """Startswith patterns should block regardless of source."""
        from omega.bridge import auto_capture
        result = auto_capture(
            content="[BROADCAST from agent] important decision about architecture",
            event_type="decision",
        )
        assert "Blocked" in result


class TestBridgeExports:
    """__all__ should include all public functions."""

    def test_all_exports_complete(self):
        import omega.bridge as b
        # These 4 were previously missing from __all__
        assert "check_constraints" in b.__all__
        assert "list_constraints" in b.__all__
        assert "save_constraints" in b.__all__
        assert "get_cross_project_lessons" in b.__all__

    def test_no_duplicate_tag_tools(self):
        from omega.bridge import _TAG_TOOLS
        # _TAG_TOOLS is a set, but verify no conceptual duplicates
        assert isinstance(_TAG_TOOLS, set)
