from datetime import UTC, datetime
from pathlib import Path

from home_agent.contracts.types import (
    Item,
    ItemKind,
    UrgencyDecision,
    UrgencyLabel,
    VectorDocument,
    VectorQuery,
    VectorSearchResult,
)
from home_agent.retrieval.backfill import run_embeddings_backfill
from home_agent.retrieval.text_renderer import DefaultItemTextRenderer
from home_agent.storage.sqlite_store import SqliteStore


class StubEmbeddingProvider:
    @property
    def provider_name(self) -> str:
        return "local_sentence_transformers"

    @property
    def model_name(self) -> str:
        return "all-MiniLM-L6-v2"

    def embed_texts(self, texts: list[str]) -> list[list[float]]:
        return [[float(index), 0.5] for index, _ in enumerate(texts, start=1)]


class CapturingBackend:
    def __init__(self) -> None:
        self.documents: list[object] = []
        self.existing_external_ids: set[str] = set()

    @property
    def backend_name(self) -> str:
        return "sqlite_vec"

    def upsert_documents(self, documents: list[VectorDocument]) -> None:
        self.documents.extend(documents)

    def query_similar(self, query: VectorQuery) -> list[VectorSearchResult]:
        _ = query
        return []

    def healthcheck(self) -> None:
        return None

    def indexed_count(self) -> int:
        return len(self.documents)

    def rebuild(self, documents: list[VectorDocument]) -> None:
        self.documents = list(documents)

    def has_document(self, key: object) -> bool:
        external_id = getattr(key, "external_id", None)
        return isinstance(external_id, str) and external_id in self.existing_external_ids


def test_backfill_indexes_documents_into_selected_backend(tmp_path: Path) -> None:
    store = SqliteStore(tmp_path / "agent.db")
    store.save_item(
        Item(
            provider="gmail",
            external_id="msg-1",
            kind=ItemKind.EMAIL,
            received_at=datetime.now(tz=UTC),
            subject="Deadline notice",
            sender="staff@example.com",
            metadata={"snippet": "Please reply"},
        ),
        UrgencyDecision(score=0.5, label=UrgencyLabel.MEDIUM, reasons=["seed"], used_llm=False),
    )
    backend = CapturingBackend()

    result = run_embeddings_backfill(
        store,
        StubEmbeddingProvider(),
        DefaultItemTextRenderer(),
        vector_backend=backend,
        batch_size=10,
        limit=None,
        since=None,
        kind=None,
        dry_run=False,
        rebuild=False,
    )

    assert result.processed == 1
    assert len(backend.documents) == 1


def test_backfill_skips_items_already_indexed_in_selected_backend(tmp_path: Path) -> None:
    store = SqliteStore(tmp_path / "agent.db")
    store.save_item(
        Item(
            provider="gmail",
            external_id="msg-1",
            kind=ItemKind.EMAIL,
            received_at=datetime.now(tz=UTC),
            subject="Deadline notice",
            sender="staff@example.com",
            metadata={"snippet": "Please reply"},
        ),
        UrgencyDecision(score=0.5, label=UrgencyLabel.MEDIUM, reasons=["seed"], used_llm=False),
    )
    backend = CapturingBackend()
    backend.existing_external_ids.add("msg-1")

    result = run_embeddings_backfill(
        store,
        StubEmbeddingProvider(),
        DefaultItemTextRenderer(),
        vector_backend=backend,
        batch_size=10,
        limit=None,
        since=None,
        kind=None,
        dry_run=False,
        rebuild=False,
    )

    assert result.processed == 0
    assert len(backend.documents) == 0
