use rocket::serde::Serialize;

use crate::db;

#[derive(Serialize, Clone)]
#[serde(crate = "rocket::serde")]
pub struct Course {
    pub course_id: i32,
    /// Internal name, shown in the admin panel
    ///
    /// Example: `4x4`
    pub course_name: String,
    /// Display name, partially shown on the certificate & public page
    ///
    /// Example: `Manejo en 4x4 road danger`
    pub course_display_name: String,
    /// Number of days of the course.
    /// Used to calculate how to space the courses
    ///
    /// Example: `2`
    pub course_days_amount: i32,
    /// Whether the course name can be extended with a label.
    /// Used in machinery courses, where the course name is the type of machinery,
    /// and the custom label the manufacturer and series (i.e. `320D CAT`).
    pub course_has_custom_label: bool,
}

impl Course {
    pub async fn get_all() -> Result<Vec<Course>, sqlx::Error> {
        let db = db();

        let results = sqlx::query!("SELECT * FROM course")
            .fetch_all(db)
            .await?
            .iter()
            .map(|d| Course {
                course_id: d.course_id,
                course_name: d.course_name.clone(),
                course_display_name: d.course_display_name.clone(),
                course_days_amount: d.course_days_amount,
                course_has_custom_label: d.course_has_custom_label != 0,
            })
            .collect();

        Ok(results)
    }

    pub async fn get_course_name(course_id: i32) -> Option<String> {
        let db = db();

        let res = sqlx::query!(
            "SELECT course_name FROM course WHERE course_id = ?",
            course_id
        )
        .fetch_one(db)
        .await;

        match res {
            Ok(data) => Some(data.course_name),
            Err(_) => None,
        }
    }
}
