"""Tests for Migration 001: sync columns."""
import pytest

from greymatter_core.db import SQLiteDatabase
from greymatter_core.schema.migrations import apply_all, get_current_version
from greymatter_core.sync import SYNC_TABLES


@pytest.fixture
def db():
    """Fresh database with base schema + migration applied."""
    d = SQLiteDatabase(":memory:")
    applied = apply_all(d)
    return d


class TestMigration001:
    def test_migration_applied(self, db):
        assert get_current_version(db) >= 1

    def test_sync_log_table_exists(self, db):
        rows = db.execute(
            "SELECT name FROM sqlite_master WHERE type='table' AND name='_sync_log'"
        )
        assert len(rows) == 1

    def test_sync_state_table_exists(self, db):
        rows = db.execute(
            "SELECT name FROM sqlite_master WHERE type='table' AND name='_sync_state'"
        )
        assert len(rows) == 1

    def test_sync_version_initialized(self, db):
        row = db.execute_one(
            "SELECT value FROM _sync_state WHERE key = ?", ("sync_version",)
        )
        assert row is not None
        assert row["value"] == "0"

    def test_node_id_generated(self, db):
        row = db.execute_one(
            "SELECT value FROM _sync_state WHERE key = ?", ("node_id",)
        )
        assert row is not None
        assert len(row["value"]) == 16  # hex(randomblob(8)) = 16 chars

    def test_sync_columns_added_to_all_tables(self, db):
        for table in SYNC_TABLES:
            # Check _sync_version column exists
            row = db.execute_one(
                f"SELECT _sync_version FROM {table} LIMIT 1"
            )
            # No rows, but query should not fail — column exists

    def test_sync_log_insert(self, db):
        db.execute(
            "INSERT INTO _sync_log (table_name, row_id, operation, sync_version, node_id) "
            "VALUES (?, ?, ?, ?, ?)",
            ("patterns", "p-1", "upsert", 1, "node-abc"),
        )
        rows = db.execute("SELECT * FROM _sync_log")
        assert len(rows) == 1
        assert rows[0]["table_name"] == "patterns"
        assert rows[0]["operation"] == "upsert"

    def test_migration_idempotent(self, db):
        # Running apply_all again should not fail
        applied = apply_all(db)
        assert applied == []  # Already at version 1
