"""
Vendors resource classes.

Auto-generated from OpenAPI specification.
"""

from __future__ import annotations

from typing import (
    TYPE_CHECKING,
    Any,
    AsyncIterator,
    Dict,
    Iterator,
    Optional,
)

if TYPE_CHECKING:
    from ..fluent import AsyncVendor, Vendor

from pydantic import BaseModel

from ..errors import ApiError, ClientValidationError
from ..models import (
    PaginatedResponse,
    VendorCreate,
    VendorResponse,
    VendorUpdate,
)


class VendorsResource:
    """Resource class for vendors operations

    Provides structured Pydantic types for all vendors API operations.
    All methods return validated Pydantic models with comprehensive error handling.

    Available operations:
        - create(): Create Vendor
        - list(): List Vendors
        - get(): Get Vendor
        - update(): Update Vendor
        - delete(): Delete Vendor
    Example:
        >>> client = CredoAI("https://api.example.com", "your-api-key")
        >>> vendors_resource = client.vendors
        >>> client.vendors.create(data=VendorCreate(...))
    """

    def __init__(self, client):
        """Initialize the VendorsResource.

        Args:
            client: The parent client instance providing HTTP functionality.
        """
        self._client = client

    def create(
        self,
        data: VendorCreate,
        *,
        timeout: Optional[float] = None,
        headers: Optional[Dict[str, str]] = None,
    ) -> VendorResponse:
        """Create Vendor.

                Create a new vendor.

        This endpoint creates a new vendor in the Credo AI vendor registry.

                Args:
                    data (VendorCreate): Request data as validated Pydantic model.
                    timeout (float, optional): Request timeout in seconds.
                    headers (Dict[str, str], optional): Additional headers to send.

                Returns:
                    VendorResponse: Validated response data.

                Response Codes:
                    201: Successful Response
                    422: Error

                Raises:
                    ApiError: When the API returns an error status code.
                    ClientValidationError: When response validation fails.
                    httpx.TimeoutException: When request times out."""
        url = "/vendors"

        return self._client._make_request(
            method="POST",
            url=url,
            data=data,
            timeout=timeout,
            headers=headers,
            response_model=VendorResponse,
            is_list_response=False,
        )

    def list(
        self,
        page_limit: Optional[Any] = None,
        page_after: Optional[Any] = None,
        *,
        timeout: Optional[float] = None,
        headers: Optional[Dict[str, str]] = None,
    ) -> PaginatedResponse[VendorResponse]:
        """List Vendors.

                List all vendors.

        This endpoint retrieves all vendors with optional pagination.
        Returns a paginated response with items and pagination metadata.

                Args:
                    page_limit (Any, optional): Parameter
                    page_after (Any, optional): Parameter
                    timeout (float, optional): Request timeout in seconds.
                    headers (Dict[str, str], optional): Additional headers to send.

                Returns:
                    List[VendorResponse]: Validated response data.

                Response Codes:
                    200: Successful Response
                    422: Error

                Raises:
                    ApiError: When the API returns an error status code.
                    ClientValidationError: When response validation fails.
                    httpx.TimeoutException: When request times out."""
        url = "/vendors"

        # Build query parameters
        params: Dict[str, Any] = {}
        if page_limit is not None:
            params["page_limit"] = page_limit
        if page_after is not None:
            params["page_after"] = page_after

        return self._client._make_request(
            method="GET",
            url=url,
            params=params if params else None,
            timeout=timeout,
            headers=headers,
            response_model=PaginatedResponse[VendorResponse],
            is_list_response=False,
        )

    def get(
        self,
        vendor_id: str,
        *,
        timeout: Optional[float] = None,
        headers: Optional[Dict[str, str]] = None,
    ) -> VendorResponse:
        """Get Vendor.

                Get a vendor by ID.

        This endpoint retrieves an existing vendor by its ID.

                Args:
                    vendor_id (str): Parameter
                    timeout (float, optional): Request timeout in seconds.
                    headers (Dict[str, str], optional): Additional headers to send.

                Returns:
                    VendorResponse: Validated response data.

                Response Codes:
                    200: Successful Response
                    422: Error

                Raises:
                    ApiError: When the API returns an error status code.
                    ClientValidationError: When response validation fails.
                    httpx.TimeoutException: When request times out."""
        url = "/vendors/{vendor_id}"
        url = url.replace("{" + "vendor_id" + "}", str(vendor_id))

        return self._client._make_request(
            method="GET",
            url=url,
            timeout=timeout,
            headers=headers,
            response_model=VendorResponse,
            is_list_response=False,
        )

    def update(
        self,
        vendor_id: str,
        data: VendorUpdate,
        *,
        timeout: Optional[float] = None,
        headers: Optional[Dict[str, str]] = None,
    ) -> VendorResponse:
        """Update Vendor.

                Update an existing vendor.

        This endpoint updates an existing vendor with the provided data.
        Only the fields provided in the request will be updated.

                Args:
                    vendor_id (str): Parameter
                    data (VendorUpdate): Request data as validated Pydantic model.
                    timeout (float, optional): Request timeout in seconds.
                    headers (Dict[str, str], optional): Additional headers to send.

                Returns:
                    VendorResponse: Validated response data.

                Response Codes:
                    200: Successful Response
                    422: Error

                Raises:
                    ApiError: When the API returns an error status code.
                    ClientValidationError: When response validation fails.
                    httpx.TimeoutException: When request times out."""
        url = "/vendors/{vendor_id}"
        url = url.replace("{" + "vendor_id" + "}", str(vendor_id))

        return self._client._make_request(
            method="PATCH",
            url=url,
            data=data,
            timeout=timeout,
            headers=headers,
            response_model=VendorResponse,
            is_list_response=False,
        )

    def delete(
        self,
        vendor_id: str,
        *,
        timeout: Optional[float] = None,
        headers: Optional[Dict[str, str]] = None,
    ) -> Any:
        """Delete Vendor.

                Delete a vendor by ID.

        This endpoint deletes an existing vendor by its ID.

                Args:
                    vendor_id (str): Parameter
                    timeout (float, optional): Request timeout in seconds.
                    headers (Dict[str, str], optional): Additional headers to send.

                Returns:
                    Any: Raw API response data.

                Response Codes:
                    204: Successful Response
                    422: Error

                Raises:
                    ApiError: When the API returns an error status code.
                    ClientValidationError: When response validation fails.
                    httpx.TimeoutException: When request times out."""
        url = "/vendors/{vendor_id}"
        url = url.replace("{" + "vendor_id" + "}", str(vendor_id))

        return self._client._make_request(
            method="DELETE",
            url=url,
            timeout=timeout,
            headers=headers,
        )

    def list_all(
        self,
        page_size: int = 100,
        *,
        timeout: Optional[float] = None,
        headers: Optional[Dict[str, str]] = None,
    ) -> Iterator[VendorResponse]:
        """Iterate through all vendors with automatic pagination.

        This generator yields items one at a time, automatically fetching
        the next page when needed. Use this for efficiently processing
        large result sets without loading everything into memory.

        Args:
            page_size (int): Number of items to fetch per page. Default: 100
            timeout (float, optional): Request timeout in seconds.
            headers (Dict[str, str], optional): Additional headers to send.

        Yields:
            VendorResponse: Individual items from the list.

        Example:
            >>> for item in client.vendors.list_all(page_size=50):
            ...     print(item.id)
            >>>
            >>> # Collect all into a list
            >>> all_items = list(client.vendors.list_all())
        """
        page_after = None
        while True:
            response = self.list(
                page_limit=page_size,
                page_after=page_after,
                timeout=timeout,
                headers=headers,
            )
            # Handle paginated response with items and pagination metadata
            items = response.items
            if not items:
                break
            for item in items:
                yield item
            # Use pagination cursor for next page
            if not response.pagination.has_more:
                break
            page_after = response.pagination.next_cursor

    def __call__(self, vendor_id: str) -> "Vendor":
        """Get a fluent accessor for a specific vendor.

        Enables intuitive subresource access:
            >>> client.vendors(vendor_id).questionnaires.list()
            >>> client.vendors(vendor_id).questionnaires.add(data)
            >>> client.vendors(vendor_id).use_cases.list()
            >>> client.vendors(vendor_id).use_cases.add(data)
            >>> client.vendors(vendor_id).models.list()
            >>> client.vendors(vendor_id).models.add(data)

        Args:
            vendor_id: The ID of the vendor

        Returns:
            Vendor: Fluent accessor for subresource operations
        """
        from ..fluent import Vendor

        return Vendor(self._client, vendor_id)


class AsyncVendorsResource:
    """Async resource class for vendors operations

    Provides async methods with structured Pydantic types for all vendors API operations.
    All methods are async and return validated Pydantic models with comprehensive error handling.

    Available async operations:
        - create(): Create Vendor
        - list(): List Vendors
        - get(): Get Vendor
        - update(): Update Vendor
        - delete(): Delete Vendor
    Example:
        >>> async_client = AsyncCredoAI("https://api.example.com", "your-api-key")
        >>> vendors_resource = async_client.vendors
        >>> result = await async_client.vendors.create(data=VendorCreate(...))
    """

    def __init__(self, client):
        """Initialize the AsyncVendorsResource.

        Args:
            client: The parent async client instance providing HTTP functionality.
        """
        self._client = client

    async def create(
        self,
        data: VendorCreate,
        *,
        timeout: Optional[float] = None,
        headers: Optional[Dict[str, str]] = None,
    ) -> VendorResponse:
        """Create Vendor.

                Create a new vendor.

        This endpoint creates a new vendor in the Credo AI vendor registry.

                Args:
                    data (VendorCreate): Request data as validated Pydantic model.
                    timeout (float, optional): Request timeout in seconds.
                    headers (Dict[str, str], optional): Additional headers to send.

                Returns:
                    VendorResponse: Validated response data.

                Response Codes:
                    201: Successful Response
                    422: Error

                Raises:
                    ApiError: When the API returns an error status code.
                    ClientValidationError: When response validation fails.
                    httpx.TimeoutException: When request times out."""
        # Prepare URL with path parameters
        url = "/vendors"

        # Prepare headers
        request_headers = {"Accept": "application/json"}
        if headers:
            request_headers.update(headers)
        # Serialize request data
        json_data = None
        if data is not None:
            if isinstance(data, BaseModel):
                json_data = data.model_dump(exclude_unset=True, by_alias=True)
            else:
                json_data = data
            request_headers["Content-Type"] = "application/json"

        # Make async request
        httpx_client = self._client.get_async_httpx_client()
        response = await httpx_client.request(
            method="POST",
            url=url,
            json=json_data,
            headers=request_headers,
            timeout=timeout,
        )

        # Handle errors
        if response.status_code >= 400:
            raise ApiError(
                status_code=response.status_code,
                message=f"POST {url} failed",
                response=response,
            )

        # Parse and validate response
        if self._client._validate_responses and response.content:
            try:
                response_data = response.json()

                # Handle JSON:API format
                if isinstance(response_data, dict) and "data" in response_data:
                    from ..models import JsonApiResponse

                    jsonapi_response = JsonApiResponse.model_validate(response_data)
                    data = jsonapi_response.data
                    # Check for attributes in both dict and object forms
                    if isinstance(data, dict) and "attributes" in data:
                        # Merge id from data level with attributes
                        merged = {"id": data.get("id"), **data["attributes"]}
                        parsed_data = VendorResponse.model_validate(merged)
                    elif hasattr(data, "attributes"):
                        parsed_data = VendorResponse.model_validate(data.attributes)
                    else:
                        parsed_data = VendorResponse.model_validate(data)
                    return parsed_data
                parsed_data = VendorResponse.model_validate(response_data)
                return parsed_data

            except Exception as e:
                if self._client._validate_responses:
                    raise ClientValidationError(f"Response validation failed: {e}")

        # Return basic response wrapper
        from ..models import ClientResponse

        return ClientResponse.from_httpx_response(
            response, response.json() if response.content else None
        )

    async def list(
        self,
        page_limit: Optional[Any] = None,
        page_after: Optional[Any] = None,
        *,
        timeout: Optional[float] = None,
        headers: Optional[Dict[str, str]] = None,
    ) -> PaginatedResponse[VendorResponse]:
        """List Vendors.

                List all vendors.

        This endpoint retrieves all vendors with optional pagination.
        Returns a paginated response with items and pagination metadata.

                Args:
                    page_limit (Any, optional): Parameter
                    page_after (Any, optional): Parameter
                    timeout (float, optional): Request timeout in seconds.
                    headers (Dict[str, str], optional): Additional headers to send.

                Returns:
                    List[VendorResponse]: Validated response data.

                Response Codes:
                    200: Successful Response
                    422: Error

                Raises:
                    ApiError: When the API returns an error status code.
                    ClientValidationError: When response validation fails.
                    httpx.TimeoutException: When request times out."""
        # Prepare URL with path parameters
        url = "/vendors"

        # Build query parameters
        params: Dict[str, Any] = {}
        if page_limit is not None:
            params["page_limit"] = page_limit
        if page_after is not None:
            params["page_after"] = page_after

        # Prepare headers
        request_headers = {"Accept": "application/json"}
        if headers:
            request_headers.update(headers)

        # Make async request
        httpx_client = self._client.get_async_httpx_client()
        response = await httpx_client.request(
            method="GET",
            url=url,
            params=params if params else None,
            headers=request_headers,
            timeout=timeout,
        )

        # Handle errors
        if response.status_code >= 400:
            raise ApiError(
                status_code=response.status_code,
                message=f"GET {url} failed",
                response=response,
            )

        # Parse and validate response
        if self._client._validate_responses and response.content:
            try:
                response_data = response.json()

                # Handle JSON:API format
                if isinstance(response_data, dict) and "data" in response_data:
                    from ..models import JsonApiResponse

                    jsonapi_response = JsonApiResponse.model_validate(response_data)
                    data = jsonapi_response.data
                    # Check for attributes in both dict and object forms
                    if isinstance(data, dict) and "attributes" in data:
                        # Merge id from data level with attributes
                        merged = {"id": data.get("id"), **data["attributes"]}
                        parsed_data = VendorResponse.model_validate(merged)
                    elif hasattr(data, "attributes"):
                        parsed_data = VendorResponse.model_validate(data.attributes)
                    else:
                        parsed_data = VendorResponse.model_validate(data)
                    return parsed_data
                # Handle paginated response
                parsed_data = PaginatedResponse[VendorResponse].model_validate(
                    response_data
                )
                return parsed_data

            except Exception as e:
                if self._client._validate_responses:
                    raise ClientValidationError(f"Response validation failed: {e}")

        # Return basic response wrapper
        from ..models import ClientResponse

        return ClientResponse.from_httpx_response(
            response, response.json() if response.content else None
        )

    async def get(
        self,
        vendor_id: str,
        *,
        timeout: Optional[float] = None,
        headers: Optional[Dict[str, str]] = None,
    ) -> VendorResponse:
        """Get Vendor.

                Get a vendor by ID.

        This endpoint retrieves an existing vendor by its ID.

                Args:
                    vendor_id (str): Parameter
                    timeout (float, optional): Request timeout in seconds.
                    headers (Dict[str, str], optional): Additional headers to send.

                Returns:
                    VendorResponse: Validated response data.

                Response Codes:
                    200: Successful Response
                    422: Error

                Raises:
                    ApiError: When the API returns an error status code.
                    ClientValidationError: When response validation fails.
                    httpx.TimeoutException: When request times out."""
        # Prepare URL with path parameters
        url = "/vendors/{vendor_id}"
        url = url.replace("{" + "vendor_id" + "}", str(vendor_id))

        # Prepare headers
        request_headers = {"Accept": "application/json"}
        if headers:
            request_headers.update(headers)

        # Make async request
        httpx_client = self._client.get_async_httpx_client()
        response = await httpx_client.request(
            method="GET", url=url, headers=request_headers, timeout=timeout
        )

        # Handle errors
        if response.status_code >= 400:
            raise ApiError(
                status_code=response.status_code,
                message=f"GET {url} failed",
                response=response,
            )

        # Parse and validate response
        if self._client._validate_responses and response.content:
            try:
                response_data = response.json()

                # Handle JSON:API format
                if isinstance(response_data, dict) and "data" in response_data:
                    from ..models import JsonApiResponse

                    jsonapi_response = JsonApiResponse.model_validate(response_data)
                    data = jsonapi_response.data
                    # Check for attributes in both dict and object forms
                    if isinstance(data, dict) and "attributes" in data:
                        # Merge id from data level with attributes
                        merged = {"id": data.get("id"), **data["attributes"]}
                        parsed_data = VendorResponse.model_validate(merged)
                    elif hasattr(data, "attributes"):
                        parsed_data = VendorResponse.model_validate(data.attributes)
                    else:
                        parsed_data = VendorResponse.model_validate(data)
                    return parsed_data
                parsed_data = VendorResponse.model_validate(response_data)
                return parsed_data

            except Exception as e:
                if self._client._validate_responses:
                    raise ClientValidationError(f"Response validation failed: {e}")

        # Return basic response wrapper
        from ..models import ClientResponse

        return ClientResponse.from_httpx_response(
            response, response.json() if response.content else None
        )

    async def update(
        self,
        vendor_id: str,
        data: VendorUpdate,
        *,
        timeout: Optional[float] = None,
        headers: Optional[Dict[str, str]] = None,
    ) -> VendorResponse:
        """Update Vendor.

                Update an existing vendor.

        This endpoint updates an existing vendor with the provided data.
        Only the fields provided in the request will be updated.

                Args:
                    vendor_id (str): Parameter
                    data (VendorUpdate): Request data as validated Pydantic model.
                    timeout (float, optional): Request timeout in seconds.
                    headers (Dict[str, str], optional): Additional headers to send.

                Returns:
                    VendorResponse: Validated response data.

                Response Codes:
                    200: Successful Response
                    422: Error

                Raises:
                    ApiError: When the API returns an error status code.
                    ClientValidationError: When response validation fails.
                    httpx.TimeoutException: When request times out."""
        # Prepare URL with path parameters
        url = "/vendors/{vendor_id}"
        url = url.replace("{" + "vendor_id" + "}", str(vendor_id))

        # Prepare headers
        request_headers = {"Accept": "application/json"}
        if headers:
            request_headers.update(headers)
        # Serialize request data
        json_data = None
        if data is not None:
            if isinstance(data, BaseModel):
                json_data = data.model_dump(exclude_unset=True, by_alias=True)
            else:
                json_data = data
            request_headers["Content-Type"] = "application/json"

        # Make async request
        httpx_client = self._client.get_async_httpx_client()
        response = await httpx_client.request(
            method="PATCH",
            url=url,
            json=json_data,
            headers=request_headers,
            timeout=timeout,
        )

        # Handle errors
        if response.status_code >= 400:
            raise ApiError(
                status_code=response.status_code,
                message=f"PATCH {url} failed",
                response=response,
            )

        # Parse and validate response
        if self._client._validate_responses and response.content:
            try:
                response_data = response.json()

                # Handle JSON:API format
                if isinstance(response_data, dict) and "data" in response_data:
                    from ..models import JsonApiResponse

                    jsonapi_response = JsonApiResponse.model_validate(response_data)
                    data = jsonapi_response.data
                    # Check for attributes in both dict and object forms
                    if isinstance(data, dict) and "attributes" in data:
                        # Merge id from data level with attributes
                        merged = {"id": data.get("id"), **data["attributes"]}
                        parsed_data = VendorResponse.model_validate(merged)
                    elif hasattr(data, "attributes"):
                        parsed_data = VendorResponse.model_validate(data.attributes)
                    else:
                        parsed_data = VendorResponse.model_validate(data)
                    return parsed_data
                parsed_data = VendorResponse.model_validate(response_data)
                return parsed_data

            except Exception as e:
                if self._client._validate_responses:
                    raise ClientValidationError(f"Response validation failed: {e}")

        # Return basic response wrapper
        from ..models import ClientResponse

        return ClientResponse.from_httpx_response(
            response, response.json() if response.content else None
        )

    async def delete(
        self,
        vendor_id: str,
        *,
        timeout: Optional[float] = None,
        headers: Optional[Dict[str, str]] = None,
    ) -> Any:
        """Delete Vendor.

                Delete a vendor by ID.

        This endpoint deletes an existing vendor by its ID.

                Args:
                    vendor_id (str): Parameter
                    timeout (float, optional): Request timeout in seconds.
                    headers (Dict[str, str], optional): Additional headers to send.

                Returns:
                    Any: Raw API response data.

                Response Codes:
                    204: Successful Response
                    422: Error

                Raises:
                    ApiError: When the API returns an error status code.
                    ClientValidationError: When response validation fails.
                    httpx.TimeoutException: When request times out."""
        # Prepare URL with path parameters
        url = "/vendors/{vendor_id}"
        url = url.replace("{" + "vendor_id" + "}", str(vendor_id))

        # Prepare headers
        request_headers = {"Accept": "application/json"}
        if headers:
            request_headers.update(headers)

        # Make async request
        httpx_client = self._client.get_async_httpx_client()
        response = await httpx_client.request(
            method="DELETE", url=url, headers=request_headers, timeout=timeout
        )

        # Handle errors
        if response.status_code >= 400:
            raise ApiError(
                status_code=response.status_code,
                message=f"DELETE {url} failed",
                response=response,
            )

        # Parse and validate response

        # Return basic response wrapper
        from ..models import ClientResponse

        return ClientResponse.from_httpx_response(
            response, response.json() if response.content else None
        )

    async def list_all(
        self,
        page_size: int = 100,
        *,
        timeout: Optional[float] = None,
        headers: Optional[Dict[str, str]] = None,
    ) -> AsyncIterator[VendorResponse]:
        """Asynchronously iterate through all vendors with automatic pagination.

        This async generator yields items one at a time, automatically fetching
        the next page when needed. Use this for efficiently processing
        large result sets without loading everything into memory.

        Args:
            page_size (int): Number of items to fetch per page. Default: 100
            timeout (float, optional): Request timeout in seconds.
            headers (Dict[str, str], optional): Additional headers to send.

        Yields:
            VendorResponse: Individual items from the list.

        Example:
            >>> async for item in client.vendors.list_all(page_size=50):
            ...     print(item.id)
            >>>
            >>> # Collect all into a list
            >>> all_items = [item async for item in client.vendors.list_all()]
        """
        page_after = None
        while True:
            response = await self.list(
                page_limit=page_size,
                page_after=page_after,
                timeout=timeout,
                headers=headers,
            )
            # Handle paginated response with items and pagination metadata
            items = response.items
            if not items:
                break
            for item in items:
                yield item
            # Use pagination cursor for next page
            if not response.pagination.has_more:
                break
            page_after = response.pagination.next_cursor

    def __call__(self, vendor_id: str) -> "AsyncVendor":
        """Get an async fluent accessor for a specific vendor.

        Enables intuitive subresource access with async/await:
            >>> await client.vendors(vendor_id).questionnaires.list()
            >>> await client.vendors(vendor_id).questionnaires.add(data)
            >>> await client.vendors(vendor_id).use_cases.list()
            >>> await client.vendors(vendor_id).use_cases.add(data)
            >>> await client.vendors(vendor_id).models.list()
            >>> await client.vendors(vendor_id).models.add(data)

        Args:
            vendor_id: The ID of the vendor

        Returns:
            AsyncVendor: Async fluent accessor for subresource operations
        """
        from ..fluent import AsyncVendor

        return AsyncVendor(self._client, vendor_id)
