"""ASV benchmarks for the FAISS ACMS vector backend adapters."""

from __future__ import annotations

import importlib
import os
import shutil
import sys
import tempfile
from pathlib import Path
from typing import ClassVar

_SRC = str(Path(__file__).resolve().parents[1] / "src")
if _SRC not in sys.path:
    sys.path.insert(0, _SRC)

import cleveragents  # noqa: E402

importlib.reload(cleveragents)

from cleveragents.application.services.config_service import ConfigService  # noqa: E402
from cleveragents.application.services.faiss_vector_backend import (  # noqa: E402
    FAISSVectorBackend,
    FAISSVectorIndexBackend,
)
from cleveragents.application.services.vector_store_service import (  # noqa: E402
    FAISS,
    VectorStoreService,
)
from cleveragents.config.settings import Settings  # noqa: E402
from cleveragents.infrastructure.database.unit_of_work import UnitOfWork  # noqa: E402


class VectorSearchLatencySuite:
    """Benchmark FAISS-backed ACMS vector indexing and search."""

    params: ClassVar[list[int]] = [250, 1000]
    param_names: ClassVar[list[str]] = ["documents"]
    timeout = 120

    def setup(self, documents: int) -> None:
        if FAISS is None:
            raise RuntimeError("FAISS is required for this benchmark")

        self._saved_env = {
            key: os.environ.get(key)
            for key in (
                "CLEVERAGENTS_INDEX_VECTOR_BACKEND",
                "CLEVERAGENTS_INDEX_VECTOR_DIR",
                "CLEVERAGENTS_EMBEDDING_PROVIDER",
                "CLEVERAGENTS_EMBEDDING_DIMENSIONS",
            )
        }
        self._tempdir = tempfile.mkdtemp(prefix="asv-faiss-vector-")
        os.environ["CLEVERAGENTS_INDEX_VECTOR_BACKEND"] = "faiss"
        os.environ["CLEVERAGENTS_INDEX_VECTOR_DIR"] = self._tempdir
        os.environ["CLEVERAGENTS_EMBEDDING_PROVIDER"] = "fake"
        os.environ["CLEVERAGENTS_EMBEDDING_DIMENSIONS"] = "32"

        service = VectorStoreService(
            Settings(),
            UnitOfWork("sqlite:///:memory:", require_confirmation=False),
            ConfigService(),
        )
        self._index_backend = FAISSVectorIndexBackend(service)
        self._vector_backend = FAISSVectorBackend(service)
        self._query = [1.0, 2.0, 3.0]
        self._scope = frozenset({f"RES{i:04d}" for i in range(min(documents, 32))})

        for i in range(documents):
            vector = [float(i % 11), float((i * 3) % 17), float((i * 5) % 19)]
            self._index_backend.index_embedding(
                "local/bench",
                f"uko:{i:04d}",
                vector,
                {
                    "resource_id": f"RES{i:04d}",
                    "location": f"src/file_{i:04d}.py",
                    "resource_type": "python",
                },
            )

    def teardown(self, documents: int) -> None:
        _ = documents
        shutil.rmtree(self._tempdir, ignore_errors=True)
        for key, value in self._saved_env.items():
            if value is None:
                os.environ.pop(key, None)
            else:
                os.environ[key] = value

    def time_project_search(self, documents: int) -> None:
        _ = documents
        self._index_backend.search_similar("local/bench", self._query, limit=20)

    def time_scoped_similarity_search(self, documents: int) -> None:
        _ = documents
        self._vector_backend.similarity_search(
            self._query,
            scope=self._scope,
            top_k=20,
        )
