/// Adds two number given.
///
/// # Arguments
/// * `left` - left side number
/// * `right` - right side number
///
/// # Examples
///
/// ```
/// let left = 5;
/// let right = 4;
/// assert_eq!(9, testing::add(left, right));
/// ```
pub fn add(left: u64, right: u64) -> u64 {
    left + right
}

pub fn add_fail(left: u64, right: u64) -> u64 {
    left + right + 1
}

pub fn add_and_print(left: u64, right: u64) -> u64 {
    let result = left + right;
    println!("{left} + {right} = {result}");
    result
}

pub fn div(left: u64, right: u64) -> (u64, u64) {
    if right == 0 {
        panic!("0で割ることはできません！");
    }
    (left / right, left % right)
}

pub fn div_fail(left: u64, right: u64) -> (u64, u64) {
    if right == 100 {
        panic!("0で割ることはできません！");
    }
    (left / right, left % right)
}

/// Subtracts two number given.
///
/// # Arguments
/// * `left` - left side number
/// * `right` - right side number
///
/// # Examples
///
/// ```
/// let left = 5;
/// let right = 4;
/// assert_eq!(1, testing::sub(left, right));
/// ```
pub fn sub(left: i64, right: i64) -> i64 {
    left - right
}

pub fn square_root(value: f64) -> f64 {
    if value < 0.0 {
        panic!("負の数の平方根は計算できません！");
    }
    value.sqrt()
}

pub mod helper {
    pub fn multiply(left: u64, right: u64) -> u64 {
        left * right
    }
}

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

    #[test]
    fn it_works() {
        let result = add(2, 2);
        assert_eq!(result, 4);
    }

    #[test]
    fn it_not_works() {
       let result = add_fail(2, 2);
        assert_eq!(result, 4);
    }

    #[test]
    fn add_and_print_success() {
        let result = add_and_print(2, 2);
        assert_eq!(result, 4);
    }

    #[test]
    fn add_and_print_fail() {
        let result = add_and_print(3, 4);
        assert_eq!(result, 4);
    }

    #[test]
    #[ignore]
    fn never_run() {
        assert!(true);
    }

    #[test]
    fn assertion_sample() {
        let left = 2;
        let right = 3;
        let result = add(left, right);
        assert!(result == 4, "Got {result}, left: {left}, right: {right}");
    }

    #[test]
    #[should_panic]
    fn divide_success() {
        div(1, 0);
    }

    #[test]
    //#[should_panic]
    #[should_panic(expected = "0で割ることはできません！")]
    fn divide_fail() {
        div_fail(1, 0);
    }

    #[test]
    fn it_works_result() -> Result<(), String> {
        let result = add(2, 2);
        if result == 4 {
            Ok(())
        } else {
            Err(String::from("2 + 2 の結果が 4 ではありません。"))
        }
    }

    #[test]
    fn sub_works() {
        let result = sub(2, 2);
        assert_eq!(result, 0);
    }

    #[test]
    fn sub_works_custom() {
        let result = sub(2, 2);
        assert!(result == 4, "2 - 2 の結果は {} ではありませんでした。", result);
    }

    #[test]
    #[should_panic]
    fn square_root_fail() {
        square_root(-1.0);
    }
}
