"""
Fluent accessor classes for Model resources.

Auto-generated from OpenAPI specification.
"""

from typing import TYPE_CHECKING, Any, Dict, Optional, Union

from ..models import (
    PaginatedResponse,
    QuestionnaireAttachment,
    QuestionnaireAttachmentResponse,
    UseCaseResponse,
    VendorResponse,
)

if TYPE_CHECKING:
    from ..client import AsyncCredoAI, CredoAI


# =============================================================================
# Model Fluent Accessors (Sync)
# =============================================================================


class ModelQuestionnairesAccessor:
    """Manage questionnaires for a specific model.

    This accessor provides methods to add, list, patch, remove
    questionnaires associated with a model.

    Example:
        >>> client.model("model-id").questionnaires.list()
        >>> client.model("model-id").questionnaires.add(QuestionnaireAttachment(key="...", version=1))
        >>> client.model("model-id").questionnaires.remove("questionnaire-id")
    """

    def __init__(self, client: "CredoAI", model_id: str):
        """Initialize the questionnaires accessor.

        Args:
            client: The CredoAI client instance
            model_id: The ID of the parent model
        """
        self._client = client
        self._model_id = model_id

    def list(
        self,
        cursor: Optional[str] = None,
        limit: Optional[int] = None,
    ) -> "PaginatedResponse[QuestionnaireAttachmentResponse]":
        """List questionnaires associated with this model.

        Args:
            cursor: Pagination cursor for next page
            limit: Maximum number of results to return

        Returns:
            PaginatedResponse containing QuestionnaireAttachmentResponse items
        """
        params: Dict[str, Any] = {}
        if cursor is not None:
            params["cursor"] = cursor
        if limit is not None:
            params["limit"] = limit

        return self._client._make_request(
            method="GET",
            url=f"/models/{self._model_id}/questionnaires",
            params=params if params else None,
            response_model=PaginatedResponse[QuestionnaireAttachmentResponse],
        )

    def add(
        self,
        questionnaire: "Union[QuestionnaireAttachment, QuestionnaireAttachmentResponse]",
    ) -> "QuestionnaireAttachmentResponse":
        """Add a questionnaire to this model.

        Args:
            questionnaire: A QuestionnaireAttachment object, or a QuestionnaireAttachmentResponse to extract fields from

        Returns:
            QuestionnaireAttachmentResponse: The added questionnaire

        Examples:
            >>> # Using request model directly
            >>> model.questionnaires.add(QuestionnaireAttachment(...))
            >>> # Using a fetched response object (extracts matching fields)
            >>> fetched = client.questionnaires.get("id")
            >>> model.questionnaires.add(fetched)
        """
        if isinstance(questionnaire, QuestionnaireAttachment):
            data = questionnaire
        else:
            # Extract fields from response object to create request model
            field_values = {
                field: getattr(questionnaire, field)
                for field in QuestionnaireAttachment.model_fields
                if hasattr(questionnaire, field)
            }
            data = QuestionnaireAttachment(**field_values)

        return self._client._make_request(
            method="POST",
            url=f"/models/{self._model_id}/questionnaires",
            data=data,
            response_model=QuestionnaireAttachmentResponse,
        )

    def remove(self, questionnaire_id: str) -> None:
        """Remove a questionnaire from this model.

        Args:
            questionnaire_id: The ID of the questionnaire to remove
        """
        self._client._make_request(
            method="DELETE",
            url=f"/models/{self._model_id}/questionnaires/{questionnaire_id}",
        )


class ModelUseCasesAccessor:
    """Manage use_cases for a specific model.

    This accessor provides methods to add, list, remove
    use_cases associated with a model.

    Example:
        >>> client.model("model-id").use_cases.list()
        >>> client.model("model-id").use_cases.add("use_case-id")
        >>> client.model("model-id").use_cases.remove("use_case-id")
    """

    def __init__(self, client: "CredoAI", model_id: str):
        """Initialize the use_cases accessor.

        Args:
            client: The CredoAI client instance
            model_id: The ID of the parent model
        """
        self._client = client
        self._model_id = model_id

    def list(
        self,
        cursor: Optional[str] = None,
        limit: Optional[int] = None,
    ) -> "PaginatedResponse[UseCaseResponse]":
        """List use_cases associated with this model.

        Args:
            cursor: Pagination cursor for next page
            limit: Maximum number of results to return

        Returns:
            PaginatedResponse containing UseCaseResponse items
        """
        params: Dict[str, Any] = {}
        if cursor is not None:
            params["cursor"] = cursor
        if limit is not None:
            params["limit"] = limit

        return self._client._make_request(
            method="GET",
            url=f"/models/{self._model_id}/use_cases",
            params=params if params else None,
            response_model=PaginatedResponse[UseCaseResponse],
        )

    def add(self, use_case: "Union[str, UseCaseResponse]") -> "UseCaseResponse":
        """Add a use_case to this model.

        Args:
            use_case: The use_case ID as a string, or a UseCaseResponse object

        Returns:
            UseCaseResponse: The added use_case

        Examples:
            >>> # Using ID directly
            >>> model.use_cases.add("use_case-123")
            >>> # Using a fetched/created response object
            >>> created = client.use_cases.create(...)
            >>> model.use_cases.add(created)
        """
        use_case_id = use_case if isinstance(use_case, str) else use_case.id

        return self._client._make_request(
            method="POST",
            url=f"/models/{self._model_id}/use_cases",
            data={"id": use_case_id},
            response_model=UseCaseResponse,
        )

    def remove(self, use_case_id: str) -> None:
        """Remove a use_case from this model.

        Args:
            use_case_id: The ID of the use_case to remove
        """
        self._client._make_request(
            method="DELETE",
            url=f"/models/{self._model_id}/use_cases/{use_case_id}",
        )


class ModelVendorsAccessor:
    """Manage vendors for a specific model.

    This accessor provides methods to add, list, remove
    vendors associated with a model.

    Example:
        >>> client.model("model-id").vendors.list()
        >>> client.model("model-id").vendors.add("vendor-id")
        >>> client.model("model-id").vendors.remove("vendor-id")
    """

    def __init__(self, client: "CredoAI", model_id: str):
        """Initialize the vendors accessor.

        Args:
            client: The CredoAI client instance
            model_id: The ID of the parent model
        """
        self._client = client
        self._model_id = model_id

    def list(
        self,
        cursor: Optional[str] = None,
        limit: Optional[int] = None,
    ) -> "PaginatedResponse[VendorResponse]":
        """List vendors associated with this model.

        Args:
            cursor: Pagination cursor for next page
            limit: Maximum number of results to return

        Returns:
            PaginatedResponse containing VendorResponse items
        """
        params: Dict[str, Any] = {}
        if cursor is not None:
            params["cursor"] = cursor
        if limit is not None:
            params["limit"] = limit

        return self._client._make_request(
            method="GET",
            url=f"/models/{self._model_id}/vendors",
            params=params if params else None,
            response_model=PaginatedResponse[VendorResponse],
        )

    def add(self, vendor: "Union[str, VendorResponse]") -> "VendorResponse":
        """Add a vendor to this model.

        Args:
            vendor: The vendor ID as a string, or a VendorResponse object

        Returns:
            VendorResponse: The added vendor

        Examples:
            >>> # Using ID directly
            >>> model.vendors.add("vendor-123")
            >>> # Using a fetched/created response object
            >>> created = client.vendors.create(...)
            >>> model.vendors.add(created)
        """
        vendor_id = vendor if isinstance(vendor, str) else vendor.id

        return self._client._make_request(
            method="POST",
            url=f"/models/{self._model_id}/vendors",
            data={"id": vendor_id},
            response_model=VendorResponse,
        )

    def remove(self, vendor_id: str) -> None:
        """Remove a vendor from this model.

        Args:
            vendor_id: The ID of the vendor to remove
        """
        self._client._make_request(
            method="DELETE",
            url=f"/models/{self._model_id}/vendors/{vendor_id}",
        )


class Model:
    """Fluent accessor for a specific model.

    Provides access to related resources through property accessors that enable
    intuitive chaining.

    Example:
        >>> model = client.model("model-id")
        >>> model.questionnaires.list()
        >>> model.questionnaires.add(QuestionnaireAttachment(key="...", version=1))
        >>> model.use_cases.list()
        >>> model.use_cases.add("use_case-id")
        >>> model.vendors.list()
        >>> model.vendors.add("vendor-id")
    """

    def __init__(self, client: "CredoAI", model_id: str):
        """Initialize the model accessor.

        Args:
            client: The CredoAI client instance
            model_id: The ID of the model
        """
        self._client = client
        self._model_id = model_id

    @property
    def questionnaires(self) -> "ModelQuestionnairesAccessor":
        """Access questionnaires associated with this model.

        Returns:
            ModelQuestionnairesAccessor: Accessor for questionnaires operations
        """
        return ModelQuestionnairesAccessor(self._client, self._model_id)

    @property
    def use_cases(self) -> "ModelUseCasesAccessor":
        """Access use_cases associated with this model.

        Returns:
            ModelUseCasesAccessor: Accessor for use_cases operations
        """
        return ModelUseCasesAccessor(self._client, self._model_id)

    @property
    def vendors(self) -> "ModelVendorsAccessor":
        """Access vendors associated with this model.

        Returns:
            ModelVendorsAccessor: Accessor for vendors operations
        """
        return ModelVendorsAccessor(self._client, self._model_id)


# =============================================================================
# Model Fluent Accessors (Async)
# =============================================================================


class AsyncModelQuestionnairesAccessor:
    """Async manage questionnaires for a specific model.

    This accessor provides async methods to add, list, patch, remove
    questionnaires associated with a model.

    Example:
        >>> await client.model("model-id").questionnaires.list()
        >>> await client.model("model-id").questionnaires.add(QuestionnaireAttachment(key="...", version=1))
        >>> await client.model("model-id").questionnaires.remove("questionnaire-id")
    """

    def __init__(self, client: "AsyncCredoAI", model_id: str):
        """Initialize the async questionnaires accessor.

        Args:
            client: The AsyncCredoAI client instance
            model_id: The ID of the parent model
        """
        self._client = client
        self._model_id = model_id

    async def list(
        self,
        cursor: Optional[str] = None,
        limit: Optional[int] = None,
    ) -> "PaginatedResponse[QuestionnaireAttachmentResponse]":
        """List questionnaires associated with this model.

        Args:
            cursor: Pagination cursor for next page
            limit: Maximum number of results to return

        Returns:
            PaginatedResponse containing QuestionnaireAttachmentResponse items
        """
        params: Dict[str, Any] = {}
        if cursor is not None:
            params["cursor"] = cursor
        if limit is not None:
            params["limit"] = limit

        return await self._client._make_request_async(
            method="GET",
            url=f"/models/{self._model_id}/questionnaires",
            params=params if params else None,
            response_model=PaginatedResponse[QuestionnaireAttachmentResponse],
        )

    async def add(
        self,
        questionnaire: "Union[QuestionnaireAttachment, QuestionnaireAttachmentResponse]",
    ) -> "QuestionnaireAttachmentResponse":
        """Add a questionnaire to this model.

        Args:
            questionnaire: A QuestionnaireAttachment object, or a QuestionnaireAttachmentResponse to extract fields from

        Returns:
            QuestionnaireAttachmentResponse: The added questionnaire

        Examples:
            >>> # Using request model directly
            >>> model.questionnaires.add(QuestionnaireAttachment(...))
            >>> # Using a fetched response object (extracts matching fields)
            >>> fetched = client.questionnaires.get("id")
            >>> model.questionnaires.add(fetched)
        """
        if isinstance(questionnaire, QuestionnaireAttachment):
            data = questionnaire
        else:
            # Extract fields from response object to create request model
            field_values = {
                field: getattr(questionnaire, field)
                for field in QuestionnaireAttachment.model_fields
                if hasattr(questionnaire, field)
            }
            data = QuestionnaireAttachment(**field_values)

        return await self._client._make_request_async(
            method="POST",
            url=f"/models/{self._model_id}/questionnaires",
            data=data,
            response_model=QuestionnaireAttachmentResponse,
        )

    async def remove(self, questionnaire_id: str) -> None:
        """Remove a questionnaire from this model.

        Args:
            questionnaire_id: The ID of the questionnaire to remove
        """
        await self._client._make_request_async(
            method="DELETE",
            url=f"/models/{self._model_id}/questionnaires/{questionnaire_id}",
        )


class AsyncModelUseCasesAccessor:
    """Async manage use_cases for a specific model.

    This accessor provides async methods to add, list, remove
    use_cases associated with a model.

    Example:
        >>> await client.model("model-id").use_cases.list()
        >>> await client.model("model-id").use_cases.add("use_case-id")
        >>> await client.model("model-id").use_cases.remove("use_case-id")
    """

    def __init__(self, client: "AsyncCredoAI", model_id: str):
        """Initialize the async use_cases accessor.

        Args:
            client: The AsyncCredoAI client instance
            model_id: The ID of the parent model
        """
        self._client = client
        self._model_id = model_id

    async def list(
        self,
        cursor: Optional[str] = None,
        limit: Optional[int] = None,
    ) -> "PaginatedResponse[UseCaseResponse]":
        """List use_cases associated with this model.

        Args:
            cursor: Pagination cursor for next page
            limit: Maximum number of results to return

        Returns:
            PaginatedResponse containing UseCaseResponse items
        """
        params: Dict[str, Any] = {}
        if cursor is not None:
            params["cursor"] = cursor
        if limit is not None:
            params["limit"] = limit

        return await self._client._make_request_async(
            method="GET",
            url=f"/models/{self._model_id}/use_cases",
            params=params if params else None,
            response_model=PaginatedResponse[UseCaseResponse],
        )

    async def add(self, use_case: "Union[str, UseCaseResponse]") -> "UseCaseResponse":
        """Add a use_case to this model.

        Args:
            use_case: The use_case ID as a string, or a UseCaseResponse object

        Returns:
            UseCaseResponse: The added use_case

        Examples:
            >>> # Using ID directly
            >>> model.use_cases.add("use_case-123")
            >>> # Using a fetched/created response object
            >>> created = client.use_cases.create(...)
            >>> model.use_cases.add(created)
        """
        use_case_id = use_case if isinstance(use_case, str) else use_case.id

        return await self._client._make_request_async(
            method="POST",
            url=f"/models/{self._model_id}/use_cases",
            data={"id": use_case_id},
            response_model=UseCaseResponse,
        )

    async def remove(self, use_case_id: str) -> None:
        """Remove a use_case from this model.

        Args:
            use_case_id: The ID of the use_case to remove
        """
        await self._client._make_request_async(
            method="DELETE",
            url=f"/models/{self._model_id}/use_cases/{use_case_id}",
        )


class AsyncModelVendorsAccessor:
    """Async manage vendors for a specific model.

    This accessor provides async methods to add, list, remove
    vendors associated with a model.

    Example:
        >>> await client.model("model-id").vendors.list()
        >>> await client.model("model-id").vendors.add("vendor-id")
        >>> await client.model("model-id").vendors.remove("vendor-id")
    """

    def __init__(self, client: "AsyncCredoAI", model_id: str):
        """Initialize the async vendors accessor.

        Args:
            client: The AsyncCredoAI client instance
            model_id: The ID of the parent model
        """
        self._client = client
        self._model_id = model_id

    async def list(
        self,
        cursor: Optional[str] = None,
        limit: Optional[int] = None,
    ) -> "PaginatedResponse[VendorResponse]":
        """List vendors associated with this model.

        Args:
            cursor: Pagination cursor for next page
            limit: Maximum number of results to return

        Returns:
            PaginatedResponse containing VendorResponse items
        """
        params: Dict[str, Any] = {}
        if cursor is not None:
            params["cursor"] = cursor
        if limit is not None:
            params["limit"] = limit

        return await self._client._make_request_async(
            method="GET",
            url=f"/models/{self._model_id}/vendors",
            params=params if params else None,
            response_model=PaginatedResponse[VendorResponse],
        )

    async def add(self, vendor: "Union[str, VendorResponse]") -> "VendorResponse":
        """Add a vendor to this model.

        Args:
            vendor: The vendor ID as a string, or a VendorResponse object

        Returns:
            VendorResponse: The added vendor

        Examples:
            >>> # Using ID directly
            >>> model.vendors.add("vendor-123")
            >>> # Using a fetched/created response object
            >>> created = client.vendors.create(...)
            >>> model.vendors.add(created)
        """
        vendor_id = vendor if isinstance(vendor, str) else vendor.id

        return await self._client._make_request_async(
            method="POST",
            url=f"/models/{self._model_id}/vendors",
            data={"id": vendor_id},
            response_model=VendorResponse,
        )

    async def remove(self, vendor_id: str) -> None:
        """Remove a vendor from this model.

        Args:
            vendor_id: The ID of the vendor to remove
        """
        await self._client._make_request_async(
            method="DELETE",
            url=f"/models/{self._model_id}/vendors/{vendor_id}",
        )


class AsyncModel:
    """Async fluent accessor for a specific model.

    Provides access to related resources through property accessors that enable
    intuitive chaining with async/await.

    Example:
        >>> model = client.model("model-id")
        >>> await model.questionnaires.list()
        >>> await model.questionnaires.add(QuestionnaireAttachment(key="...", version=1))
        >>> await model.use_cases.list()
        >>> await model.use_cases.add("use_case-id")
        >>> await model.vendors.list()
        >>> await model.vendors.add("vendor-id")
    """

    def __init__(self, client: "AsyncCredoAI", model_id: str):
        """Initialize the async model accessor.

        Args:
            client: The AsyncCredoAI client instance
            model_id: The ID of the model
        """
        self._client = client
        self._model_id = model_id

    @property
    def questionnaires(self) -> "AsyncModelQuestionnairesAccessor":
        """Access questionnaires associated with this model.

        Returns:
            AsyncModelQuestionnairesAccessor: Async accessor for questionnaires operations
        """
        return AsyncModelQuestionnairesAccessor(self._client, self._model_id)

    @property
    def use_cases(self) -> "AsyncModelUseCasesAccessor":
        """Access use_cases associated with this model.

        Returns:
            AsyncModelUseCasesAccessor: Async accessor for use_cases operations
        """
        return AsyncModelUseCasesAccessor(self._client, self._model_id)

    @property
    def vendors(self) -> "AsyncModelVendorsAccessor":
        """Access vendors associated with this model.

        Returns:
            AsyncModelVendorsAccessor: Async accessor for vendors operations
        """
        return AsyncModelVendorsAccessor(self._client, self._model_id)


# =============================================================================
# Export list
# =============================================================================

__all__ = [
    "Model",
    "AsyncModel",
    "ModelQuestionnairesAccessor",
    "AsyncModelQuestionnairesAccessor",
    "ModelUseCasesAccessor",
    "AsyncModelUseCasesAccessor",
    "ModelVendorsAccessor",
    "AsyncModelVendorsAccessor",
]
