"""Tests for TemporalTracker — fact change tracking over time."""

from pathlib import Path
from memotrail.core.temporal import TemporalTracker
from memotrail.storage.sqlite_store import SQLiteStore


def _make_tracker(tmp_path: Path) -> tuple[TemporalTracker, SQLiteStore]:
    """Create a fresh TemporalTracker with temp DB."""
    store = SQLiteStore(db_path=tmp_path / "test.db")
    store.connect()
    tracker = TemporalTracker(store)
    return tracker, store


class TestRecordChange:
    def test_record_created(self, tmp_path):
        tracker, store = _make_tracker(tmp_path)
        entry_id = tracker.record_change(
            fact_type="decision",
            fact_id="dec_123",
            new_value="Use PostgreSQL",
            change_type="created",
        )
        assert entry_id.startswith("hist_")

    def test_record_updated(self, tmp_path):
        tracker, _ = _make_tracker(tmp_path)
        tracker.record_change(
            fact_type="memory",
            fact_id="mem_123",
            new_value="Use Redis for caching (v2)",
            change_type="updated",
            previous_value="Use Memcached for caching",
        )
        history = tracker.get_fact_history("mem_123")
        assert len(history) == 1
        assert history[0]["change_type"] == "updated"
        assert history[0]["previous_value"] == "Use Memcached for caching"

    def test_record_contradicted(self, tmp_path):
        tracker, _ = _make_tracker(tmp_path)
        tracker.record_change(
            fact_type="decision",
            fact_id="dec_456",
            new_value="Don't use Redis anymore",
            change_type="contradicted",
            previous_value="Use Redis for caching",
        )
        history = tracker.get_fact_history("dec_456")
        assert history[0]["change_type"] == "contradicted"

    def test_record_with_session(self, tmp_path):
        tracker, store = _make_tracker(tmp_path)
        session = store.create_session(project="proj1")
        tracker.record_change(
            fact_type="decision",
            fact_id="dec_789",
            new_value="Use TypeScript",
            change_type="created",
            session_id=session.id,
        )
        history = tracker.get_fact_history("dec_789")
        assert history[0]["session_id"] == session.id


class TestGetFactHistory:
    def test_empty_history(self, tmp_path):
        tracker, _ = _make_tracker(tmp_path)
        assert tracker.get_fact_history("nonexistent") == []

    def test_ordered_by_time(self, tmp_path):
        tracker, _ = _make_tracker(tmp_path)
        tracker.record_change("decision", "dec_1", "v1", "created")
        tracker.record_change("decision", "dec_1", "v2", "updated", previous_value="v1")
        tracker.record_change("decision", "dec_1", "v3", "updated", previous_value="v2")

        history = tracker.get_fact_history("dec_1")
        assert len(history) == 3
        assert history[0]["new_value"] == "v1"
        assert history[2]["new_value"] == "v3"

    def test_multiple_facts_independent(self, tmp_path):
        tracker, _ = _make_tracker(tmp_path)
        tracker.record_change("decision", "dec_a", "val_a", "created")
        tracker.record_change("decision", "dec_b", "val_b", "created")

        assert len(tracker.get_fact_history("dec_a")) == 1
        assert len(tracker.get_fact_history("dec_b")) == 1


class TestGetFactAtTime:
    def test_get_at_future_time(self, tmp_path):
        tracker, _ = _make_tracker(tmp_path)
        tracker.record_change("memory", "mem_1", "value1", "created")
        result = tracker.get_fact_at_time("mem_1", "2099-01-01T00:00:00")
        assert result is not None
        assert result["new_value"] == "value1"

    def test_get_at_past_time(self, tmp_path):
        tracker, _ = _make_tracker(tmp_path)
        tracker.record_change("memory", "mem_1", "value1", "created")
        result = tracker.get_fact_at_time("mem_1", "2000-01-01T00:00:00")
        assert result is None

    def test_nonexistent_fact(self, tmp_path):
        tracker, _ = _make_tracker(tmp_path)
        result = tracker.get_fact_at_time("nonexistent", "2099-01-01")
        assert result is None


class TestGetChangesInRange:
    def test_all_changes(self, tmp_path):
        tracker, _ = _make_tracker(tmp_path)
        tracker.record_change("decision", "d1", "v1", "created")
        tracker.record_change("memory", "m1", "v2", "created")

        changes = tracker.get_changes_in_range("2000-01-01", "2099-01-01")
        assert len(changes) == 2

    def test_filter_by_type(self, tmp_path):
        tracker, _ = _make_tracker(tmp_path)
        tracker.record_change("decision", "d1", "v1", "created")
        tracker.record_change("memory", "m1", "v2", "created")

        changes = tracker.get_changes_in_range("2000-01-01", "2099-01-01", fact_type="decision")
        assert len(changes) == 1
        assert changes[0]["fact_type"] == "decision"

    def test_empty_range(self, tmp_path):
        tracker, _ = _make_tracker(tmp_path)
        tracker.record_change("decision", "d1", "v1", "created")

        changes = tracker.get_changes_in_range("2000-01-01", "2000-01-02")
        assert len(changes) == 0


class TestGetRecentChanges:
    def test_recent_changes(self, tmp_path):
        tracker, _ = _make_tracker(tmp_path)
        for i in range(5):
            tracker.record_change("decision", f"d{i}", f"v{i}", "created")

        recent = tracker.get_recent_changes(limit=3)
        assert len(recent) == 3

    def test_empty_db(self, tmp_path):
        tracker, _ = _make_tracker(tmp_path)
        assert tracker.get_recent_changes() == []
