from __future__ import annotations

from datetime import UTC, datetime

import pytest

from app.core.config import settings
from app.models.intent import IntentResult, QueryIntent
from app.models.query import QueryRequest
from app.models.query_log import QueryLogEntry
from app.repositories.query_log_repository import QueryLogRepository
from app.services.query_service import QueryService
from tests.unit.test_query_service import FakeOrchestrator
from app.models.search import SearchMetadata, SearchResponse


class InMemoryQueryLogRepo:
    def __init__(self):
        self.entries: dict[str, QueryLogEntry] = {}

    async def ensure_indexes(self):
        return None

    async def insert_entry(self, entry: QueryLogEntry) -> str:
        self.entries[entry.request_id] = entry
        return entry.request_id

    async def find_by_request_id(self, request_id: str) -> QueryLogEntry | None:
        return self.entries.get(request_id)


@pytest.mark.integration
@pytest.mark.asyncio
async def test_query_writes_log_entry(monkeypatch):
    monkeypatch.setattr(settings, "QUERY_LOGS_ENABLED", True)
    monkeypatch.setattr(settings, "GENERAL_LLM_FALLBACK_ENABLED", False)
    repo = InMemoryQueryLogRepo()
    search_response = SearchResponse(
        request_id="req_log_integration",
        repo_id="ad/example.com",
        snapshot_id="snap_1",
        question="Where is Foo?",
        intent=IntentResult(
            type=QueryIntent.CODE_LOOKUP,
            confidence=0.9,
            source_types_used=[],
        ),
        metadata=SearchMetadata(latency_ms=10, retrieval_count=0),
    )

    from app.services.query_log_service import QueryLogService

    service = QueryService(
        orchestrator=FakeOrchestrator(search_response),
        query_log_service=QueryLogService(repository=repo),  # type: ignore[arg-type]
    )
    await service.query(
        QueryRequest(repo_id="ad/example.com", question="Where is Foo?"),
        user_id="user_test",
    )
    entry = await repo.find_by_request_id("req_log_integration")
    assert entry is not None
    assert entry.user_id == "user_test"
    assert entry.streamed is False
    assert entry.status == "no_context"
