use std::sync::Arc;

use crate::client::TetrixClient;
use crate::errors::TetrixError;
use crate::types::*;

impl TetrixClient {
    pub async fn create_category(
        self: &Arc<Self>,
        req: &CreateCategoryRequest,
    ) -> Result<CreateCategoryResponse, TetrixError> {
        self.request("CREATE_CATEGORY", req).await
    }

    pub async fn get_category(
        self: &Arc<Self>,
        category_id: &str,
    ) -> Result<GetCategoryResponse, TetrixError> {
        self.request("GET_CATEGORY", &GetCategoryRequest {
            category_id: category_id.to_string(),
        }).await
    }

    pub async fn update_category(
        self: &Arc<Self>,
        req: &UpdateCategoryRequest,
    ) -> Result<UpdateCategoryResponse, TetrixError> {
        self.request("UPDATE_CATEGORY", req).await
    }

    pub async fn delete_category(
        self: &Arc<Self>,
        category_id: &str,
    ) -> Result<(), TetrixError> {
        let _: DeleteCategoryResponse = self
            .request("DELETE_CATEGORY", &DeleteCategoryRequest {
                category_id: category_id.to_string(),
            })
            .await?;
        Ok(())
    }

    pub async fn list_categories(
        self: &Arc<Self>,
        req: Option<&ListCategoriesRequest>,
    ) -> Result<ListCategoriesResponse, TetrixError> {
        let default = ListCategoriesRequest::default();
        let req = req.unwrap_or(&default);
        self.request("LIST_CATEGORIES", req).await
    }

    pub async fn assign_entity_category(
        self: &Arc<Self>,
        entity_id: &str,
        category_id: &str,
    ) -> Result<AssignEntityCategoryResponse, TetrixError> {
        self.request("ASSIGN_ENTITY_CATEGORY", &AssignEntityCategoryRequest {
            entity_id: entity_id.to_string(),
            category_id: category_id.to_string(),
        }).await
    }

    pub async fn unassign_entity_category(
        self: &Arc<Self>,
        entity_id: &str,
        category_id: &str,
    ) -> Result<(), TetrixError> {
        let _: UnassignEntityCategoryResponse = self
            .request("UNASSIGN_ENTITY_CATEGORY", &UnassignEntityCategoryRequest {
                entity_id: entity_id.to_string(),
                category_id: category_id.to_string(),
            })
            .await?;
        Ok(())
    }

    pub async fn list_entity_categories(
        self: &Arc<Self>,
        entity_id: &str,
    ) -> Result<ListEntityCategoriesResponse, TetrixError> {
        self.request("LIST_ENTITY_CATEGORIES", &ListEntityCategoriesRequest {
            entity_id: entity_id.to_string(),
        }).await
    }
}
