#[allow(warnings)]
#[cfg(feature = "date")]
pub mod date {
    /// Returns the current date and time as a formatted string in "YYYY-MM-DD-HH-MM-SS" format.
    ///
    /// # Examples
    ///
    /// ```ignore
    /// use doe::date;
    /// let current_time = date::now();
    /// println!("Current time: {}", current_time);
    /// ```
    pub fn now() -> String {
        use chrono::prelude::*;
        // Get the current date and time
        let current_time = Local::now();

        // Extract the year, month, day, hour, minute, and second from the current date and time
        let year = current_time.format("%Y").to_string();
        let month = current_time.format("%m").to_string();
        let day = current_time.format("%d").to_string();
        let hours = current_time.format("%H").to_string();
        let minutes = current_time.format("%M").to_string();
        let seconds = current_time.format("%S").to_string();

        // Join the extracted values together and return the resulting string
        format!(
            "{}-{}-{}-{}-{}-{}",
            year, month, day, hours, minutes, seconds
        )
    }

    use chrono::prelude::*;

    fn current_time() -> DateTime<Local> {
        Local::now()
    }

    pub fn year() -> String {
        current_time().format("%Y").to_string()
    }

    pub fn month() -> String {
        current_time().format("%m").to_string()
    }

    pub fn day() -> String {
        current_time().format("%d").to_string()
    }

    pub fn hours() -> String {
        current_time().format("%H").to_string()
    }

    pub fn minutes() -> String {
        current_time().format("%M").to_string()
    }

    pub fn seconds() -> String {
        current_time().format("%S").to_string()
    }

    /// Returns a vector of strings representing the dates of the last seven days in "YYYY-MM-DD" format.
    ///
    /// # Examples
    ///
    /// ```ignore
    /// use doe::date;
    /// let recent_dates = date::get_recent_seven_days();
    /// for date in recent_dates {
    ///     println!("{}", date);
    /// }
    /// ```
    pub fn get_recent_seven_days() -> Vec<String> {
        use chrono::prelude::*;
        use chrono::Duration;
        // Get the current date
        let today = Local::today();

        // Initialize an empty array to hold the seven dates
        let mut seven_days_array: Vec<String> = Vec::new();

        // Iterate backwards through the previous seven days and add each date to the array
        for i in (0..7).rev() {
            let current_date = today - Duration::days(i);

            // Extract the year, month, and day from the current date
            let (year, month, day) = (
                current_date.year(),
                current_date.month(),
                current_date.day(),
            );

            // Format the date as a string in "YYYY-MM-DD" format and add it to the array
            let formatted_date = format!("{:04}-{:02}-{:02}", year, month, day);
            seven_days_array.push(formatted_date);
        }

        // Return the array of seven dates
        seven_days_array
    }

    /// Converts a normal date string in "YYYY-MM-DD" format to an Excel date number.
    ///
    /// # Arguments
    ///
    /// * `normal_date` - A string slice representing the date in "YYYY-MM-DD" format.
    ///
    /// # Returns
    ///
    /// Returns `Ok(i64)` representing the Excel date number if the conversion is successful.
    /// Returns `Err(String)` if the input date string is invalid or the conversion fails.
    ///
    /// # Examples
    ///
    /// ```ignore
    /// use doe::date;
    /// let excel_date = date::normal_date_to_excel_date("2023-10-01").unwrap();
    /// println!("Excel date: {}", excel_date);
    /// ```
    pub fn normal_date_to_excel_date(normal_date: &str) -> Result<i64, String> {
        use crate::Str;
        use chrono::prelude::*;
        use regex::Regex;
        let date_regex = Regex::new(r"\b\d{4}-\d{2}-\d{2}\b").unwrap();
        if date_regex.is_match(normal_date) {
            let nomal_date_vec = normal_date
                .split_to_vec("-")
                .iter()
                .map(|s| s.parse::<u32>().unwrap())
                .collect::<Vec<_>>();
            if let Some(date) = NaiveDate::from_ymd_opt(
                nomal_date_vec[0] as i32,
                nomal_date_vec[1],
                nomal_date_vec[2],
            ) {
                if let Some(start_date) = chrono::NaiveDate::from_ymd_opt(1899, 12, 30) {
                    let days = (date - start_date).num_days();
                    return Ok(days);
                }
                return Err("chrono::NaiveDate::from_ymd_opt(1899, 12, 30)".to_string());
            }
            return  Err("NaiveDate::from_ymd_opt(nomal_date_vec[0] as i32, nomal_date_vec[1], nomal_date_vec[2])".to_string());
        }
        return Err("date_regex.is_match(normal_date)".to_string());
    }

    /// Converts an Excel date number to a normal date string in "YYYY-MM-DD" format.
    ///
    /// # Arguments
    ///
    /// * `excel_date` - An `i64` representing the Excel date number.
    ///
    /// # Returns
    ///
    /// Returns `Some(String)` representing the date in "YYYY-MM-DD" format if the conversion is successful.
    /// Returns `None` if the conversion fails.
    ///
    /// # Examples
    ///
    /// ```ignore
    /// use doe::date;
    /// let normal_date = date::excel_date_to_normal_date(45292).unwrap();
    /// println!("Normal date: {}", normal_date);
    /// ```
    pub fn excel_date_to_normal_date(excel_date: i64) -> Option<String> {
        use chrono::NaiveDate;
        let days_since_excel_epoch = excel_date; // Excel's epoch starts on December 30, 1899 (not January 1, 1900)
                                                 // Convert days since Excel's epoch to NaiveDate
        let date = NaiveDate::from_ymd_opt(1899, 12, 30)?
            .checked_add_signed(chrono::Duration::days(days_since_excel_epoch as i64))?;
        // Format the date as a string in "YYYY-MM-DD" format
        Some(date.format("%Y-%m-%d").to_string())
    }
    pub use chrono::*;
    use chrono::{NaiveDate, NaiveDateTime, NaiveTime};
    use regex::Regex;
    use std::sync::LazyLock;

static DATETIME_RE: LazyLock<Regex> = LazyLock::new(|| {
    Regex::new(
        r#"^(\d{4})[:/\-](\d{1,2})[:/\-](\d{1,2})(?:\s+(\d{1,2})[:/\-](\d{1,2})(?:[:/\-](\d{1,2}))?)?(?:\s*[+-]\d{2}:\d{2})?\s*$"#
    ).unwrap()
});

    /// Parse a datetime string with flexible separators (`:`, `/`, `-`) and
    /// optional time/timezone components.
    ///
    /// When time is absent, defaults to 00:00:00.
    /// Timezone offset is accepted but discarded (returns `NaiveDateTime`).
    pub fn parse_datetime(s: &str) -> Option<NaiveDateTime> {
        let caps = DATETIME_RE.captures(s)?;

        let year: i32 = caps[1].parse().ok()?;
        let month: u32 = caps[2].parse().ok()?;
        let day: u32 = caps[3].parse().ok()?;

        let hour: u32 = caps
            .get(4)
            .and_then(|m| m.as_str().parse().ok())
            .unwrap_or(0);
        let minute: u32 = caps
            .get(5)
            .and_then(|m| m.as_str().parse().ok())
            .unwrap_or(0);
        let second: u32 = caps
            .get(6)
            .and_then(|m| m.as_str().parse().ok())
            .unwrap_or(0);

        Some(NaiveDateTime::new(
            NaiveDate::from_ymd_opt(year, month, day)?,
            NaiveTime::from_hms_opt(hour, minute, second)?,
        ))
    }
}

#[cfg(feature = "date")]
pub use date::*;
