from __future__ import annotations

import asyncio

from app.core.rag.contracts.enums import RagLayer
from app.core.rag.indexing.service import RagService


class _FakeEmbedder:
    def embed(self, texts: list[str]) -> list[list[float]]:
        return [[0.0, 0.1, 0.2] for _ in texts]


class _FakeRepository:
    def __init__(self) -> None:
        self.replaced_docs = []

    def get_session(self, rag_session_id: str) -> dict:
        return {"project_id": rag_session_id}

    def get_cached_documents(self, repo_id: str, blob_sha: str) -> list:
        return []

    def cache_documents(self, repo_id: str, path: str, blob_sha: str, docs: list) -> None:
        return None

    def replace_documents(self, rag_session_id: str, docs: list) -> None:
        self.replaced_docs = docs


def test_rag_service_progress_uses_only_indexable_files() -> None:
    repository = _FakeRepository()
    service = RagService(embedder=_FakeEmbedder(), repository=repository)
    files = [
        {"path": ".env", "content": "SECRET=1", "content_hash": "h1"},
        {"path": "src/.hidden/config.py", "content": "A=1", "content_hash": "h2"},
        {"path": "src/__pycache__/cache.py", "content": "A=2", "content_hash": "h3"},
        {"path": "src/main.py", "content": "def main():\n    return 1\n", "content_hash": "h4"},
    ]
    progress: list[tuple[int, int, str]] = []

    def progress_cb(current: int, total: int, path: str) -> None:
        progress.append((current, total, path))

    indexed, failed, cache_hits, cache_misses = asyncio.run(
        service.index_snapshot("project-1", files, progress_cb=progress_cb)
    )

    assert indexed == 1
    assert failed == 0
    assert cache_hits == 0
    assert cache_misses == 1
    assert progress == [(1, 1, "src/main.py")]


def test_rag_service_keeps_docs_artifact_type_metadata() -> None:
    repository = _FakeRepository()
    service = RagService(embedder=_FakeEmbedder(), repository=repository)
    files = [
        {
            "path": "docs/api/health.md",
            "content_hash": "docs-h1",
            "content": """---
id: api.health
type: api_method
doc_type: api_method
title: Health API
domain: runtime
sub_domain: health
related_docs: []
status: active
---
# Health API

## Summary
- Purpose: check service health.

## Details
### Описание
Returns health payload.
""",
        }
    ]

    asyncio.run(service.index_snapshot("project-1", files))

    doc_chunk = next(doc for doc in repository.replaced_docs if doc.layer == RagLayer.DOCS_DOC_CHUNKS)
    assert doc_chunk.metadata["artifact_type"] == "DOCS"
    assert doc_chunk.metadata["domain"] == "runtime"
    assert doc_chunk.metadata["subdomain"] == "health"
