//! Checked 320-bit subtraction returning [`None`] on underflow.
use super::U320;

impl U320 {
    /// Computes `self - other`, returning `None` if the result would
    /// underflow (i.e., `other > self`).
    ///
    /// Delegates to [`U320::overflowing_sub`] and converts the underflow
    /// flag into an [`Option`].
    ///
    /// # Examples
    ///
    /// ```
    /// use cnfy_uint::u320::U320;
    ///
    /// let a = U320::from_be_limbs([0, 0, 0, 0, 10]);
    /// let b = U320::from_be_limbs([0, 0, 0, 0, 3]);
    /// assert_eq!(a.checked_sub(&b), Some(U320::from_be_limbs([0, 0, 0, 0, 7])));
    /// assert_eq!(U320::ZERO.checked_sub(&U320::ONE), None);
    /// ```
    #[inline]
    pub const fn checked_sub(&self, other: &U320) -> Option<U320> {
        let (result, underflow) = self.overflowing_sub(other);
        if underflow {
            None
        } else {
            Some(result)
        }
    }
}

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

    /// Non-underflowing subtraction returns Some.
    #[test]
    fn no_underflow() {
        let a = U320::from_be_limbs([0, 0, 0, 0, 10]);
        let b = U320::from_be_limbs([0, 0, 0, 0, 3]);
        assert_eq!(a.checked_sub(&b), Some(U320::from_be_limbs([0, 0, 0, 0, 7])));
    }

    /// Underflowing subtraction returns None.
    #[test]
    fn underflow_returns_none() {
        assert_eq!(U320::ZERO.checked_sub(&U320::ONE), None);
    }

    /// Subtracting zero returns Some(self).
    #[test]
    fn sub_zero() {
        let a = U320::from_be_limbs([0x1234, 0x5678, 0x9ABC, 0xDEF0, 0x1111]);
        assert_eq!(a.checked_sub(&U320::ZERO), Some(a));
    }

    /// Subtracting self returns Some(ZERO).
    #[test]
    fn self_cancellation() {
        let a = U320::from_be_limbs([0x1234, 0x5678, 0x9ABC, 0xDEF0, 0x1111]);
        assert_eq!(a.checked_sub(&a), Some(U320::ZERO));
    }

    /// Larger minus smaller across limbs.
    #[test]
    fn cross_limb() {
        let a = U320::from_be_limbs([1, 0, 0, 0, 0]);
        let b = U320::ONE;
        assert_eq!(
            a.checked_sub(&b),
            Some(U320::from_be_limbs([0, u64::MAX, u64::MAX, u64::MAX, u64::MAX])),
        );
    }
}
