// SPDX-FileCopyrightText: Politik im Blick developers
// SPDX-FileCopyrightText: Wolfgang Silbermayr <wolfgang@silbermayr.at>
//
// SPDX-License-Identifier: AGPL-3.0-or-later OR EUPL-1.2

#[derive(
    Debug,
    Clone,
    PartialEq,
    Eq,
    PartialOrd,
    Ord,
    Hash,
    serde::Serialize,
    serde::Deserialize,
    strum::AsRefStr,
    strum::Display,
    strum::EnumString,
)]
#[cfg_attr(feature = "sea-orm", derive(sea_orm::DeriveValueType))]
#[cfg_attr(feature = "sea-orm", sea_orm(value_type = "String"))]
pub enum OrganizationType {
    #[serde(rename = "Gremium")]
    #[strum(serialize = "Gremium")]
    Council,

    #[serde(rename = "Partei")]
    #[strum(serialize = "Partei")]
    Party,

    #[serde(rename = "Fraktion")]
    #[strum(serialize = "Fraktion")]
    ParliamentaryGroup,

    #[serde(rename = "Verwaltungsbereich")]
    #[strum(serialize = "Verwaltungsbereich")]
    AdministrativeAmbit,

    #[serde(rename = "externes Gremium")]
    #[strum(serialize = "externes Gremium")]
    ExternalCouncil,

    #[serde(rename = "Institution")]
    #[strum(serialize = "Institution")]
    Institution,

    #[serde(rename = "Sonstiges")]
    #[strum(serialize = "Sonstiges")]
    Other,
}

#[cfg(test)]
mod tests {
    use super::OrganizationType;

    #[test]
    fn to_string() {
        assert_eq!(OrganizationType::Council.to_string(), "Gremium");
        assert_eq!(OrganizationType::Party.to_string(), "Partei");
        assert_eq!(OrganizationType::ParliamentaryGroup.to_string(), "Fraktion");
        assert_eq!(
            OrganizationType::AdministrativeAmbit.to_string(),
            "Verwaltungsbereich"
        );
        assert_eq!(
            OrganizationType::ExternalCouncil.to_string(),
            "externes Gremium"
        );
        assert_eq!(OrganizationType::Institution.to_string(), "Institution");
        assert_eq!(OrganizationType::Other.to_string(), "Sonstiges");
    }

    #[test]
    fn parse_good() {
        let parsed: OrganizationType = "Gremium"
            .parse()
            .expect("value must be parsable as organization type");
        assert_eq!(parsed, OrganizationType::Council);

        let parsed: OrganizationType = "Partei"
            .parse()
            .expect("value must be parsable as organization type");
        assert_eq!(parsed, OrganizationType::Party);

        let parsed: OrganizationType = "Fraktion"
            .parse()
            .expect("value must be parsable as organization type");
        assert_eq!(parsed, OrganizationType::ParliamentaryGroup);

        let parsed: OrganizationType = "Institution"
            .parse()
            .expect("value must be parsable as organization type");
        assert_eq!(parsed, OrganizationType::Institution);

        let parsed: OrganizationType = "externes Gremium"
            .parse()
            .expect("value must be parsable as organization type");
        assert_eq!(parsed, OrganizationType::ExternalCouncil);

        let parsed: OrganizationType = "Sonstiges"
            .parse()
            .expect("value must be parsable as organization type");
        assert_eq!(parsed, OrganizationType::Other);
    }

    #[test]
    fn deserialize_bad() {
        assert!("gremium".parse::<OrganizationType>().is_err());
        assert!("GREMIUM".parse::<OrganizationType>().is_err());
    }
}

#[cfg(test)]
mod serde_tests {
    use pretty_assertions::assert_eq;
    use serde_json::json;

    use super::OrganizationType;

    #[test]
    fn serialize() {
        assert_eq!(json!(OrganizationType::Council), json!("Gremium"));
        assert_eq!(json!(OrganizationType::Party), json!("Partei"));
        assert_eq!(
            json!(OrganizationType::ParliamentaryGroup),
            json!("Fraktion")
        );
        assert_eq!(
            json!(OrganizationType::AdministrativeAmbit),
            json!("Verwaltungsbereich")
        );
        assert_eq!(
            json!(OrganizationType::ExternalCouncil),
            json!("externes Gremium")
        );
        assert_eq!(json!(OrganizationType::Institution), json!("Institution"));
        assert_eq!(json!(OrganizationType::Other), json!("Sonstiges"));
    }

    #[test]
    fn deserialize_good() {
        let deserialized: OrganizationType = serde_json::from_value(json!("Gremium"))
            .expect("value must be deserializable as organization type");
        assert_eq!(deserialized, OrganizationType::Council);

        let deserialized: OrganizationType = serde_json::from_value(json!("Partei"))
            .expect("value must be deserializable as organization type");
        assert_eq!(deserialized, OrganizationType::Party);

        let deserialized: OrganizationType = serde_json::from_value(json!("Fraktion"))
            .expect("value must be deserializable as organization type");
        assert_eq!(deserialized, OrganizationType::ParliamentaryGroup);

        let deserialized: OrganizationType = serde_json::from_value(json!("Institution"))
            .expect("value must be deserializable as organization type");
        assert_eq!(deserialized, OrganizationType::Institution);

        let deserialized: OrganizationType = serde_json::from_value(json!("externes Gremium"))
            .expect("value must be deserializable as organization type");
        assert_eq!(deserialized, OrganizationType::ExternalCouncil);

        let deserialized: OrganizationType = serde_json::from_value(json!("Sonstiges"))
            .expect("value must be deserializable as organization type");
        assert_eq!(deserialized, OrganizationType::Other);
    }

    #[test]
    fn deserialize_bad() {
        assert!(serde_json::from_value::<OrganizationType>(json!("gremium")).is_err());
        assert!(serde_json::from_value::<OrganizationType>(json!("GREMIUM")).is_err());
        assert!(serde_json::from_value::<OrganizationType>(json!({})).is_err());
        assert!(serde_json::from_value::<OrganizationType>(json!([])).is_err());
        assert!(serde_json::from_value::<OrganizationType>(json!(null)).is_err());
    }
}
