use crate::{
  data::{
    Value,
    condition::Condition,
    executable_query::ExecutableQuery,
    insert::InsertBuilder,
    query::QueryBuilder,
    update::UpdateBuilder,
  },
  error::Result,
};
use serde::{Deserialize, Serialize};

const TABLE_NAME: &str = "guilds";

#[derive(Serialize, Deserialize, sqlx::FromRow, Debug)]
pub struct GuildCache {
  pub id: i64,
  pub name: Option<String>,
  pub owner_id: Option<i64>,
  pub volume: i32,
}

impl GuildCache {
  pub async fn insert(&self) -> Result<()> {
    InsertBuilder::new(TABLE_NAME)
      .column("id", Value::BigInt(self.id))
      .column("name", Value::OptionalText(self.name.clone()))
      .column("owner_id", Value::OptionalBigInt(self.owner_id))
      .column("volume", Value::Int(self.volume))
      .execute()
      .await?;
    Ok(())
  }

  pub async fn find_by_id(id: i64) -> Option<Self> {
    QueryBuilder::new(TABLE_NAME)
      .where_condition(Condition::is_equal("id", Value::BigInt(id)))
      .fetch_optional()
      .await
  }

  pub async fn update(&self) -> Result<()> {
    UpdateBuilder::new(TABLE_NAME)
      .column("name", Value::OptionalText(self.name.clone()))
      .column("owner_id", Value::OptionalBigInt(self.owner_id))
      .column("volume", Value::Int(self.volume))
      .where_condition(Condition::is_equal("id", Value::BigInt(self.id)))
      .execute()
      .await?;
    Ok(())
  }
}
