use eiktyrner::{content, HttpClient};
use crate::{Param, PathAndQueryBuilder, Result};

use crate::Client;
use crate::models::{
     CreatedView,
     Guid,
     ProductView,
     ProductsTemplateView,
     ProductsView,
    
};


impl Client {
    
    

/// Creates a product. Note that ProductPublicId are generated by Billecta API and can't be set through the API and should be omitted when creating. CreditorPublicId specifies under which creditor it shall be created since creditors don't share data
pub async fn products_create_a_product(&self,body: ProductView,
                         
) -> Result<CreatedView> {


    let path_and_query = PathAndQueryBuilder::new()
        .url(Param::value("v1"))
        .url(Param::value("products"))
        .url(Param::value("product"))
        .build();






    let request = self.new_request(
        http::method::Method::POST,
        path_and_query,
    )
    .body(content::Json(body)).expect("setting json body");
    
    self.client.send::<_, content::Json<_>>(request).await
    
}
    
    

/// Imports multiple products. If product has ProductPublicId set it will update corresponding product. If ProductPublicId is not set the product will be created
pub async fn products_create_multiple_products(&self,body: ProductsView,
                         
) -> Result<CreatedView> {


    let path_and_query = PathAndQueryBuilder::new()
        .url(Param::value("v1"))
        .url(Param::value("products"))
        .url(Param::value("products"))
        .build();






    let request = self.new_request(
        http::method::Method::POST,
        path_and_query,
    )
    .body(content::Json(body)).expect("setting json body");
    
    self.client.send::<_, content::Json<_>>(request).await
    
}
    
    

/// 
pub async fn products_create_update_a_product(&self,body: ProductsTemplateView,
                         
) -> Result<()> {


    let path_and_query = PathAndQueryBuilder::new()
        .url(Param::value("v1"))
        .url(Param::value("products"))
        .url(Param::value("productstemplate"))
        .build();






    let request = self.new_request(
        http::method::Method::PUT,
        path_and_query,
    )
    .body(content::Json(body)).expect("setting json body");
    
    self.client.send::<_, content::Empty>(request).await
    
}
    
    

/// A product can't be deleted if it used in an invoice (of any kind)
/// - **id**: Product public id
pub async fn products_delete_a_product(&self,id: Guid,
                         
) -> Result<()> {


    let path_and_query = PathAndQueryBuilder::new()
        .url(Param::value("v1"))
        .url(Param::value("products"))
        .url(Param::value("product"))
        .url(Param::value(id))
        .build();






    let request = self.new_request(
        http::method::Method::DELETE,
        path_and_query,
    )
    .body(content::Empty).expect("setting json body");
    
    self.client.send::<_, content::Empty>(request).await
    
}
    
    

/// Returns the associated product. Note that the values on the product should only be considered as a template (except for the book keeping accounts). When creating an invoice, you must set the specific values for that invoice record/row.
/// - **id**: Product public id
pub async fn products_get_a_product(&self,id: Guid,
                         
) -> Result<ProductView> {


    let path_and_query = PathAndQueryBuilder::new()
        .url(Param::value("v1"))
        .url(Param::value("products"))
        .url(Param::value("product"))
        .url(Param::value(id))
        .build();






    let request = self.new_request(
        http::method::Method::GET,
        path_and_query,
    )
    .body(content::Empty).expect("setting json body");
    
    self.client.send::<_, content::Json<_>>(request).await
    
}
    
    

/// Get all products for a creditor
/// - **id**: Creditor public id
/// - **offset**: Offset
/// - **limit**: Limit
/// - **sortingfield**: Sorting field
/// - **asc**: Ascending sorting. Default value is true
pub async fn products_get_all_products(&self,id: Guid,
                         offset: Option<i64>,
                         limit: Option<i64>,
                         sortingfield: Option<String>,
                         asc: Option<bool>,
                         
) -> Result<ProductsView> {


    let path_and_query = PathAndQueryBuilder::new()
        .url(Param::value("v1"))
        .url(Param::value("products"))
        .url(Param::value("products"))
        .url(Param::value(id))
        .query("offset", Param::opt(offset))
        .query("limit", Param::opt(limit))
        .query("sortingfield", Param::opt(sortingfield))
        .query("asc", Param::opt(asc))
        .build();






    let request = self.new_request(
        http::method::Method::GET,
        path_and_query,
    )
    .body(content::Empty).expect("setting json body");
    
    self.client.send::<_, content::Json<_>>(request).await
    
}
    
    

/// 
/// - **id**: Creditor public id
pub async fn products_get_product_template(&self,id: Guid,
                         
) -> Result<ProductsTemplateView> {


    let path_and_query = PathAndQueryBuilder::new()
        .url(Param::value("v1"))
        .url(Param::value("products"))
        .url(Param::value("productstemplate"))
        .url(Param::value(id))
        .build();






    let request = self.new_request(
        http::method::Method::GET,
        path_and_query,
    )
    .body(content::Empty).expect("setting json body");
    
    self.client.send::<_, content::Json<_>>(request).await
    
}
    
    

/// Get products by its external id. An external id is a field on the 
/// - **id**: Creditor public id
/// - **productexternalid**: Product external id
/// - **offset**: Offset
/// - **limit**: Limit
/// - **sortingfield**: Sorting field
/// - **asc**: Ascending sorting. Default value is true
pub async fn products_get_products_by_product_external_id(&self,id: Guid,
                         productexternalid: String,
                         offset: Option<i64>,
                         limit: Option<i64>,
                         sortingfield: Option<String>,
                         asc: Option<bool>,
                         
) -> Result<ProductsView> {


    let path_and_query = PathAndQueryBuilder::new()
        .url(Param::value("v1"))
        .url(Param::value("products"))
        .url(Param::value("productsbyexternalid"))
        .url(Param::value(id))
        .query("productexternalid", Param::value(productexternalid))
        .query("offset", Param::opt(offset))
        .query("limit", Param::opt(limit))
        .query("sortingfield", Param::opt(sortingfield))
        .query("asc", Param::opt(asc))
        .build();






    let request = self.new_request(
        http::method::Method::GET,
        path_and_query,
    )
    .body(content::Empty).expect("setting json body");
    
    self.client.send::<_, content::Json<_>>(request).await
    
}
    
    

/// Note that ProductPublicId must be set when updating a product. It is used to identify which product to update. CreditorPublicId specifies under which creditor it shall be created since creditors don't share data
pub async fn products_update_a_product(&self,body: ProductView,
                         
) -> Result<()> {


    let path_and_query = PathAndQueryBuilder::new()
        .url(Param::value("v1"))
        .url(Param::value("products"))
        .url(Param::value("product"))
        .build();






    let request = self.new_request(
        http::method::Method::PUT,
        path_and_query,
    )
    .body(content::Json(body)).expect("setting json body");
    
    self.client.send::<_, content::Empty>(request).await
    
}
    
}