use const_format::concatcp;
use sqlx::types::chrono::{DateTime, Utc};
use sqlx::{Executor, Postgres};
use dialtone_common::ap::ActorType;
use dialtone_common::rest::actors::actor_model::OwnedActor;
use crate::db::actor::{ActorDbType, OWNER_ACTOR_JSON_OBJECT};
use crate::db::{bind_params, date_range_condition, make_where_clause, return_optional, CondParam};
pub async fn page_owned_actors_by_owner(
exec: impl Executor<'_, Database = Postgres>,
prev_date: Option<&DateTime<Utc>>,
next_date: Option<&DateTime<Utc>>,
limit: u32,
user_acct_owner: &str,
actor_type: Option<&ActorType>,
) -> Result<Option<Vec<OwnedActor>>, sqlx::Error> {
let pre_select = concatcp!(
"select json_agg(",
OWNER_ACTOR_JSON_OBJECT,
r#"
) as "owned_actor: Json<OwnedActor>" from (
select
actor.activity_pub_json,
actor.webfinger_json,
actor.owner_data,
actor.created_at,
actor.modified_at
from actor, actor_owner
"#
);
let post_select = concatcp!("order by actor.modified_at asc limit $1) as actor");
let mut conditions: Vec<String> = Vec::new();
let mut params: Vec<CondParam> = vec![CondParam::String(user_acct_owner)];
conditions.push(format!(
"actor_owner.user_owner = ${} and actor_owner.actor_id = actor.id",
params.len() + 1
));
conditions.push("visibility != 'Banned'".to_string());
let a_type_string;
if actor_type.is_some() {
let a_type = ActorDbType::from(actor_type.unwrap());
a_type_string = a_type.to_string();
params.push(CondParam::String(&a_type_string));
conditions.push(format!("type = ${}::actor_type", params.len() + 1));
}
let (conditions, params) =
date_range_condition(prev_date, next_date, "modified_at", conditions, params);
let where_clause = make_where_clause(&conditions);
let sql = format!("{} {} {}", pre_select, where_clause, post_select);
let mut query = sqlx::query(&sql).bind(limit);
query = bind_params(query, ¶ms);
let result = query.fetch_optional(exec).await?;
return_optional(&result)
}