"""Bilgi tabanı iş mantığı — kaynak CRUD + indexleme tetikleme + arama.

Indexleme uzun iş → Celery (ARCHITECTURE §8). Broker erişilemezse kaynak yine de
oluşturulur (status pending kalır); enqueue başarısızlığı çekirdek akışı bozmaz.
"""
import logging

from fastapi import Depends

from app.models.knowledge import FlovyKnowledgeSource
from app.repositories.knowledge_repo import KnowledgeRepository
from app.schemas.knowledge import (
    CreateFaqRequest,
    CreateManualRequest,
    CreateUrlRequest,
    SearchResultItem,
    SourceResponse,
)
from app.services.rag.knowledge_retriever import KnowledgeRetriever
from app.utils.exceptions import NotFoundError

logger = logging.getLogger("flovy")


def _enqueue_index_source(source_id: str, tenant_id: str) -> None:
    try:
        from app.tasks.index_knowledge import index_knowledge

        index_knowledge.apply_async(args=[source_id, tenant_id], retry=False)
    except Exception as e:  # noqa: BLE001 — broker down olabilir, akışı bozma
        logger.warning("index_knowledge enqueue başarısız (source=%s): %s", source_id, e)


class KnowledgeService:
    def __init__(
        self,
        repo: KnowledgeRepository = Depends(),
        retriever: KnowledgeRetriever = Depends(),
    ):
        self.repo = repo
        self.retriever = retriever

    async def list_sources(self, tenant_id: str) -> list[dict]:
        sources = await self.repo.list_sources(tenant_id)
        return [SourceResponse.model_validate(s).model_dump(mode="json") for s in sources]

    async def create_faq(self, tenant_id: str, body: CreateFaqRequest) -> SourceResponse:
        return await self._create_text_source(tenant_id, "faq", body.title, body.content)

    async def create_manual(
        self, tenant_id: str, body: CreateManualRequest
    ) -> SourceResponse:
        return await self._create_text_source(tenant_id, "manual", body.title, body.content)

    async def create_url(self, tenant_id: str, body: CreateUrlRequest) -> SourceResponse:
        source = await self.repo.create_source(
            tenant_id=tenant_id,
            source_type="url",
            title=body.title or body.url,
            url=body.url,
            status="pending",
        )
        # TODO(scraper): Celery scrape task → content çek → reindex. Şimdilik pending.
        return SourceResponse.model_validate(source)

    async def delete_source(self, source_id: str, tenant_id: str) -> None:
        source = await self._get_or_404(source_id, tenant_id)
        await self.repo.delete_source(source)

    async def reindex_source(self, source_id: str, tenant_id: str) -> SourceResponse:
        source = await self._get_or_404(source_id, tenant_id)
        await self.repo.update_source(source, status="pending")
        _enqueue_index_source(source.id, tenant_id)
        return SourceResponse.model_validate(source)

    async def search(
        self, tenant_id: str, query: str, source_type: str | None = None, k: int = 5
    ) -> list[dict]:
        results = await self.retriever.top_k(tenant_id, query, k=k, source_type=source_type)
        return [SearchResultItem(**r).model_dump(mode="json") for r in results]

    async def _create_text_source(
        self, tenant_id: str, source_type: str, title: str, content: str
    ) -> SourceResponse:
        source = await self.repo.create_source(
            tenant_id=tenant_id,
            source_type=source_type,
            title=title,
            content=content,
            status="pending",
        )
        _enqueue_index_source(source.id, tenant_id)
        return SourceResponse.model_validate(source)

    async def _get_or_404(self, source_id: str, tenant_id: str) -> FlovyKnowledgeSource:
        source = await self.repo.get_source(source_id, tenant_id)
        if not source:
            raise NotFoundError("Bilgi kaynağı")
        return source
