from __future__ import annotations

import httpx

from .models import (
    DataSource,
    DataSourceCreateRequest,
    DataSourceRequest,
    Document,
    DocumentUploadRequest,
    PaginatedDataSourceList,
    PaginatedDocumentList,
    PaginatedProjectList,
    PatchedDataSourceRequest,
    PatchedProjectRequest,
    Project,
    ProjectCreate,
    ProjectCreateRequest,
    ProjectRequest,
    SearchRequestRequest,
    SearchResponse,
)


class SyncKnowbaseKnowbaseAPI:
    """Synchronous API endpoints for Knowbase."""

    def __init__(self, client: httpx.Client):
        """Initialize sync sub-client with shared httpx client."""
        self._client = client

    def projects_list(
        self,
        ordering: str | None = None,
        page: int | None = None,
        page_size: int | None = None,
        search: str | None = None,
    ) -> list[PaginatedProjectList]:
        """
        CRUD for KnowledgeBase Projects. list: GET /api/knowbase/projects/
        create: POST /api/knowbase/projects/ retrieve: GET
        /api/knowbase/projects/{slug}/ update: PATCH
        /api/knowbase/projects/{slug}/ destroy: DELETE
        /api/knowbase/projects/{slug}/
        """
        url = "/api/knowbase/projects/"
        _params = {
            k: v for k, v in {
                "ordering": ordering,
                "page": page,
                "page_size": page_size,
                "search": search,
            }.items() if v is not None
        }
        response = self._client.get(url, params=_params)
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return PaginatedProjectList.model_validate(response.json())


    def projects_create(self, data: ProjectCreateRequest) -> ProjectCreate:
        """
        CRUD for KnowledgeBase Projects. list: GET /api/knowbase/projects/
        create: POST /api/knowbase/projects/ retrieve: GET
        /api/knowbase/projects/{slug}/ update: PATCH
        /api/knowbase/projects/{slug}/ destroy: DELETE
        /api/knowbase/projects/{slug}/
        """
        url = "/api/knowbase/projects/"
        response = self._client.post(url, json=data.model_dump(mode="json", exclude_unset=True, exclude_none=True))
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return ProjectCreate.model_validate(response.json())


    def projects_documents_list(
        self,
        project_slug: str,
        ordering: str | None = None,
        page: int | None = None,
        page_size: int | None = None,
        search: str | None = None,
    ) -> list[PaginatedDocumentList]:
        """
        Document management within a project. list: GET
        /api/knowbase/projects/{slug}/documents/ retrieve: GET
        /api/knowbase/projects/{slug}/documents/{id}/ upload: POST
        /api/knowbase/projects/{slug}/documents/ destroy: DELETE
        /api/knowbase/projects/{slug}/documents/{id}/
        """
        url = f"/api/knowbase/projects/{project_slug}/documents/"
        _params = {
            k: v for k, v in {
                "ordering": ordering,
                "page": page,
                "page_size": page_size,
                "search": search,
            }.items() if v is not None
        }
        response = self._client.get(url, params=_params)
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return PaginatedDocumentList.model_validate(response.json())


    def projects_documents_create(
        self,
        project_slug: str,
        data: DocumentUploadRequest,
    ) -> Document:
        """
        Upload a document manually.
        """
        url = f"/api/knowbase/projects/{project_slug}/documents/"
        response = self._client.post(url, json=data.model_dump(mode="json", exclude_unset=True, exclude_none=True))
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return Document.model_validate(response.json())


    def projects_documents_retrieve(self, id: str, project_slug: str) -> Document:
        """
        Document management within a project. list: GET
        /api/knowbase/projects/{slug}/documents/ retrieve: GET
        /api/knowbase/projects/{slug}/documents/{id}/ upload: POST
        /api/knowbase/projects/{slug}/documents/ destroy: DELETE
        /api/knowbase/projects/{slug}/documents/{id}/
        """
        url = f"/api/knowbase/projects/{project_slug}/documents/{id}/"
        response = self._client.get(url)
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return Document.model_validate(response.json())


    def projects_documents_destroy(self, id: str, project_slug: str) -> None:
        """
        Document management within a project. list: GET
        /api/knowbase/projects/{slug}/documents/ retrieve: GET
        /api/knowbase/projects/{slug}/documents/{id}/ upload: POST
        /api/knowbase/projects/{slug}/documents/ destroy: DELETE
        /api/knowbase/projects/{slug}/documents/{id}/
        """
        url = f"/api/knowbase/projects/{project_slug}/documents/{id}/"
        response = self._client.delete(url)
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return None


    def projects_search_create(
        self,
        project_slug: str,
        data: SearchRequestRequest,
    ) -> SearchResponse:
        """
        Search knowledge base

        Semantic vector search within a knowledge base project. Public projects
        are accessible without authentication.
        """
        url = f"/api/knowbase/projects/{project_slug}/search/"
        response = self._client.post(url, json=data.model_dump(mode="json", exclude_unset=True, exclude_none=True))
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return SearchResponse.model_validate(response.json())


    def projects_sources_list(
        self,
        project_slug: str,
        ordering: str | None = None,
        page: int | None = None,
        page_size: int | None = None,
        search: str | None = None,
    ) -> list[PaginatedDataSourceList]:
        """
        Data source management within a project. list: GET
        /api/knowbase/projects/{slug}/sources/ create: POST
        /api/knowbase/projects/{slug}/sources/ update: PATCH
        /api/knowbase/projects/{slug}/sources/{id}/ destroy: DELETE
        /api/knowbase/projects/{slug}/sources/{id}/ crawl: POST
        /api/knowbase/projects/{slug}/sources/{id}/crawl/
        """
        url = f"/api/knowbase/projects/{project_slug}/sources/"
        _params = {
            k: v for k, v in {
                "ordering": ordering,
                "page": page,
                "page_size": page_size,
                "search": search,
            }.items() if v is not None
        }
        response = self._client.get(url, params=_params)
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return PaginatedDataSourceList.model_validate(response.json())


    def projects_sources_create(
        self,
        project_slug: str,
        data: DataSourceCreateRequest,
    ) -> DataSource:
        """
        Create a source using DataSourceCreateSerializer for input, return full
        DataSourceSerializer.
        """
        url = f"/api/knowbase/projects/{project_slug}/sources/"
        response = self._client.post(url, json=data.model_dump(mode="json", exclude_unset=True, exclude_none=True))
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return DataSource.model_validate(response.json())


    def projects_sources_retrieve(self, id: str, project_slug: str) -> DataSource:
        """
        Data source management within a project. list: GET
        /api/knowbase/projects/{slug}/sources/ create: POST
        /api/knowbase/projects/{slug}/sources/ update: PATCH
        /api/knowbase/projects/{slug}/sources/{id}/ destroy: DELETE
        /api/knowbase/projects/{slug}/sources/{id}/ crawl: POST
        /api/knowbase/projects/{slug}/sources/{id}/crawl/
        """
        url = f"/api/knowbase/projects/{project_slug}/sources/{id}/"
        response = self._client.get(url)
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return DataSource.model_validate(response.json())


    def projects_sources_update(
        self,
        id: str,
        project_slug: str,
        data: DataSourceRequest,
    ) -> DataSource:
        """
        Data source management within a project. list: GET
        /api/knowbase/projects/{slug}/sources/ create: POST
        /api/knowbase/projects/{slug}/sources/ update: PATCH
        /api/knowbase/projects/{slug}/sources/{id}/ destroy: DELETE
        /api/knowbase/projects/{slug}/sources/{id}/ crawl: POST
        /api/knowbase/projects/{slug}/sources/{id}/crawl/
        """
        url = f"/api/knowbase/projects/{project_slug}/sources/{id}/"
        response = self._client.put(url, json=data.model_dump(mode="json", exclude_unset=True, exclude_none=True))
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return DataSource.model_validate(response.json())


    def projects_sources_partial_update(
        self,
        id: str,
        project_slug: str,
        data: PatchedDataSourceRequest | None = None,
    ) -> DataSource:
        """
        Data source management within a project. list: GET
        /api/knowbase/projects/{slug}/sources/ create: POST
        /api/knowbase/projects/{slug}/sources/ update: PATCH
        /api/knowbase/projects/{slug}/sources/{id}/ destroy: DELETE
        /api/knowbase/projects/{slug}/sources/{id}/ crawl: POST
        /api/knowbase/projects/{slug}/sources/{id}/crawl/
        """
        url = f"/api/knowbase/projects/{project_slug}/sources/{id}/"
        _json = data.model_dump(mode="json", exclude_unset=True, exclude_none=True) if data else None
        response = self._client.patch(url, json=_json)
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return DataSource.model_validate(response.json())


    def projects_sources_destroy(self, id: str, project_slug: str) -> None:
        """
        Data source management within a project. list: GET
        /api/knowbase/projects/{slug}/sources/ create: POST
        /api/knowbase/projects/{slug}/sources/ update: PATCH
        /api/knowbase/projects/{slug}/sources/{id}/ destroy: DELETE
        /api/knowbase/projects/{slug}/sources/{id}/ crawl: POST
        /api/knowbase/projects/{slug}/sources/{id}/crawl/
        """
        url = f"/api/knowbase/projects/{project_slug}/sources/{id}/"
        response = self._client.delete(url)
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return None


    def projects_sources_crawl_create(
        self,
        id: str,
        project_slug: str,
        data: DataSourceRequest,
    ) -> None:
        """
        Trigger crawl

        Trigger an immediate crawl of this data source.
        """
        url = f"/api/knowbase/projects/{project_slug}/sources/{id}/crawl/"
        response = self._client.post(url, json=data.model_dump(mode="json", exclude_unset=True, exclude_none=True))
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return None


    def projects_retrieve(self, slug: str) -> Project:
        """
        CRUD for KnowledgeBase Projects. list: GET /api/knowbase/projects/
        create: POST /api/knowbase/projects/ retrieve: GET
        /api/knowbase/projects/{slug}/ update: PATCH
        /api/knowbase/projects/{slug}/ destroy: DELETE
        /api/knowbase/projects/{slug}/
        """
        url = f"/api/knowbase/projects/{slug}/"
        response = self._client.get(url)
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return Project.model_validate(response.json())


    def projects_update(self, slug: str, data: ProjectRequest) -> Project:
        """
        CRUD for KnowledgeBase Projects. list: GET /api/knowbase/projects/
        create: POST /api/knowbase/projects/ retrieve: GET
        /api/knowbase/projects/{slug}/ update: PATCH
        /api/knowbase/projects/{slug}/ destroy: DELETE
        /api/knowbase/projects/{slug}/
        """
        url = f"/api/knowbase/projects/{slug}/"
        response = self._client.put(url, json=data.model_dump(mode="json", exclude_unset=True, exclude_none=True))
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return Project.model_validate(response.json())


    def projects_partial_update(
        self,
        slug: str,
        data: PatchedProjectRequest | None = None,
    ) -> Project:
        """
        CRUD for KnowledgeBase Projects. list: GET /api/knowbase/projects/
        create: POST /api/knowbase/projects/ retrieve: GET
        /api/knowbase/projects/{slug}/ update: PATCH
        /api/knowbase/projects/{slug}/ destroy: DELETE
        /api/knowbase/projects/{slug}/
        """
        url = f"/api/knowbase/projects/{slug}/"
        _json = data.model_dump(mode="json", exclude_unset=True, exclude_none=True) if data else None
        response = self._client.patch(url, json=_json)
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return Project.model_validate(response.json())


    def projects_destroy(self, slug: str) -> None:
        """
        CRUD for KnowledgeBase Projects. list: GET /api/knowbase/projects/
        create: POST /api/knowbase/projects/ retrieve: GET
        /api/knowbase/projects/{slug}/ update: PATCH
        /api/knowbase/projects/{slug}/ destroy: DELETE
        /api/knowbase/projects/{slug}/
        """
        url = f"/api/knowbase/projects/{slug}/"
        response = self._client.delete(url)
        if not response.is_success:
            try:
                error_body = response.json()
            except Exception:
                error_body = response.text
            msg = f"{response.status_code}: {error_body}"
            raise httpx.HTTPStatusError(
                msg, request=response.request, response=response
            )
        return None


