Documentation
use crate::{types::*, Endpoint, LDateTime, Res};
use chrono::Local;
use serde::{Deserialize, Serialize};

#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct Lesson {
    pub uid: String,
    pub datum: String,
    pub kezdet_idopont: LDateTime,
    pub veg_idopont: LDateTime,
    pub nev: String,
    pub oraszam: Option<u8>,
    pub ora_eves_sorszama: Option<u32>,
    pub osztaly_csoport: Option<Uid>,
    pub tanar_neve: Option<String>,
    pub tantargy: Option<Tantargy>,
    pub tema: Option<String>,
    pub terem_neve: Option<String>,
    pub tipus: Rektip,
    pub tanulo_jelenlet: Option<Rektip>,
    pub allapot: Option<Rektip>,
    pub helyettes_tanar_neve: Option<String>,
    pub hazi_feladat_uid: Option<String>,
    pub feladat_group_uid: Option<String>,
    pub nyelvi_feladat_group_uid: Option<String>,
    pub bejelentett_szamonkeres_uid: Option<String>,
    pub is_tanulo_hazi_feladat_enabled: bool,
    pub is_hazi_feladat_megoldva: bool,
    pub csatolmanyok: Vec<String>,
    pub is_digitalis_ora: bool,
    pub digitalis_eszkoz_tipus: Option<String>,
    pub digitalis_platform_tipus: Option<String>,
    pub digitalis_tamogato_eszkoz_tipus_list: Option<Vec<String>>,
    pub letrehozas: String,
    pub utolso_modositas: chrono::NaiveDateTime,
}
impl Lesson {
    /// The two goddamn [`Lesson`]s should happen in the same time.
    pub fn same_time(&self, other: &Self) -> bool {
        self.kezdet_idopont == other.kezdet_idopont && self.veg_idopont == other.veg_idopont
    }
    /// Returns whether this [`Lesson`] has been/will be cancelled.
    pub fn cancelled(&self) -> bool {
        self.allapot.as_ref().is_some_and(|a| a.nev == "Elmaradt")
    }
    /// Returns whether the student has appeared on this [`Lesson`].
    pub fn absent(&self) -> bool {
        self.tanulo_jelenlet
            .as_ref()
            .is_some_and(|absence| absence.nev == "Hianyzas")
    }
    /// Returns the subject id of this [`Lesson`].
    pub fn subject_id(&self) -> Option<&String> {
        self.tantargy.as_ref().map(|tt| &tt.kategoria.nev)
    }
    /// Returns whether this [`Lesson`] is just false positive, meaning it's just a title for a day.
    pub fn kamu_smafu(&self) -> bool {
        self.kezdet_idopont
            .signed_duration_since(self.veg_idopont)
            .is_zero()
    }
    /// Returns whether this [`Lesson`] is currently happening.
    pub fn happening(&self) -> bool {
        if self.cancelled() {
            return false;
        }
        self.kezdet_idopont <= Local::now() && self.veg_idopont >= Local::now()
    }

    /// Returns whether this [`Lesson`] is a forecoming one: to be done.
    pub fn forecoming(&self) -> bool {
        self.kezdet_idopont > Local::now()
    }
}

impl Endpoint for Lesson {
    type Args = (chrono::NaiveDate, chrono::NaiveDate);

    fn path(_args: &Self::Args) -> String {
        "/ellenorzo/V3/Sajat/OrarendElemek".into()
    }

    fn query(input: &Self::Args) -> Res<impl Serialize> {
        let mut q = vec![];
        q.push(("datumTol", input.0.to_string()));
        q.push(("datumIg", input.1.to_string()));
        Ok(q)
    }
}