/*
 * Zernio API
 *
 * API reference for Zernio. Authenticate with a Bearer API key. Base URL: https://zernio.com/api
 *
 * The version of the OpenAPI document: 1.0.1
 * Contact: support@zernio.com
 * Generated by: https://openapi-generator.tech
 */

use super::{configuration, ContentType, Error};
use crate::{apis::ResponseContent, models};
use reqwest;
use serde::{de::Error as _, Deserialize, Serialize};

/// struct for typed errors of method [`get_analytics`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum GetAnalyticsError {
    Status400(models::GetAnalytics400Response),
    Status401(models::InlineObject),
    Status402(models::GetAnalytics402Response),
    Status404(models::InlineObject1),
    Status424(models::AnalyticsSinglePostResponse),
    Status500(models::ErrorResponse),
    UnknownValue(serde_json::Value),
}

/// struct for typed errors of method [`get_best_time_to_post`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum GetBestTimeToPostError {
    Status401(models::InlineObject),
    Status403(models::GetBestTimeToPost403Response),
    UnknownValue(serde_json::Value),
}

/// struct for typed errors of method [`get_content_decay`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum GetContentDecayError {
    Status401(models::InlineObject),
    Status403(models::GetBestTimeToPost403Response),
    UnknownValue(serde_json::Value),
}

/// struct for typed errors of method [`get_daily_metrics`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum GetDailyMetricsError {
    Status401(models::InlineObject),
    Status402(models::GetAnalytics402Response),
    UnknownValue(serde_json::Value),
}

/// struct for typed errors of method [`get_follower_stats`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum GetFollowerStatsError {
    Status401(models::InlineObject),
    Status403(models::GetFollowerStats403Response),
    UnknownValue(serde_json::Value),
}

/// struct for typed errors of method [`get_instagram_account_insights`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum GetInstagramAccountInsightsError {
    Status400(models::GetYouTubeDailyViews400Response),
    Status401(models::InlineObject),
    Status402(models::GetAnalytics402Response),
    Status403(models::GetYouTubeDailyViews403Response),
    Status404(models::GetInstagramAccountInsights404Response),
    UnknownValue(serde_json::Value),
}

/// struct for typed errors of method [`get_instagram_demographics`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum GetInstagramDemographicsError {
    Status400(models::GetYouTubeDailyViews400Response),
    Status401(models::InlineObject),
    Status402(models::GetAnalytics402Response),
    Status403(models::GetYouTubeDailyViews403Response),
    Status404(models::GetInstagramAccountInsights404Response),
    UnknownValue(serde_json::Value),
}

/// struct for typed errors of method [`get_linked_in_aggregate_analytics`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum GetLinkedInAggregateAnalyticsError {
    Status400(models::GetLinkedInAggregateAnalytics400Response),
    Status401(models::InlineObject),
    Status402(models::GetLinkedInAggregateAnalytics402Response),
    Status403(models::GetLinkedInAggregateAnalytics403Response),
    Status404(),
    UnknownValue(serde_json::Value),
}

/// struct for typed errors of method [`get_linked_in_post_analytics`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum GetLinkedInPostAnalyticsError {
    Status400(models::GetLinkedInPostAnalytics400Response),
    Status401(models::InlineObject),
    Status402(),
    Status403(models::GetLinkedInPostAnalytics403Response),
    Status404(models::GetLinkedInAggregateAnalytics402Response),
    UnknownValue(serde_json::Value),
}

/// struct for typed errors of method [`get_linked_in_post_reactions`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum GetLinkedInPostReactionsError {
    Status400(models::GetLinkedInPostReactions400Response),
    Status401(models::InlineObject),
    Status402(),
    Status403(),
    Status404(),
    UnknownValue(serde_json::Value),
}

/// struct for typed errors of method [`get_post_timeline`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum GetPostTimelineError {
    Status400(models::GetPostTimeline400Response),
    Status401(models::InlineObject),
    Status402(models::GetAnalytics402Response),
    Status403(models::GetPostTimeline403Response),
    Status404(models::GetPostTimeline404Response),
    UnknownValue(serde_json::Value),
}

/// struct for typed errors of method [`get_posting_frequency`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum GetPostingFrequencyError {
    Status401(models::InlineObject),
    Status403(models::GetBestTimeToPost403Response),
    UnknownValue(serde_json::Value),
}

/// struct for typed errors of method [`get_you_tube_daily_views`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum GetYouTubeDailyViewsError {
    Status400(models::GetYouTubeDailyViews400Response),
    Status401(models::InlineObject),
    Status402(models::GetAnalytics402Response),
    Status403(models::GetYouTubeDailyViews403Response),
    Status412(models::YouTubeScopeMissingResponse),
    Status500(models::GetYouTubeDailyViews500Response),
    UnknownValue(serde_json::Value),
}

/// Returns analytics for posts. With postId, returns a single post. Without it, returns a paginated list with overview stats. Accepts both Zernio Post IDs and External Post IDs (auto-resolved). fromDate defaults to 90 days ago if omitted, max range 366 days. Single post lookups may return 202 (sync pending) or 424 (all platforms failed). For follower stats, use /v1/accounts/follower-stats.
pub async fn get_analytics(
    configuration: &configuration::Configuration,
    post_id: Option<&str>,
    platform: Option<&str>,
    profile_id: Option<&str>,
    account_id: Option<&str>,
    source: Option<&str>,
    from_date: Option<String>,
    to_date: Option<String>,
    limit: Option<i32>,
    page: Option<i32>,
    sort_by: Option<&str>,
    order: Option<&str>,
) -> Result<models::GetAnalytics200Response, Error<GetAnalyticsError>> {
    // add a prefix to parameters to efficiently prevent name collisions
    let p_query_post_id = post_id;
    let p_query_platform = platform;
    let p_query_profile_id = profile_id;
    let p_query_account_id = account_id;
    let p_query_source = source;
    let p_query_from_date = from_date;
    let p_query_to_date = to_date;
    let p_query_limit = limit;
    let p_query_page = page;
    let p_query_sort_by = sort_by;
    let p_query_order = order;

    let uri_str = format!("{}/v1/analytics", configuration.base_path);
    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);

    if let Some(ref param_value) = p_query_post_id {
        req_builder = req_builder.query(&[("postId", &param_value.to_string())]);
    }
    if let Some(ref param_value) = p_query_platform {
        req_builder = req_builder.query(&[("platform", &param_value.to_string())]);
    }
    if let Some(ref param_value) = p_query_profile_id {
        req_builder = req_builder.query(&[("profileId", &param_value.to_string())]);
    }
    if let Some(ref param_value) = p_query_account_id {
        req_builder = req_builder.query(&[("accountId", &param_value.to_string())]);
    }
    if let Some(ref param_value) = p_query_source {
        req_builder = req_builder.query(&[("source", &param_value.to_string())]);
    }
    if let Some(ref param_value) = p_query_from_date {
        req_builder = req_builder.query(&[("fromDate", &param_value.to_string())]);
    }
    if let Some(ref param_value) = p_query_to_date {
        req_builder = req_builder.query(&[("toDate", &param_value.to_string())]);
    }
    if let Some(ref param_value) = p_query_limit {
        req_builder = req_builder.query(&[("limit", &param_value.to_string())]);
    }
    if let Some(ref param_value) = p_query_page {
        req_builder = req_builder.query(&[("page", &param_value.to_string())]);
    }
    if let Some(ref param_value) = p_query_sort_by {
        req_builder = req_builder.query(&[("sortBy", &param_value.to_string())]);
    }
    if let Some(ref param_value) = p_query_order {
        req_builder = req_builder.query(&[("order", &param_value.to_string())]);
    }
    if let Some(ref user_agent) = configuration.user_agent {
        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
    }
    if let Some(ref token) = configuration.bearer_access_token {
        req_builder = req_builder.bearer_auth(token.to_owned());
    };

    let req = req_builder.build()?;
    let resp = configuration.client.execute(req).await?;

    let status = resp.status();
    let content_type = resp
        .headers()
        .get("content-type")
        .and_then(|v| v.to_str().ok())
        .unwrap_or("application/octet-stream");
    let content_type = super::ContentType::from(content_type);

    if !status.is_client_error() && !status.is_server_error() {
        let content = resp.text().await?;
        match content_type {
            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::GetAnalytics200Response`"))),
            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::GetAnalytics200Response`")))),
        }
    } else {
        let content = resp.text().await?;
        let entity: Option<GetAnalyticsError> = serde_json::from_str(&content).ok();
        Err(Error::ResponseError(ResponseContent {
            status,
            content,
            entity,
        }))
    }
}

/// Returns the best times to post based on historical engagement data. Groups all published posts by day of week and hour (UTC), calculating average engagement per slot. Use this to auto-schedule posts at optimal times. Requires the Analytics add-on.
pub async fn get_best_time_to_post(
    configuration: &configuration::Configuration,
    platform: Option<&str>,
    profile_id: Option<&str>,
    source: Option<&str>,
) -> Result<models::GetBestTimeToPost200Response, Error<GetBestTimeToPostError>> {
    // add a prefix to parameters to efficiently prevent name collisions
    let p_query_platform = platform;
    let p_query_profile_id = profile_id;
    let p_query_source = source;

    let uri_str = format!("{}/v1/analytics/best-time", configuration.base_path);
    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);

    if let Some(ref param_value) = p_query_platform {
        req_builder = req_builder.query(&[("platform", &param_value.to_string())]);
    }
    if let Some(ref param_value) = p_query_profile_id {
        req_builder = req_builder.query(&[("profileId", &param_value.to_string())]);
    }
    if let Some(ref param_value) = p_query_source {
        req_builder = req_builder.query(&[("source", &param_value.to_string())]);
    }
    if let Some(ref user_agent) = configuration.user_agent {
        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
    }
    if let Some(ref token) = configuration.bearer_access_token {
        req_builder = req_builder.bearer_auth(token.to_owned());
    };

    let req = req_builder.build()?;
    let resp = configuration.client.execute(req).await?;

    let status = resp.status();
    let content_type = resp
        .headers()
        .get("content-type")
        .and_then(|v| v.to_str().ok())
        .unwrap_or("application/octet-stream");
    let content_type = super::ContentType::from(content_type);

    if !status.is_client_error() && !status.is_server_error() {
        let content = resp.text().await?;
        match content_type {
            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::GetBestTimeToPost200Response`"))),
            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::GetBestTimeToPost200Response`")))),
        }
    } else {
        let content = resp.text().await?;
        let entity: Option<GetBestTimeToPostError> = serde_json::from_str(&content).ok();
        Err(Error::ResponseError(ResponseContent {
            status,
            content,
            entity,
        }))
    }
}

/// Returns how engagement accumulates over time after a post is published. Each bucket shows what percentage of the post's total engagement had been reached by that time window. Useful for understanding content lifespan (e.g. \"posts reach 78% of total engagement within 24 hours\"). Requires the Analytics add-on.
pub async fn get_content_decay(
    configuration: &configuration::Configuration,
    platform: Option<&str>,
    profile_id: Option<&str>,
    source: Option<&str>,
) -> Result<models::GetContentDecay200Response, Error<GetContentDecayError>> {
    // add a prefix to parameters to efficiently prevent name collisions
    let p_query_platform = platform;
    let p_query_profile_id = profile_id;
    let p_query_source = source;

    let uri_str = format!("{}/v1/analytics/content-decay", configuration.base_path);
    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);

    if let Some(ref param_value) = p_query_platform {
        req_builder = req_builder.query(&[("platform", &param_value.to_string())]);
    }
    if let Some(ref param_value) = p_query_profile_id {
        req_builder = req_builder.query(&[("profileId", &param_value.to_string())]);
    }
    if let Some(ref param_value) = p_query_source {
        req_builder = req_builder.query(&[("source", &param_value.to_string())]);
    }
    if let Some(ref user_agent) = configuration.user_agent {
        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
    }
    if let Some(ref token) = configuration.bearer_access_token {
        req_builder = req_builder.bearer_auth(token.to_owned());
    };

    let req = req_builder.build()?;
    let resp = configuration.client.execute(req).await?;

    let status = resp.status();
    let content_type = resp
        .headers()
        .get("content-type")
        .and_then(|v| v.to_str().ok())
        .unwrap_or("application/octet-stream");
    let content_type = super::ContentType::from(content_type);

    if !status.is_client_error() && !status.is_server_error() {
        let content = resp.text().await?;
        match content_type {
            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::GetContentDecay200Response`"))),
            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::GetContentDecay200Response`")))),
        }
    } else {
        let content = resp.text().await?;
        let entity: Option<GetContentDecayError> = serde_json::from_str(&content).ok();
        Err(Error::ResponseError(ResponseContent {
            status,
            content,
            entity,
        }))
    }
}

/// Returns daily aggregated analytics metrics and a per-platform breakdown. Each day includes post count, platform distribution, and summed metrics (impressions, reach, likes, comments, shares, saves, clicks, views). Defaults to the last 180 days. Requires the Analytics add-on.
pub async fn get_daily_metrics(
    configuration: &configuration::Configuration,
    platform: Option<&str>,
    profile_id: Option<&str>,
    account_id: Option<&str>,
    from_date: Option<String>,
    to_date: Option<String>,
    source: Option<&str>,
) -> Result<models::GetDailyMetrics200Response, Error<GetDailyMetricsError>> {
    // add a prefix to parameters to efficiently prevent name collisions
    let p_query_platform = platform;
    let p_query_profile_id = profile_id;
    let p_query_account_id = account_id;
    let p_query_from_date = from_date;
    let p_query_to_date = to_date;
    let p_query_source = source;

    let uri_str = format!("{}/v1/analytics/daily-metrics", configuration.base_path);
    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);

    if let Some(ref param_value) = p_query_platform {
        req_builder = req_builder.query(&[("platform", &param_value.to_string())]);
    }
    if let Some(ref param_value) = p_query_profile_id {
        req_builder = req_builder.query(&[("profileId", &param_value.to_string())]);
    }
    if let Some(ref param_value) = p_query_account_id {
        req_builder = req_builder.query(&[("accountId", &param_value.to_string())]);
    }
    if let Some(ref param_value) = p_query_from_date {
        req_builder = req_builder.query(&[("fromDate", &param_value.to_string())]);
    }
    if let Some(ref param_value) = p_query_to_date {
        req_builder = req_builder.query(&[("toDate", &param_value.to_string())]);
    }
    if let Some(ref param_value) = p_query_source {
        req_builder = req_builder.query(&[("source", &param_value.to_string())]);
    }
    if let Some(ref user_agent) = configuration.user_agent {
        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
    }
    if let Some(ref token) = configuration.bearer_access_token {
        req_builder = req_builder.bearer_auth(token.to_owned());
    };

    let req = req_builder.build()?;
    let resp = configuration.client.execute(req).await?;

    let status = resp.status();
    let content_type = resp
        .headers()
        .get("content-type")
        .and_then(|v| v.to_str().ok())
        .unwrap_or("application/octet-stream");
    let content_type = super::ContentType::from(content_type);

    if !status.is_client_error() && !status.is_server_error() {
        let content = resp.text().await?;
        match content_type {
            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::GetDailyMetrics200Response`"))),
            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::GetDailyMetrics200Response`")))),
        }
    } else {
        let content = resp.text().await?;
        let entity: Option<GetDailyMetricsError> = serde_json::from_str(&content).ok();
        Err(Error::ResponseError(ResponseContent {
            status,
            content,
            entity,
        }))
    }
}

/// Returns follower count history and growth metrics for connected social accounts. Requires analytics add-on subscription. Follower counts are refreshed once per day.
pub async fn get_follower_stats(
    configuration: &configuration::Configuration,
    account_ids: Option<&str>,
    profile_id: Option<&str>,
    from_date: Option<String>,
    to_date: Option<String>,
    granularity: Option<&str>,
) -> Result<models::GetFollowerStats200Response, Error<GetFollowerStatsError>> {
    // add a prefix to parameters to efficiently prevent name collisions
    let p_query_account_ids = account_ids;
    let p_query_profile_id = profile_id;
    let p_query_from_date = from_date;
    let p_query_to_date = to_date;
    let p_query_granularity = granularity;

    let uri_str = format!("{}/v1/accounts/follower-stats", configuration.base_path);
    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);

    if let Some(ref param_value) = p_query_account_ids {
        req_builder = req_builder.query(&[("accountIds", &param_value.to_string())]);
    }
    if let Some(ref param_value) = p_query_profile_id {
        req_builder = req_builder.query(&[("profileId", &param_value.to_string())]);
    }
    if let Some(ref param_value) = p_query_from_date {
        req_builder = req_builder.query(&[("fromDate", &param_value.to_string())]);
    }
    if let Some(ref param_value) = p_query_to_date {
        req_builder = req_builder.query(&[("toDate", &param_value.to_string())]);
    }
    if let Some(ref param_value) = p_query_granularity {
        req_builder = req_builder.query(&[("granularity", &param_value.to_string())]);
    }
    if let Some(ref user_agent) = configuration.user_agent {
        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
    }
    if let Some(ref token) = configuration.bearer_access_token {
        req_builder = req_builder.bearer_auth(token.to_owned());
    };

    let req = req_builder.build()?;
    let resp = configuration.client.execute(req).await?;

    let status = resp.status();
    let content_type = resp
        .headers()
        .get("content-type")
        .and_then(|v| v.to_str().ok())
        .unwrap_or("application/octet-stream");
    let content_type = super::ContentType::from(content_type);

    if !status.is_client_error() && !status.is_server_error() {
        let content = resp.text().await?;
        match content_type {
            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::GetFollowerStats200Response`"))),
            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::GetFollowerStats200Response`")))),
        }
    } else {
        let content = resp.text().await?;
        let entity: Option<GetFollowerStatsError> = serde_json::from_str(&content).ok();
        Err(Error::ResponseError(ResponseContent {
            status,
            content,
            entity,
        }))
    }
}

/// Returns account-level Instagram insights such as reach, views, accounts engaged, and total interactions. These metrics reflect the entire account's performance across all content surfaces (feed, stories, explore, profile), and are fundamentally different from post-level metrics. Data may be delayed up to 48 hours. Max 90 days, defaults to last 30 days. Requires the Analytics add-on.
pub async fn get_instagram_account_insights(
    configuration: &configuration::Configuration,
    account_id: &str,
    metrics: Option<&str>,
    since: Option<String>,
    until: Option<String>,
    metric_type: Option<&str>,
    breakdown: Option<&str>,
) -> Result<models::InstagramAccountInsightsResponse, Error<GetInstagramAccountInsightsError>> {
    // add a prefix to parameters to efficiently prevent name collisions
    let p_query_account_id = account_id;
    let p_query_metrics = metrics;
    let p_query_since = since;
    let p_query_until = until;
    let p_query_metric_type = metric_type;
    let p_query_breakdown = breakdown;

    let uri_str = format!(
        "{}/v1/analytics/instagram/account-insights",
        configuration.base_path
    );
    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);

    req_builder = req_builder.query(&[("accountId", &p_query_account_id.to_string())]);
    if let Some(ref param_value) = p_query_metrics {
        req_builder = req_builder.query(&[("metrics", &param_value.to_string())]);
    }
    if let Some(ref param_value) = p_query_since {
        req_builder = req_builder.query(&[("since", &param_value.to_string())]);
    }
    if let Some(ref param_value) = p_query_until {
        req_builder = req_builder.query(&[("until", &param_value.to_string())]);
    }
    if let Some(ref param_value) = p_query_metric_type {
        req_builder = req_builder.query(&[("metricType", &param_value.to_string())]);
    }
    if let Some(ref param_value) = p_query_breakdown {
        req_builder = req_builder.query(&[("breakdown", &param_value.to_string())]);
    }
    if let Some(ref user_agent) = configuration.user_agent {
        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
    }
    if let Some(ref token) = configuration.bearer_access_token {
        req_builder = req_builder.bearer_auth(token.to_owned());
    };

    let req = req_builder.build()?;
    let resp = configuration.client.execute(req).await?;

    let status = resp.status();
    let content_type = resp
        .headers()
        .get("content-type")
        .and_then(|v| v.to_str().ok())
        .unwrap_or("application/octet-stream");
    let content_type = super::ContentType::from(content_type);

    if !status.is_client_error() && !status.is_server_error() {
        let content = resp.text().await?;
        match content_type {
            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::InstagramAccountInsightsResponse`"))),
            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::InstagramAccountInsightsResponse`")))),
        }
    } else {
        let content = resp.text().await?;
        let entity: Option<GetInstagramAccountInsightsError> = serde_json::from_str(&content).ok();
        Err(Error::ResponseError(ResponseContent {
            status,
            content,
            entity,
        }))
    }
}

/// Returns audience demographic insights for an Instagram account, broken down by age, city, country, and/or gender. Requires at least 100 followers. Returns top 45 entries per dimension. Data may be delayed up to 48 hours. Requires the Analytics add-on.
pub async fn get_instagram_demographics(
    configuration: &configuration::Configuration,
    account_id: &str,
    metric: Option<&str>,
    breakdown: Option<&str>,
    timeframe: Option<&str>,
) -> Result<models::InstagramDemographicsResponse, Error<GetInstagramDemographicsError>> {
    // add a prefix to parameters to efficiently prevent name collisions
    let p_query_account_id = account_id;
    let p_query_metric = metric;
    let p_query_breakdown = breakdown;
    let p_query_timeframe = timeframe;

    let uri_str = format!(
        "{}/v1/analytics/instagram/demographics",
        configuration.base_path
    );
    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);

    req_builder = req_builder.query(&[("accountId", &p_query_account_id.to_string())]);
    if let Some(ref param_value) = p_query_metric {
        req_builder = req_builder.query(&[("metric", &param_value.to_string())]);
    }
    if let Some(ref param_value) = p_query_breakdown {
        req_builder = req_builder.query(&[("breakdown", &param_value.to_string())]);
    }
    if let Some(ref param_value) = p_query_timeframe {
        req_builder = req_builder.query(&[("timeframe", &param_value.to_string())]);
    }
    if let Some(ref user_agent) = configuration.user_agent {
        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
    }
    if let Some(ref token) = configuration.bearer_access_token {
        req_builder = req_builder.bearer_auth(token.to_owned());
    };

    let req = req_builder.build()?;
    let resp = configuration.client.execute(req).await?;

    let status = resp.status();
    let content_type = resp
        .headers()
        .get("content-type")
        .and_then(|v| v.to_str().ok())
        .unwrap_or("application/octet-stream");
    let content_type = super::ContentType::from(content_type);

    if !status.is_client_error() && !status.is_server_error() {
        let content = resp.text().await?;
        match content_type {
            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::InstagramDemographicsResponse`"))),
            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::InstagramDemographicsResponse`")))),
        }
    } else {
        let content = resp.text().await?;
        let entity: Option<GetInstagramDemographicsError> = serde_json::from_str(&content).ok();
        Err(Error::ResponseError(ResponseContent {
            status,
            content,
            entity,
        }))
    }
}

/// Returns aggregate analytics across all posts for a LinkedIn personal account. Org accounts should use /v1/analytics instead. Requires r_member_postAnalytics scope.
pub async fn get_linked_in_aggregate_analytics(
    configuration: &configuration::Configuration,
    account_id: &str,
    aggregation: Option<&str>,
    start_date: Option<String>,
    end_date: Option<String>,
    metrics: Option<&str>,
) -> Result<
    models::GetLinkedInAggregateAnalytics200Response,
    Error<GetLinkedInAggregateAnalyticsError>,
> {
    // add a prefix to parameters to efficiently prevent name collisions
    let p_path_account_id = account_id;
    let p_query_aggregation = aggregation;
    let p_query_start_date = start_date;
    let p_query_end_date = end_date;
    let p_query_metrics = metrics;

    let uri_str = format!(
        "{}/v1/accounts/{accountId}/linkedin-aggregate-analytics",
        configuration.base_path,
        accountId = crate::apis::urlencode(p_path_account_id)
    );
    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);

    if let Some(ref param_value) = p_query_aggregation {
        req_builder = req_builder.query(&[("aggregation", &param_value.to_string())]);
    }
    if let Some(ref param_value) = p_query_start_date {
        req_builder = req_builder.query(&[("startDate", &param_value.to_string())]);
    }
    if let Some(ref param_value) = p_query_end_date {
        req_builder = req_builder.query(&[("endDate", &param_value.to_string())]);
    }
    if let Some(ref param_value) = p_query_metrics {
        req_builder = req_builder.query(&[("metrics", &param_value.to_string())]);
    }
    if let Some(ref user_agent) = configuration.user_agent {
        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
    }
    if let Some(ref token) = configuration.bearer_access_token {
        req_builder = req_builder.bearer_auth(token.to_owned());
    };

    let req = req_builder.build()?;
    let resp = configuration.client.execute(req).await?;

    let status = resp.status();
    let content_type = resp
        .headers()
        .get("content-type")
        .and_then(|v| v.to_str().ok())
        .unwrap_or("application/octet-stream");
    let content_type = super::ContentType::from(content_type);

    if !status.is_client_error() && !status.is_server_error() {
        let content = resp.text().await?;
        match content_type {
            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::GetLinkedInAggregateAnalytics200Response`"))),
            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::GetLinkedInAggregateAnalytics200Response`")))),
        }
    } else {
        let content = resp.text().await?;
        let entity: Option<GetLinkedInAggregateAnalyticsError> =
            serde_json::from_str(&content).ok();
        Err(Error::ResponseError(ResponseContent {
            status,
            content,
            entity,
        }))
    }
}

/// Returns analytics for a specific LinkedIn post by URN. Works for both personal and organization accounts.
pub async fn get_linked_in_post_analytics(
    configuration: &configuration::Configuration,
    account_id: &str,
    urn: &str,
) -> Result<models::GetLinkedInPostAnalytics200Response, Error<GetLinkedInPostAnalyticsError>> {
    // add a prefix to parameters to efficiently prevent name collisions
    let p_path_account_id = account_id;
    let p_query_urn = urn;

    let uri_str = format!(
        "{}/v1/accounts/{accountId}/linkedin-post-analytics",
        configuration.base_path,
        accountId = crate::apis::urlencode(p_path_account_id)
    );
    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);

    req_builder = req_builder.query(&[("urn", &p_query_urn.to_string())]);
    if let Some(ref user_agent) = configuration.user_agent {
        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
    }
    if let Some(ref token) = configuration.bearer_access_token {
        req_builder = req_builder.bearer_auth(token.to_owned());
    };

    let req = req_builder.build()?;
    let resp = configuration.client.execute(req).await?;

    let status = resp.status();
    let content_type = resp
        .headers()
        .get("content-type")
        .and_then(|v| v.to_str().ok())
        .unwrap_or("application/octet-stream");
    let content_type = super::ContentType::from(content_type);

    if !status.is_client_error() && !status.is_server_error() {
        let content = resp.text().await?;
        match content_type {
            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::GetLinkedInPostAnalytics200Response`"))),
            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::GetLinkedInPostAnalytics200Response`")))),
        }
    } else {
        let content = resp.text().await?;
        let entity: Option<GetLinkedInPostAnalyticsError> = serde_json::from_str(&content).ok();
        Err(Error::ResponseError(ResponseContent {
            status,
            content,
            entity,
        }))
    }
}

/// Returns individual reactions for a specific LinkedIn post, including reactor profiles (name, headline/job title, profile picture, profile URL, reaction type). Only works for **organization/company page** accounts. LinkedIn restricts reaction data for personal profiles (r_member_social_feed is a closed permission).
pub async fn get_linked_in_post_reactions(
    configuration: &configuration::Configuration,
    account_id: &str,
    urn: &str,
    limit: Option<i32>,
    cursor: Option<&str>,
) -> Result<models::GetLinkedInPostReactions200Response, Error<GetLinkedInPostReactionsError>> {
    // add a prefix to parameters to efficiently prevent name collisions
    let p_path_account_id = account_id;
    let p_query_urn = urn;
    let p_query_limit = limit;
    let p_query_cursor = cursor;

    let uri_str = format!(
        "{}/v1/accounts/{accountId}/linkedin-post-reactions",
        configuration.base_path,
        accountId = crate::apis::urlencode(p_path_account_id)
    );
    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);

    req_builder = req_builder.query(&[("urn", &p_query_urn.to_string())]);
    if let Some(ref param_value) = p_query_limit {
        req_builder = req_builder.query(&[("limit", &param_value.to_string())]);
    }
    if let Some(ref param_value) = p_query_cursor {
        req_builder = req_builder.query(&[("cursor", &param_value.to_string())]);
    }
    if let Some(ref user_agent) = configuration.user_agent {
        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
    }
    if let Some(ref token) = configuration.bearer_access_token {
        req_builder = req_builder.bearer_auth(token.to_owned());
    };

    let req = req_builder.build()?;
    let resp = configuration.client.execute(req).await?;

    let status = resp.status();
    let content_type = resp
        .headers()
        .get("content-type")
        .and_then(|v| v.to_str().ok())
        .unwrap_or("application/octet-stream");
    let content_type = super::ContentType::from(content_type);

    if !status.is_client_error() && !status.is_server_error() {
        let content = resp.text().await?;
        match content_type {
            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::GetLinkedInPostReactions200Response`"))),
            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::GetLinkedInPostReactions200Response`")))),
        }
    } else {
        let content = resp.text().await?;
        let entity: Option<GetLinkedInPostReactionsError> = serde_json::from_str(&content).ok();
        Err(Error::ResponseError(ResponseContent {
            status,
            content,
            entity,
        }))
    }
}

/// Returns a daily timeline of analytics metrics for a specific post, showing how impressions, likes, and other metrics evolved day-by-day since publishing. Each row represents one day of data per platform. For multi-platform Zernio posts, returns separate rows for each platform. Requires the Analytics add-on.
pub async fn get_post_timeline(
    configuration: &configuration::Configuration,
    post_id: &str,
    from_date: Option<String>,
    to_date: Option<String>,
) -> Result<models::GetPostTimeline200Response, Error<GetPostTimelineError>> {
    // add a prefix to parameters to efficiently prevent name collisions
    let p_query_post_id = post_id;
    let p_query_from_date = from_date;
    let p_query_to_date = to_date;

    let uri_str = format!("{}/v1/analytics/post-timeline", configuration.base_path);
    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);

    req_builder = req_builder.query(&[("postId", &p_query_post_id.to_string())]);
    if let Some(ref param_value) = p_query_from_date {
        req_builder = req_builder.query(&[("fromDate", &param_value.to_string())]);
    }
    if let Some(ref param_value) = p_query_to_date {
        req_builder = req_builder.query(&[("toDate", &param_value.to_string())]);
    }
    if let Some(ref user_agent) = configuration.user_agent {
        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
    }
    if let Some(ref token) = configuration.bearer_access_token {
        req_builder = req_builder.bearer_auth(token.to_owned());
    };

    let req = req_builder.build()?;
    let resp = configuration.client.execute(req).await?;

    let status = resp.status();
    let content_type = resp
        .headers()
        .get("content-type")
        .and_then(|v| v.to_str().ok())
        .unwrap_or("application/octet-stream");
    let content_type = super::ContentType::from(content_type);

    if !status.is_client_error() && !status.is_server_error() {
        let content = resp.text().await?;
        match content_type {
            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::GetPostTimeline200Response`"))),
            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::GetPostTimeline200Response`")))),
        }
    } else {
        let content = resp.text().await?;
        let entity: Option<GetPostTimelineError> = serde_json::from_str(&content).ok();
        Err(Error::ResponseError(ResponseContent {
            status,
            content,
            entity,
        }))
    }
}

/// Returns the correlation between posting frequency (posts per week) and engagement rate, broken down by platform. Helps find the optimal posting cadence for each platform. Each row represents a specific (platform, posts_per_week) combination with the average engagement rate observed across all weeks matching that frequency. Requires the Analytics add-on.
pub async fn get_posting_frequency(
    configuration: &configuration::Configuration,
    platform: Option<&str>,
    profile_id: Option<&str>,
    source: Option<&str>,
) -> Result<models::GetPostingFrequency200Response, Error<GetPostingFrequencyError>> {
    // add a prefix to parameters to efficiently prevent name collisions
    let p_query_platform = platform;
    let p_query_profile_id = profile_id;
    let p_query_source = source;

    let uri_str = format!("{}/v1/analytics/posting-frequency", configuration.base_path);
    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);

    if let Some(ref param_value) = p_query_platform {
        req_builder = req_builder.query(&[("platform", &param_value.to_string())]);
    }
    if let Some(ref param_value) = p_query_profile_id {
        req_builder = req_builder.query(&[("profileId", &param_value.to_string())]);
    }
    if let Some(ref param_value) = p_query_source {
        req_builder = req_builder.query(&[("source", &param_value.to_string())]);
    }
    if let Some(ref user_agent) = configuration.user_agent {
        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
    }
    if let Some(ref token) = configuration.bearer_access_token {
        req_builder = req_builder.bearer_auth(token.to_owned());
    };

    let req = req_builder.build()?;
    let resp = configuration.client.execute(req).await?;

    let status = resp.status();
    let content_type = resp
        .headers()
        .get("content-type")
        .and_then(|v| v.to_str().ok())
        .unwrap_or("application/octet-stream");
    let content_type = super::ContentType::from(content_type);

    if !status.is_client_error() && !status.is_server_error() {
        let content = resp.text().await?;
        match content_type {
            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::GetPostingFrequency200Response`"))),
            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::GetPostingFrequency200Response`")))),
        }
    } else {
        let content = resp.text().await?;
        let entity: Option<GetPostingFrequencyError> = serde_json::from_str(&content).ok();
        Err(Error::ResponseError(ResponseContent {
            status,
            content,
            entity,
        }))
    }
}

/// Returns daily view counts for a YouTube video including views, watch time, and subscriber changes. Requires yt-analytics.readonly scope (re-authorization may be needed). Data has a 2-3 day delay. Max 90 days, defaults to last 30 days.
pub async fn get_you_tube_daily_views(
    configuration: &configuration::Configuration,
    video_id: &str,
    account_id: &str,
    start_date: Option<String>,
    end_date: Option<String>,
) -> Result<models::YouTubeDailyViewsResponse, Error<GetYouTubeDailyViewsError>> {
    // add a prefix to parameters to efficiently prevent name collisions
    let p_query_video_id = video_id;
    let p_query_account_id = account_id;
    let p_query_start_date = start_date;
    let p_query_end_date = end_date;

    let uri_str = format!(
        "{}/v1/analytics/youtube/daily-views",
        configuration.base_path
    );
    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);

    req_builder = req_builder.query(&[("videoId", &p_query_video_id.to_string())]);
    req_builder = req_builder.query(&[("accountId", &p_query_account_id.to_string())]);
    if let Some(ref param_value) = p_query_start_date {
        req_builder = req_builder.query(&[("startDate", &param_value.to_string())]);
    }
    if let Some(ref param_value) = p_query_end_date {
        req_builder = req_builder.query(&[("endDate", &param_value.to_string())]);
    }
    if let Some(ref user_agent) = configuration.user_agent {
        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
    }
    if let Some(ref token) = configuration.bearer_access_token {
        req_builder = req_builder.bearer_auth(token.to_owned());
    };

    let req = req_builder.build()?;
    let resp = configuration.client.execute(req).await?;

    let status = resp.status();
    let content_type = resp
        .headers()
        .get("content-type")
        .and_then(|v| v.to_str().ok())
        .unwrap_or("application/octet-stream");
    let content_type = super::ContentType::from(content_type);

    if !status.is_client_error() && !status.is_server_error() {
        let content = resp.text().await?;
        match content_type {
            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::YouTubeDailyViewsResponse`"))),
            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::YouTubeDailyViewsResponse`")))),
        }
    } else {
        let content = resp.text().await?;
        let entity: Option<GetYouTubeDailyViewsError> = serde_json::from_str(&content).ok();
        Err(Error::ResponseError(ResponseContent {
            status,
            content,
            entity,
        }))
    }
}
