// client/src/output/layout.rs

use super::display::MonitorInfo;
use tracing::debug;

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Rect {
    pub x: i32,
    pub y: i32,
    pub w: i32,
    pub h: i32,
}

/// Compute rectangles for the current monitor topology.
///
/// Inputs: the ordered monitor list plus the active video streams and their
/// nominal sizes.
/// Outputs: one rectangle per stream, laid out across the available monitors
/// or split across a single display when only one monitor is present.
/// Why: the display policy is pure so the monitor selection logic can be
/// exercised by unit tests without GTK or Wayland state.
pub fn assign_rectangles(
    monitors: &[MonitorInfo],
    streams: &[(&str, i32, i32)], // (name, w, h)
) -> Vec<Rect> {
    let mut rects = vec![
        Rect {
            x: 0,
            y: 0,
            w: 0,
            h: 0
        };
        streams.len()
    ];

    match monitors.len() {
        0 => return rects, // impossible, but keep compiler happy
        1 => {
            // One monitor: side-by-side layout, full height
            let m = &monitors[0].geometry;
            let count = streams.len().max(1) as i32;
            let base_w = m.width() / count;
            let mut x = m.x();
            for (idx, _stream) in streams.iter().enumerate() {
                let w = if idx == streams.len() - 1 {
                    m.width() - base_w * (count - 1)
                } else {
                    base_w
                };
                rects[idx] = Rect {
                    x,
                    y: m.y(),
                    w,
                    h: m.height(),
                };
                x += w;
            }
        }
        _ => {
            // ≥2 monitors: map 1-to-1 until we run out, full screen per monitor
            for (idx, _stream) in streams.iter().enumerate() {
                if idx >= monitors.len() {
                    break;
                }

                let m = &monitors[idx];
                let geom = m.geometry;
                rects[idx] = Rect {
                    x: geom.x(),
                    y: geom.y(),
                    w: geom.width(),
                    h: geom.height(),
                };
            }
        }
    }
    debug!("📐 final rectangles = {:?}", rects);
    rects
}

#[cfg(test)]
mod tests {
    use super::{Rect, assign_rectangles};
    use crate::output::display::MonitorInfo;
    use gtk::gdk;

    fn monitor(x: i32, y: i32, w: i32, h: i32, is_internal: bool) -> MonitorInfo {
        MonitorInfo {
            geometry: gdk::Rectangle::new(x, y, w, h),
            scale_factor: 1,
            is_internal,
        }
    }

    #[test]
    fn single_monitor_splits_streams_evenly() {
        let rects = assign_rectangles(
            &[monitor(10, 20, 1920, 1080, false)],
            &[("left", 0, 0), ("right", 0, 0)],
        );

        assert_eq!(
            rects,
            vec![
                Rect {
                    x: 10,
                    y: 20,
                    w: 960,
                    h: 1080,
                },
                Rect {
                    x: 970,
                    y: 20,
                    w: 960,
                    h: 1080,
                },
            ]
        );
    }

    #[test]
    fn multiple_monitors_map_streams_one_to_one() {
        let rects = assign_rectangles(
            &[
                monitor(0, 0, 1280, 720, false),
                monitor(1280, 0, 1920, 1080, true),
            ],
            &[("left", 0, 0), ("right", 0, 0), ("extra", 0, 0)],
        );

        assert_eq!(
            rects,
            vec![
                Rect {
                    x: 0,
                    y: 0,
                    w: 1280,
                    h: 720,
                },
                Rect {
                    x: 1280,
                    y: 0,
                    w: 1920,
                    h: 1080,
                },
                Rect {
                    x: 0,
                    y: 0,
                    w: 0,
                    h: 0,
                },
            ]
        );
    }
}
