"""Tests for cross-device pattern discovery."""
import pytest

from greymatter_core.db import SQLiteDatabase
from greymatter_core.schema.migrations import apply_all
from greymatter_core.sync.patterns import (
    discover_cross_node_patterns,
    escalate_pattern_confidence,
)
from greymatter_core.sync.tracking import install_sqlite_triggers


def _make_db():
    d = SQLiteDatabase(":memory:")
    apply_all(d)
    install_sqlite_triggers(d)
    return d


class TestEscalatePatternConfidence:
    def test_no_escalation_single_node(self):
        db = _make_db()
        db.execute(
            "INSERT INTO patterns (id, type, domain, title, observation, confidence) "
            "VALUES (?, ?, ?, ?, ?, ?)",
            ("p-1", "process", "testing", "Title", "Obs", "low"),
        )
        # Single node — no escalation
        result = escalate_pattern_confidence(db, "p-1")
        assert result is None

    def test_escalates_with_two_nodes(self):
        db = _make_db()
        db.execute(
            "INSERT INTO patterns (id, type, domain, title, observation, confidence) "
            "VALUES (?, ?, ?, ?, ?, ?)",
            ("p-1", "process", "testing", "Title", "Obs", "low"),
        )
        # Simulate a second node's log entry
        db.execute(
            "INSERT INTO _sync_log (table_name, row_id, operation, sync_version, node_id) "
            "VALUES (?, ?, ?, ?, ?)",
            ("patterns", "p-1", "upsert", 100, "node-remote"),
        )
        result = escalate_pattern_confidence(db, "p-1")
        assert result == "medium"

    def test_never_downgrades(self):
        db = _make_db()
        db.execute(
            "INSERT INTO patterns (id, type, domain, title, observation, confidence) "
            "VALUES (?, ?, ?, ?, ?, ?)",
            ("p-1", "process", "testing", "Title", "Obs", "verified"),
        )
        db.execute(
            "INSERT INTO _sync_log (table_name, row_id, operation, sync_version, node_id) "
            "VALUES (?, ?, ?, ?, ?)",
            ("patterns", "p-1", "upsert", 100, "node-remote"),
        )
        result = escalate_pattern_confidence(db, "p-1")
        assert result is None  # Already verified, don't downgrade to medium

    def test_escalates_to_high_with_three_nodes(self):
        db = _make_db()
        db.execute(
            "INSERT INTO patterns (id, type, domain, title, observation, confidence) "
            "VALUES (?, ?, ?, ?, ?, ?)",
            ("p-1", "process", "testing", "Title", "Obs", "low"),
        )
        for i, node in enumerate(["node-2", "node-3"]):
            db.execute(
                "INSERT INTO _sync_log (table_name, row_id, operation, sync_version, node_id) "
                "VALUES (?, ?, ?, ?, ?)",
                ("patterns", "p-1", "upsert", 100 + i, node),
            )
        result = escalate_pattern_confidence(db, "p-1")
        assert result == "high"


class TestDiscoverCrossNodePatterns:
    def test_finds_multi_node_patterns(self):
        db = _make_db()
        db.execute(
            "INSERT INTO patterns (id, type, domain, title, observation, confidence) "
            "VALUES (?, ?, ?, ?, ?, ?)",
            ("p-1", "process", "testing", "Title", "Obs", "low"),
        )
        db.execute(
            "INSERT INTO _sync_log (table_name, row_id, operation, sync_version, node_id) "
            "VALUES (?, ?, ?, ?, ?)",
            ("patterns", "p-1", "upsert", 100, "node-remote"),
        )
        results = discover_cross_node_patterns(db)
        assert len(results) >= 1
        assert results[0]["node_count"] >= 2
        assert results[0]["id"] == "p-1"

    def test_ignores_single_node_patterns(self):
        db = _make_db()
        db.execute(
            "INSERT INTO patterns (id, type, domain, title, observation) "
            "VALUES (?, ?, ?, ?, ?)",
            ("p-solo", "process", "testing", "Solo", "Obs"),
        )
        results = discover_cross_node_patterns(db)
        solo_results = [r for r in results if r["id"] == "p-solo"]
        assert len(solo_results) == 0
