use chrono::{DateTime, Utc};
use deadpool_diesel::postgres::Connection;
use diesel::{
    dsl::{auto_type, AsSelect},
    pg::Pg,
    prelude::*,
};
use uuid::Uuid;

use crate::{app_error::AppError, schema::api_keys, teams::Team};

#[derive(Associations, Clone, Debug, Identifiable, Insertable, Queryable, Selectable)]
#[diesel(table_name = api_keys)]
#[diesel(belongs_to(Team))]
pub struct ApiKey {
    pub id: Uuid,
    pub team_id: Uuid,
    pub last_used_at: Option<DateTime<Utc>>,
}

impl ApiKey {
    pub async fn generate_for_team(db_conn: &Connection, team_id: Uuid) -> Result<Self, AppError> {
        let api_key = Self {
            team_id,
            id: Uuid::new_v4(),
            last_used_at: None,
        };
        let api_key_copy = api_key.clone();
        db_conn
            .interact(move |conn| {
                diesel::insert_into(api_keys::table)
                    .values(api_key_copy)
                    .execute(conn)
            })
            .await
            .unwrap()?;
        Ok(api_key)
    }

    #[auto_type(no_type_alias)]
    pub fn all() -> _ {
        let select: AsSelect<ApiKey, Pg> = ApiKey::as_select();
        api_keys::table.select(select)
    }

    #[auto_type(no_type_alias)]
    pub fn with_id(id: Uuid) -> _ {
        api_keys::id.eq(id)
    }

    #[auto_type(no_type_alias)]
    pub fn with_team(team_id: Uuid) -> _ {
        api_keys::team_id.eq(team_id)
    }
}
