#[cfg(feature = "schema-gen")]
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

use crate::types::{
    Color, CommonDefinition, DateDef, DateDefExceptions, EntityRef, MassesDefinitions, Precedence,
    TitlesDef,
};

/// Locale identifier for internationalization
pub type LocaleId = String;

/// Macro to generate SingleOrMultiple types for handling both single values and arrays
macro_rules! single_or_multiple {
    ($name:ident, $type:ty) => {
        #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
        #[cfg_attr(feature = "schema-gen", derive(JsonSchema))]
        #[serde(untagged)]
        pub enum $name {
            Single($type),
            Multiple(Vec<$type>),
        }
    };
}

single_or_multiple!(CommonsDef, CommonDefinition);
single_or_multiple!(ColorsDef, Color);

/// Unique identifier for a day definition
pub type DayId = String;

/// Definition of a liturgical day with all its properties and configurations.
/// It represents a complete liturgical day definition that can be used
/// to generate calendar entries with proper precedence, colors, and entity associations.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "schema-gen", derive(JsonSchema))]
pub struct DayDefinition {
    /// The date definition for this liturgical day
    pub date_def: Option<DateDef>,
    /// The date definition exceptions (overrides for specific circumstances)
    pub date_exceptions: Option<DateDefExceptions>,
    /// The precedence type of the liturgical day
    pub precedence: Option<Precedence>,
    /// The **Common** refers to a set of prayers, readings, and chants used for celebrating saints or
    /// feasts that belong to a specific category, such as martyrs, virgins, pastors, or the Blessed
    /// Virgin Mary.
    pub commons_def: Option<CommonsDef>,
    /// Holy days of obligation are days on which the faithful are expected to attend Mass
    /// and engage in rest from work and recreation
    pub is_holy_day_of_obligation: Option<bool>,
    /// Allow similar items that have the same rank and the same or lower precedence
    /// to coexist with this liturgical day without being overwritten
    pub allow_similar_rank_items: Option<bool>,
    /// Specify if this liturgical day is optional within a specific liturgical calendar
    ///
    /// UNLY #14:
    /// Memorials are either obligatory or optional; their observance is integrated into
    /// the celebration of the occurring weekday in accordance with the norms set forth in the
    /// General Instruction of the Roman Missal and of the Liturgy of the Hours
    ///
    /// Note: also used for the dedication of consecrated churches, which is an optional solemnity
    /// that should not overwrite the default weekday.
    pub is_optional: Option<bool>,
    /// The custom locale ID for this date definition in this calendar
    pub custom_locale_id: Option<LocaleId>,
    /// The entities (Saints, Blessed, or Places) linked from the Entity catalog
    pub entities: Option<Vec<EntityRef>>,
    /// The combined titles of all entities linked to this date definition
    pub titles: Option<TitlesDef>,
    /// If this liturgical day must be removed from this calendar and from all parent calendars
    /// in the final calendar generated by romcal
    pub drop: Option<bool>,
    /// The liturgical color(s) of the liturgical day.
    ///
    /// **Deprecated:** Rely on the `titles` field of entities instead to determine the liturgical color(s).
    pub colors: Option<ColorsDef>,
    /// The masses definitions for this liturgical day
    pub masses: Option<MassesDefinitions>,
}
