from conftest import make_event, make_mr, make_pipeline, make_vuln

from project_hub.core.cache import Cache
from project_hub.core.models import EventType


# --- Tests ---


async def test_migrations_applied(cache: Cache):
    async with cache._db.execute("SELECT name FROM migrations_applied ORDER BY name") as cur:
        applied = [row[0] for row in await cur.fetchall()]
    assert len(applied) >= 1
    assert applied[0] == "001_initial.sql"


async def test_store_and_read_mrs(cache: Cache):
    mrs = [make_mr(1), make_mr(2)]
    await cache.store_mrs("repo-alpha", mrs)
    result = await cache.get_mrs("repo-alpha")
    assert len(result) == 2
    ids = {mr.iid for mr in result}
    assert ids == {1, 2}
    assert all(mr.repo_name == "repo-alpha" for mr in result)
    assert all(mr.author == "alice" for mr in result)


async def test_store_mrs_replaces_existing(cache: Cache):
    await cache.store_mrs("repo-alpha", [make_mr(1), make_mr(2)])
    await cache.store_mrs("repo-alpha", [make_mr(3)])
    result = await cache.get_mrs("repo-alpha")
    assert len(result) == 1
    assert result[0].iid == 3


async def test_store_and_read_pipelines(cache: Cache):
    pipelines = [make_pipeline(10), make_pipeline(11)]
    await cache.store_pipelines("repo-alpha", pipelines)
    result = await cache.get_pipelines("repo-alpha")
    assert len(result) == 2
    assert {p.id for p in result} == {10, 11}
    assert all(p.repo_name == "repo-alpha" for p in result)


async def test_store_and_read_vulns(cache: Cache):
    vulns = [make_vuln(200), make_vuln(201)]
    await cache.store_vulns("repo-alpha", vulns)
    result = await cache.get_vulns("repo-alpha")
    assert len(result) == 2
    assert {v.id for v in result} == {200, 201}
    assert all(v.severity == "high" for v in result)


async def test_store_and_read_events(cache: Cache):
    events = [make_event(EventType.PIPELINE_FAILED), make_event(EventType.MR_APPROVED)]
    await cache.store_events(events)
    result = await cache.get_unseen_events()
    assert len(result) == 2
    types = {e.type for e in result}
    assert EventType.PIPELINE_FAILED in types
    assert EventType.MR_APPROVED in types
    assert all(not e.seen for e in result)


async def test_mark_events_seen(cache: Cache):
    await cache.store_events([make_event()])
    unseen = await cache.get_unseen_events()
    assert len(unseen) == 1
    event_id = unseen[0].id
    assert event_id is not None
    await cache.mark_events_seen([event_id])
    unseen_after = await cache.get_unseen_events()
    assert len(unseen_after) == 0


async def test_mark_all_events_seen(cache: Cache):
    await cache.store_events([make_event(), make_event(EventType.MR_MERGED)])
    unseen = await cache.get_unseen_events()
    assert len(unseen) == 2
    await cache.mark_all_events_seen()
    assert len(await cache.get_unseen_events()) == 0


async def test_reinitialize_is_idempotent(cache: Cache):
    # Store data, reinitialize, data should survive
    await cache.store_mrs("repo-alpha", [make_mr(1)])
    await cache.initialize()
    result = await cache.get_mrs("repo-alpha")
    assert len(result) == 1
