"""Knowledge Base project CRUD resources."""

from __future__ import annotations

import logging

from ..._api.client import AsyncBaseResource, BaseResource
from ..._api.generated.knowbase.knowbase__api__knowbase.client import (
    KnowbaseKnowbaseAPI as _AsyncAPI,
)
from ..._api.generated.knowbase.knowbase__api__knowbase.models import (
    PaginatedProjectList,
    PatchedProjectRequest,
    Project,
    ProjectCreate,
    ProjectCreateRequest,
)
from ..._api.generated.knowbase.knowbase__api__knowbase.sync_client import (
    SyncKnowbaseKnowbaseAPI as _SyncAPI,
)
from ..._config import SDKConfig
from ...exceptions import api_error_handler, async_api_error_handler

logger = logging.getLogger(__name__)


class _ProjectsResource(BaseResource):
    """CRUD for Knowledge Base projects (sync)."""

    def __init__(self, config: SDKConfig) -> None:
        super().__init__(config)
        self._api = _SyncAPI(self._http_client)

    @api_error_handler
    def list(self, *, page: int = 1, page_size: int = 20) -> PaginatedProjectList:
        """List your KB projects."""
        return self._api.projects_list(page=page, page_size=page_size)  # type: ignore[return-value]

    @api_error_handler
    def create(
        self,
        *,
        name: str,
        slug: str,
        description: str | None = None,
        is_public: bool = False,
        embedding_model: str | None = None,
        similarity_threshold: float | None = None,
        max_search_results: int | None = None,
    ) -> ProjectCreate:
        """Create a new KB project.

        Args:
            name: Display name.
            slug: URL-safe identifier (unique per user).
            description: Optional description.
            is_public: If True, accessible via MCP without auth.
            embedding_model: Override embedding model (default: text-embedding-ada-002).
            similarity_threshold: Min cosine similarity 0.0–1.0.
            max_search_results: Hard cap on search results.
        """
        logger.debug("KB project create: slug=%s", slug)
        data = ProjectCreateRequest(
            name=name,
            slug=slug,
            description=description,
            is_public=is_public,
            embedding_model=embedding_model,
            similarity_threshold=similarity_threshold,
            max_search_results=max_search_results,
        )
        return self._api.projects_create(data=data)

    @api_error_handler
    def get(self, slug: str) -> Project:
        """Get a project by slug."""
        return self._api.projects_retrieve(slug=slug)

    @api_error_handler
    def update(
        self,
        slug: str,
        *,
        name: str | None = None,
        description: str | None = None,
        is_public: bool | None = None,
        similarity_threshold: float | None = None,
        max_search_results: int | None = None,
    ) -> Project:
        """Partially update a project."""
        data = PatchedProjectRequest(  # type: ignore[call-arg]
            name=name,
            description=description,
            is_public=is_public,
            similarity_threshold=similarity_threshold,
            max_search_results=max_search_results,
        )
        return self._api.projects_partial_update(slug=slug, data=data)

    @api_error_handler
    def delete(self, slug: str) -> None:
        """Delete a project and all its documents, chunks, and sources."""
        logger.info("KB project delete: slug=%s", slug)
        self._api.projects_destroy(slug=slug)


class _AsyncProjectsResource(AsyncBaseResource):
    """CRUD for Knowledge Base projects (async)."""

    def __init__(self, config: SDKConfig) -> None:
        super().__init__(config)
        self._api = _AsyncAPI(self._http_client)

    @async_api_error_handler
    async def list(self, *, page: int = 1, page_size: int = 20) -> PaginatedProjectList:
        """List your KB projects."""
        return await self._api.projects_list(page=page, page_size=page_size)  # type: ignore[return-value]

    @async_api_error_handler
    async def create(
        self,
        *,
        name: str,
        slug: str,
        description: str | None = None,
        is_public: bool = False,
        embedding_model: str | None = None,
        similarity_threshold: float | None = None,
        max_search_results: int | None = None,
    ) -> ProjectCreate:
        """Create a new KB project."""
        data = ProjectCreateRequest(
            name=name,
            slug=slug,
            description=description,
            is_public=is_public,
            embedding_model=embedding_model,
            similarity_threshold=similarity_threshold,
            max_search_results=max_search_results,
        )
        return await self._api.projects_create(data=data)

    @async_api_error_handler
    async def get(self, slug: str) -> Project:
        """Get a project by slug."""
        return await self._api.projects_retrieve(slug=slug)

    @async_api_error_handler
    async def update(
        self,
        slug: str,
        *,
        name: str | None = None,
        description: str | None = None,
        is_public: bool | None = None,
        similarity_threshold: float | None = None,
        max_search_results: int | None = None,
    ) -> Project:
        """Partially update a project."""
        data = PatchedProjectRequest(  # type: ignore[call-arg]
            name=name,
            description=description,
            is_public=is_public,
            similarity_threshold=similarity_threshold,
            max_search_results=max_search_results,
        )
        return await self._api.projects_partial_update(slug=slug, data=data)

    @async_api_error_handler
    async def delete(self, slug: str) -> None:
        """Delete a project and all its documents, chunks, and sources."""
        await self._api.projects_destroy(slug=slug)


__all__ = [
    "_ProjectsResource",
    "_AsyncProjectsResource",
]
