"""tests/test_session_claim_join.py — Verify session claim queries join correctly.

The session_record table has two key columns:
  - id: hex PK (lower(hex(randomblob(16))))
  - session_id: application-level string UUID

Claims store source_session = session_record.id (the hex PK).
But get_session_claims() and count_session_claims() receive the string UUID
(session_id).  They must join through session_record to resolve UUID → PK.

This test creates real DB rows and verifies the join works end-to-end.
"""

from __future__ import annotations

import uuid

import pytest

from cortex.storage.sqlite_adapter import SQLiteAdapter


# ---------------------------------------------------------------------------
# Fixtures
# ---------------------------------------------------------------------------

@pytest.fixture
async def adapter():
    """In-memory SQLiteAdapter with all migrations applied."""
    a = SQLiteAdapter(db_path=":memory:")
    await a.initialize()
    yield a
    await a.close()


# ---------------------------------------------------------------------------
# Tests
# ---------------------------------------------------------------------------

@pytest.mark.asyncio
async def test_get_session_claims_joins_via_hex_pk(adapter):
    """get_session_claims(session_uuid) should find claims stored with hex PK."""
    # 1. Create a session — captures both id (hex PK) and session_id (UUID)
    app_session_id = f"test-{uuid.uuid4()}"
    session = await adapter.create_session(
        session_id=app_session_id, owner_id="default"
    )
    hex_pk = session.id
    assert hex_pk != app_session_id, "hex PK and session_id must differ"

    # 2. Insert a claim with source_session = hex PK (as wake_pipeline does)
    conn = await adapter._get_conn()
    claim_id = f"claim-{uuid.uuid4()}"
    await conn.execute(
        """
        INSERT INTO semantic_claim
            (id, owner_id, subject, predicate, object_value,
             confidence, source_session, created_at, updated_at, status)
        VALUES (?, 'default', 'Andrew', 'prefers', 'dark mode',
                0.9, ?, datetime('now'), datetime('now'), 'active')
        """,
        (claim_id, hex_pk),
    )
    await conn.commit()

    # 3. Query by the application-level session UUID
    claims = await adapter.get_session_claims(app_session_id)
    assert len(claims) == 1, f"Expected 1 claim, got {len(claims)}"
    assert claims[0].id == claim_id


@pytest.mark.asyncio
async def test_count_session_claims_joins_via_hex_pk(adapter):
    """count_session_claims(session_uuid) should count claims stored with hex PK."""
    app_session_id = f"test-{uuid.uuid4()}"
    session = await adapter.create_session(
        session_id=app_session_id, owner_id="default"
    )
    hex_pk = session.id

    # Insert two claims
    conn = await adapter._get_conn()
    for i in range(2):
        await conn.execute(
            """
            INSERT INTO semantic_claim
                (id, owner_id, subject, predicate, object_value,
                 confidence, source_session, created_at, updated_at, status)
            VALUES (?, 'default', 'Andrew', 'uses', ?,
                    0.9, ?, datetime('now'), datetime('now'), 'active')
            """,
            (f"claim-{uuid.uuid4()}", f"tool-{i}", hex_pk),
        )
    await conn.commit()

    count = await adapter.count_session_claims(app_session_id)
    assert count == 2, f"Expected 2, got {count}"


@pytest.mark.asyncio
async def test_session_claims_empty_when_no_claims(adapter):
    """A session with no claims should return empty list / count 0."""
    app_session_id = f"test-{uuid.uuid4()}"
    await adapter.create_session(session_id=app_session_id, owner_id="default")

    claims = await adapter.get_session_claims(app_session_id)
    assert claims == []

    count = await adapter.count_session_claims(app_session_id)
    assert count == 0


@pytest.mark.asyncio
async def test_session_claims_nonexistent_session(adapter):
    """Querying claims for a non-existent session should return empty / 0."""
    claims = await adapter.get_session_claims("nonexistent-session-id")
    assert claims == []

    count = await adapter.count_session_claims("nonexistent-session-id")
    assert count == 0
