import pytest

from app.repositories import embedding_record_repo, embedding_run_repo
from app.repositories import snapshot_graph_repo
from app.repositories.upstream import code_chunk_repo, commit_analysis_repo, doc_chunk_repo
from app.services.embedding_service import EmbeddingService, reset_embedding_service
from tests.integration.fakes import (
    FakeEmbeddingProvider,
    FakeIntegrationDB,
    FakeQdrantClient,
    FakeQdrantStore,
)


@pytest.fixture
def integration_env(monkeypatch):
    """Wire in-memory Mongo, Qdrant, and OpenAI fakes for pipeline integration tests."""
    fake_db = FakeIntegrationDB()
    fake_qdrant = FakeQdrantStore()

    def _fake_db():
        return fake_db

    monkeypatch.setattr("app.core.database.get_db", _fake_db)
    monkeypatch.setattr("app.core.database.get_docs_db", _fake_db)
    monkeypatch.setattr("app.core.database.get_code_chunks_db", _fake_db)
    monkeypatch.setattr("app.core.database.get_commit_analyses_db", _fake_db)
    monkeypatch.setattr(doc_chunk_repo, "get_docs_db", _fake_db)
    monkeypatch.setattr(code_chunk_repo, "get_code_chunks_db", _fake_db)
    monkeypatch.setattr(commit_analysis_repo, "get_commit_analyses_db", _fake_db)
    monkeypatch.setattr(snapshot_graph_repo, "get_code_chunks_db", _fake_db)
    monkeypatch.setattr(embedding_record_repo, "get_db", lambda: fake_db)
    monkeypatch.setattr(embedding_run_repo, "get_db", lambda: fake_db)

    embedding_record_repo._INDEXES_READY = False
    embedding_run_repo._INDEXES_READY = False

    def _upsert_vectors(items, **kwargs):
        from qdrant_client.http import models

        from app.qdrant.point_id import qdrant_point_id
        from app.qdrant.payload import embedding_record_to_qdrant_payload

        points = [
            models.PointStruct(
                id=qdrant_point_id(item.record.record_id),
                vector=item.vector,
                payload=embedding_record_to_qdrant_payload(item.record),
            )
            for item in items
        ]
        fake_qdrant.upsert("adpilot_embeddings", points)
        from app.qdrant.vector_store import VectorUpsertResult

        return [
            VectorUpsertResult(record_id=item.record.record_id, point_id=qdrant_point_id(item.record.record_id))
            for item in items
        ]

    monkeypatch.setattr("app.qdrant.vector_store.upsert_vectors", _upsert_vectors)
    monkeypatch.setattr("app.services.qdrant_index_service.upsert_vectors", _upsert_vectors)

    reset_embedding_service()
    provider = FakeEmbeddingProvider()
    embedding_service = EmbeddingService(provider=provider)
    monkeypatch.setattr(
        "app.services.record_embedding_service.get_embedding_service",
        lambda: embedding_service,
    )
    monkeypatch.setattr(
        "app.services.embedding_service.get_embedding_service",
        lambda: embedding_service,
    )
    monkeypatch.setattr(
        "app.retrieval.vector_search.get_embedding_service",
        lambda: embedding_service,
    )

    fake_qdrant_client = FakeQdrantClient(fake_qdrant)
    monkeypatch.setattr("app.qdrant.client.get_qdrant_client", lambda: fake_qdrant_client)
    monkeypatch.setattr("app.qdrant.vector_store.get_qdrant_client", lambda: fake_qdrant_client)

    yield {
        "db": fake_db,
        "qdrant": fake_qdrant,
        "qdrant_client": fake_qdrant_client,
        "embedding_service": embedding_service,
        "embedding_provider": provider,
    }

    reset_embedding_service()
