use diesel::prelude::*;
use serde::Serialize;
use uuid::Uuid;

use super::DbError;
use crate::schema::projects::dsl;

#[derive(Queryable, Selectable, Debug, Clone, Serialize)]
#[diesel(table_name = crate::schema::projects)]
#[diesel(check_for_backend(diesel::sqlite::Sqlite))]
pub struct Project {
    pub id: String,
    pub creator_id: String,
    pub name: String,
    pub description: String,
    pub key: String,
}

#[derive(Insertable)]
#[diesel(table_name = crate::schema::projects)]
pub struct NewProject {
    pub id: String,
    pub creator_id: String,
    pub name: String,
    pub description: String,
    pub key: String,
}

impl NewProject {
    pub fn new(creator_id: String, name: String, description: String, key: String) -> Self {
        Self { id: Uuid::now_v7().to_string(), creator_id, name, description, key }
    }
}

pub mod q {
    use super::*;

    pub fn for_user(conn: &mut SqliteConnection, user_id: String) -> Result<Vec<Project>, DbError> {
        let projects =
            dsl::projects.filter(dsl::creator_id.eq(user_id.to_string())).load::<Project>(conn)?;
        Ok(projects)
    }

    pub fn create(
        conn: &mut SqliteConnection,
        new_project: NewProject,
    ) -> Result<Project, diesel::result::Error> {
        use crate::schema::projects::dsl as p;

        let project = diesel::insert_into(p::projects).values(new_project).get_result(conn)?;

        Ok(project)
    }
}