use crate::decode::DecodedImage;

/// Count pixels that differ between two images (a pixel differs if ANY of its
/// RGBA channels differ). Returns `None` if dimensions differ.
///
/// Early-exit: as soon as the running count exceeds `cap`, returns a value that
/// is `> cap` (not necessarily the true total). Callers use this only to reject
/// candidates whose diff exceeds `cap`; when the result is `<= cap` it is exact.
pub fn diff_count(a: &DecodedImage, b: &DecodedImage, cap: u64) -> Option<u64> {
    if a.width != b.width || a.height != b.height {
        return None;
    }
    let mut count: u64 = 0;
    for (pa, pb) in a.rgba.chunks_exact(4).zip(b.rgba.chunks_exact(4)) {
        if pa != pb {
            count += 1;
            if count > cap {
                return Some(count);
            }
        }
    }
    Some(count)
}

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

    fn img(w: u32, h: u32, fill: [u8; 4]) -> DecodedImage {
        DecodedImage { width: w, height: h, rgba: fill.repeat((w * h) as usize) }
    }

    #[test]
    fn identical_images_have_zero_diff() {
        let a = img(3, 2, [1, 2, 3, 255]);
        let b = img(3, 2, [1, 2, 3, 255]);
        assert_eq!(diff_count(&a, &b, u64::MAX), Some(0));
    }

    #[test]
    fn single_pixel_difference_counts_one() {
        let a = img(2, 1, [0, 0, 0, 255]);
        let mut b = img(2, 1, [0, 0, 0, 255]);
        b.rgba[4] = 9; // change second pixel's red channel
        assert_eq!(diff_count(&a, &b, u64::MAX), Some(1));
    }

    #[test]
    fn dimension_mismatch_returns_none() {
        let a = img(2, 2, [0, 0, 0, 255]);
        let b = img(3, 2, [0, 0, 0, 255]);
        assert_eq!(diff_count(&a, &b, u64::MAX), None);
    }

    #[test]
    fn early_exit_stops_past_cap() {
        // All 4 pixels differ; with cap=2 it must stop early, returning > 2.
        let a = img(2, 2, [0, 0, 0, 255]);
        let b = img(2, 2, [9, 9, 9, 255]);
        let got = diff_count(&a, &b, 2).unwrap();
        assert!(got > 2);
    }
}
