/// 8. 有机流体彩色玻璃融合 (Metaballs Colored Glass Gooey Effect)
pub fn apply(data: &mut [u8], w: usize, h: usize, rng: &mut fastrand::Rng) {
    let num_balls = rng.usize(2..5);
    #[derive(Copy, Clone)]
    struct Metaball {
        cx: i32,
        cy: i32,
        r_sq_scaled: i32,
    }
    let mut balls = [Metaball {
        cx: 0,
        cy: 0,
        r_sq_scaled: 0,
    }; 5];

    let mut min_x = w as i32;
    let mut min_y = h as i32;
    let mut max_x = 0;
    let mut max_y = 0;

    for b in balls.iter_mut().take(num_balls) {
        let cx = rng.i32(30..(w as i32).saturating_sub(30).max(31));
        let cy = rng.i32(30..(h as i32).saturating_sub(30).max(31));
        let r = rng.i32(20..45);
        *b = Metaball {
            cx,
            cy,
            r_sq_scaled: r * r * 256,
        };

        let influence = r * 2;
        min_x = min_x.min(cx - influence);
        min_y = min_y.min(cy - influence);
        max_x = max_x.max(cx + influence);
        max_y = max_y.max(cy + influence);
    }

    let dr = rng.i8(-90..90);
    let dg = rng.i8(-90..90);
    let db = rng.i8(-90..90);

    let x_start = min_x.max(0) as usize;
    let x_end = max_x.max(0).min(w as i32) as usize;
    let y_start = min_y.max(0) as usize;
    let y_end = max_y.max(0).min(h as i32) as usize;

    if y_start < y_end && x_start < x_end {
        let start_bytes = y_start * w * 4;
        let end_bytes = y_end * w * 4;
        if end_bytes <= data.len() {
            for (y, row) in data[start_bytes..end_bytes]
                .chunks_exact_mut(w * 4)
                .enumerate()
            {
                let y_i32 = (y_start + y) as i32;
                unsafe {
                    let ptr = row.as_mut_ptr();
                    for x in x_start..x_end {
                        let x_i32 = x as i32;
                        let mut sum = 0;

                        for i in 0..num_balls {
                            let b = balls.get_unchecked(i);
                            let dx = x_i32 - b.cx;
                            let dy = y_i32 - b.cy;
                            let dist_sq = dx * dx + dy * dy + 1;
                            sum += b.r_sq_scaled / dist_sq;
                        }

                        if sum > 256 {
                            let idx = x * 4;
                            *ptr.add(idx) = (*ptr.add(idx)).saturating_add_signed(dr);
                            *ptr.add(idx + 1) = (*ptr.add(idx + 1)).saturating_add_signed(dg);
                            *ptr.add(idx + 2) = (*ptr.add(idx + 2)).saturating_add_signed(db);
                        }
                    }
                }
            }
        }
    }
}
