//! Master-detail layout for list + detail view
//!
//! Implements R-RESPONSIVE-LAYOUT: Percentage-based constraints that adapt
//! to terminal size changes automatically.

use ratatui::prelude::*;

/// Master-detail layout areas
///
/// Typical layout:
/// ```text
/// ┌──────────────────────────────────────┐
/// │ Master List    │ Detail View         │
/// │                │                     │
/// │ Item 1         │ Details for Item 1  │
/// │ Item 2         │ ...                 │
/// │ Item 3         │                     │
/// │                │                     │
/// └──────────────────────────────────────┘
/// ```
#[derive(Clone, Copy, Debug)]
pub struct MasterDetailAreas {
    /// Master list area (left)
    pub master: Rect,
    /// Detail view area (right)
    pub detail: Rect,
}

impl MasterDetailAreas {
    /// Calculate master-detail areas based on the given space
    ///
    /// Uses percentage-based constraints:
    /// - Master: 30% of width
    /// - Detail: 70% of width
    #[must_use]
    pub fn new(area: Rect) -> Self {
        let master_width = (area.width * 3 / 10).max(10);

        let master = Rect {
            x: area.x,
            y: area.y,
            width: master_width,
            height: area.height,
        };

        let detail = Rect {
            x: area.x + master_width,
            y: area.y,
            width: area.width.saturating_sub(master_width),
            height: area.height,
        };

        Self { master, detail }
    }

    /// Create custom areas with specified master width percentage
    #[must_use]
    pub fn with_master_width(area: Rect, master_width_percent: u16) -> Self {
        let master_width = (area.width * master_width_percent / 100).max(5);

        let master = Rect {
            x: area.x,
            y: area.y,
            width: master_width,
            height: area.height,
        };

        let detail = Rect {
            x: area.x + master_width,
            y: area.y,
            width: area.width.saturating_sub(master_width),
            height: area.height,
        };

        Self { master, detail }
    }
}

/// Master-detail layout manager
///
/// Provides a two-pane layout for displaying a list and its details.
///
/// # Example
///
/// ```ignore
/// let layout = MasterDetailLayout::new();
/// let areas = layout.areas(frame.size());
///
/// // Render master list in left pane
/// frame.render_widget(list_widget, areas.master);
///
/// // Render details in right pane
/// frame.render_widget(detail_widget, areas.detail);
/// ```
#[derive(Clone, Debug)]
pub struct MasterDetailLayout {
    /// Master pane width percentage (default 30)
    master_width_percent: u16,
}

impl MasterDetailLayout {
    /// Create a new master-detail layout
    #[must_use]
    pub const fn new() -> Self {
        Self {
            master_width_percent: 30,
        }
    }

    /// Set the master pane width as percentage (0-100)
    #[must_use]
    pub fn with_master_width(mut self, percent: u16) -> Self {
        self.master_width_percent = percent.clamp(10, 90);
        self
    }

    /// Get master width percentage
    #[must_use]
    pub const fn master_width_percent(&self) -> u16 {
        self.master_width_percent
    }

    /// Calculate areas for the given space
    #[must_use]
    pub fn areas(&self, area: Rect) -> MasterDetailAreas {
        MasterDetailAreas::with_master_width(area, self.master_width_percent)
    }
}

impl Default for MasterDetailLayout {
    fn default() -> Self {
        Self::new()
    }
}

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

    #[test]
    fn test_master_detail_areas_new() {
        let area = Rect {
            x: 0,
            y: 0,
            width: 100,
            height: 30,
        };

        let areas = MasterDetailAreas::new(area);

        // Master should be ~30% of width
        assert!(areas.master.width >= 10);
        assert!(areas.master.width <= 40);

        // Detail should be remaining width
        assert!(areas.detail.width > 0);
        assert_eq!(areas.master.width + areas.detail.width, area.width);
    }

    #[test]
    fn test_master_detail_areas_small_terminal() {
        let area = Rect {
            x: 0,
            y: 0,
            width: 20,
            height: 10,
        };

        let areas = MasterDetailAreas::new(area);

        // Both panes should exist even on small terminal
        assert!(areas.master.width > 0);
        assert!(areas.detail.width > 0);
    }

    #[test]
    fn test_master_detail_areas_custom_width() {
        let area = Rect {
            x: 0,
            y: 0,
            width: 100,
            height: 30,
        };

        let areas = MasterDetailAreas::with_master_width(area, 50);

        // Master should be ~50% of width
        assert!(areas.master.width >= 45);
        assert!(areas.master.width <= 55);
    }

    #[test]
    fn test_master_detail_layout_new() {
        let layout = MasterDetailLayout::new();
        assert_eq!(layout.master_width_percent(), 30);
    }

    #[test]
    fn test_master_detail_layout_custom_width() {
        let layout = MasterDetailLayout::new().with_master_width(40);
        assert_eq!(layout.master_width_percent(), 40);
    }

    #[test]
    fn test_master_detail_layout_width_clamp_min() {
        let layout = MasterDetailLayout::new().with_master_width(5); // Below min
        assert_eq!(layout.master_width_percent(), 10); // Clamped to min
    }

    #[test]
    fn test_master_detail_layout_width_clamp_max() {
        let layout = MasterDetailLayout::new().with_master_width(95); // Above max
        assert_eq!(layout.master_width_percent(), 90); // Clamped to max
    }

    #[test]
    fn test_master_detail_areas_master_position() {
        let area = Rect {
            x: 0,
            y: 0,
            width: 100,
            height: 30,
        };

        let areas = MasterDetailAreas::new(area);

        assert_eq!(areas.master.x, 0);
        assert_eq!(areas.master.y, 0);
    }

    #[test]
    fn test_master_detail_areas_detail_position() {
        let area = Rect {
            x: 0,
            y: 0,
            width: 100,
            height: 30,
        };

        let areas = MasterDetailAreas::new(area);

        assert_eq!(areas.detail.x, areas.master.width);
        assert_eq!(areas.detail.y, 0);
    }

    #[test]
    fn test_master_detail_areas_heights_match() {
        let area = Rect {
            x: 0,
            y: 0,
            width: 100,
            height: 30,
        };

        let areas = MasterDetailAreas::new(area);

        assert_eq!(areas.master.height, area.height);
        assert_eq!(areas.detail.height, area.height);
    }

    #[test]
    fn test_master_detail_layout_default() {
        let layout = MasterDetailLayout::default();
        assert_eq!(layout.master_width_percent(), 30);
    }

    #[test]
    fn test_master_detail_layout_clone() {
        let layout1 = MasterDetailLayout::new().with_master_width(40);
        let layout2 = layout1.clone();
        assert_eq!(
            layout1.master_width_percent(),
            layout2.master_width_percent()
        );
    }

    #[test]
    fn test_master_detail_layout_areas_method() {
        let layout = MasterDetailLayout::new();
        let area = Rect {
            x: 0,
            y: 0,
            width: 100,
            height: 30,
        };

        let areas = layout.areas(area);
        assert!(areas.master.width > 0);
        assert!(areas.detail.width > 0);
    }

    #[test]
    fn test_master_detail_areas_no_overlap() {
        let area = Rect {
            x: 0,
            y: 0,
            width: 100,
            height: 30,
        };

        let areas = MasterDetailAreas::new(area);

        // Panes should not overlap
        assert_eq!(areas.master.x + areas.master.width, areas.detail.x);
    }
}
