"""Tests for SQLite storage layer."""

import pytest
import os
import tempfile

from xyglue.storage import Storage


@pytest.fixture
async def storage():
    """Create a temporary storage instance for testing."""
    tmp = tempfile.NamedTemporaryFile(suffix=".db", delete=False)
    tmp.close()
    s = Storage(db_path=tmp.name)
    await s.initialize()
    yield s
    await s.close()
    os.unlink(tmp.name)


class TestStorage:
    async def test_initialize(self, storage):
        assert storage.is_initialized is True

    async def test_save_and_load(self, storage):
        await storage.save_json("patterns", "p1", {"name": "test"}, name="test", created_at=1.0)
        data = await storage.load_json("patterns", "p1")
        assert data is not None
        assert data["name"] == "test"

    async def test_load_missing(self, storage):
        data = await storage.load_json("patterns", "nonexistent")
        assert data is None

    async def test_delete(self, storage):
        await storage.save_json("patterns", "p1", {"name": "test"}, name="test", created_at=1.0)
        deleted = await storage.delete("patterns", "p1")
        assert deleted is True
        data = await storage.load_json("patterns", "p1")
        assert data is None

    async def test_delete_missing(self, storage):
        deleted = await storage.delete("patterns", "nonexistent")
        assert deleted is False

    async def test_exists(self, storage):
        await storage.save_json("patterns", "p1", {"name": "test"}, name="test", created_at=1.0)
        assert await storage.exists("patterns", "p1") is True
        assert await storage.exists("patterns", "nope") is False

    async def test_list_ids(self, storage):
        await storage.save_json("patterns", "p1", {}, name="a", created_at=1.0)
        await storage.save_json("patterns", "p2", {}, name="b", created_at=2.0)
        ids = await storage.list_ids("patterns")
        assert "p1" in ids
        assert "p2" in ids

    async def test_list_all(self, storage):
        await storage.save_json("patterns", "p1", {"val": 1}, name="a", created_at=1.0)
        await storage.save_json("patterns", "p2", {"val": 2}, name="b", created_at=2.0)
        docs = await storage.list_all("patterns")
        assert len(docs) == 2

    async def test_count(self, storage):
        assert await storage.count("patterns") == 0
        await storage.save_json("patterns", "p1", {}, name="a", created_at=1.0)
        assert await storage.count("patterns") == 1

    async def test_find_by_field(self, storage):
        await storage.save_json("patterns", "p1", {}, name="test", category="timeout", created_at=1.0)
        await storage.save_json("patterns", "p2", {}, name="test2", category="network", created_at=2.0)
        results = await storage.find_by_field("patterns", "category", "timeout")
        assert len(results) == 1

    async def test_find_by_invalid_field(self, storage):
        with pytest.raises(ValueError, match="Cannot query field"):
            await storage.find_by_field("patterns", "invalid_column", "x")

    async def test_invalid_table(self, storage):
        with pytest.raises(ValueError, match="Invalid table"):
            await storage.save_json("invalid_table", "id", {})

    async def test_save_run(self, storage):
        await storage.save_run("run1", "test goal", "running", "auto", {"steps": 3})
        run = await storage.get_run("run1")
        assert run is not None
        assert run["goal"] == "test goal"
        assert run["status"] == "running"

    async def test_list_runs(self, storage):
        await storage.save_run("r1", "goal1", "completed", "auto", {})
        await storage.save_run("r2", "goal2", "running", "semi", {})
        all_runs = await storage.list_runs()
        assert len(all_runs) == 2

        completed = await storage.list_runs(status="completed")
        assert len(completed) == 1

    async def test_health_check(self, storage):
        health = await storage.health_check()
        assert health["healthy"] is True

    async def test_get_stats(self, storage):
        stats = await storage.get_stats()
        assert stats["initialized"] is True
        assert "total_documents" in stats

    async def test_context_manager(self):
        tmp = tempfile.NamedTemporaryFile(suffix=".db", delete=False)
        tmp.close()
        try:
            async with Storage(tmp.name) as s:
                assert s.is_initialized
                await s.save_json("patterns", "p1", {}, name="test", created_at=1.0)
            # After exiting, storage should be closed
            assert not s.is_initialized
        finally:
            os.unlink(tmp.name)
