/// FlexLayout — the underlying flex engine for VStack, HStack.
///
/// This is the power behind the stacks. Most developers use VStack/HStack
/// directly; FlexLayout is available when you need full control.

/// Direction of the flex axis.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FlexDirection {
    /// Children arranged top-to-bottom (VStack).
    Column,
    /// Children arranged left-to-right (HStack) — respects RTL automatically.
    Row,
    /// Like Column, but children wrap to new columns when they overflow.
    ColumnWrap,
    /// Like Row, but children wrap to new rows when they overflow.
    RowWrap,
}

impl FlexDirection {
    pub fn is_horizontal(&self) -> bool {
        matches!(self, FlexDirection::Row | FlexDirection::RowWrap)
    }

    pub fn is_vertical(&self) -> bool {
        matches!(self, FlexDirection::Column | FlexDirection::ColumnWrap)
    }

    pub fn wraps(&self) -> bool {
        matches!(
            self,
            FlexDirection::ColumnWrap | FlexDirection::RowWrap
        )
    }
}

/// Alignment along the cross axis.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CrossAxisAlignment {
    /// Stretch children to fill the cross axis.
    Stretch,
    /// Align children to the start of the cross axis.
    Start,
    /// Center children on the cross axis.
    Center,
    /// Align children to the end of the cross axis.
    End,
    /// Align text baselines (horizontal stacks only).
    Baseline,
}

/// Alignment along the main axis.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MainAxisAlignment {
    /// Pack children toward the start.
    Start,
    /// Center children.
    Center,
    /// Pack children toward the end.
    End,
    /// Distribute space between children.
    SpaceBetween,
    /// Distribute space around children.
    SpaceAround,
    /// Distribute space evenly around children.
    SpaceEvenly,
}

/// How much space the main axis should occupy.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MainAxisSize {
    /// Shrink to minimum size needed.
    Min,
    /// Expand to fill all available space.
    Max,
}

/// Logical horizontal alignment (RTL-aware).
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum HAlign {
    /// Toward the reading-start (left in LTR, right in RTL).
    Leading,
    Center,
    /// Toward the reading-end (right in LTR, left in RTL).
    Trailing,
}

/// Vertical alignment.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum VAlign {
    Top,
    Center,
    Bottom,
    Baseline,
}

/// Full flex layout specification.
#[derive(Debug, Clone)]
pub struct FlexLayout {
    pub direction: FlexDirection,
    pub main_axis_alignment: MainAxisAlignment,
    pub cross_axis_alignment: CrossAxisAlignment,
    pub main_axis_size: MainAxisSize,
    /// Gap between children in dp.
    pub gap: u32,
}

impl FlexLayout {
    /// VStack defaults (column, wrapping, leading-aligned).
    pub fn vstack(spacing: u32, wrap: bool) -> Self {
        Self {
            direction: if wrap {
                FlexDirection::ColumnWrap
            } else {
                FlexDirection::Column
            },
            main_axis_alignment: MainAxisAlignment::Start,
            cross_axis_alignment: CrossAxisAlignment::Stretch,
            main_axis_size: MainAxisSize::Max,
            gap: spacing,
        }
    }

    /// HStack defaults (row, wrapping, center-aligned vertically).
    pub fn hstack(spacing: u32, wrap: bool) -> Self {
        Self {
            direction: if wrap {
                FlexDirection::RowWrap
            } else {
                FlexDirection::Row
            },
            main_axis_alignment: MainAxisAlignment::Start,
            cross_axis_alignment: CrossAxisAlignment::Center,
            main_axis_size: MainAxisSize::Max,
            gap: spacing,
        }
    }
}

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

    #[test]
    fn flex_direction_horizontal() {
        assert!(FlexDirection::Row.is_horizontal());
        assert!(FlexDirection::RowWrap.is_horizontal());
        assert!(!FlexDirection::Column.is_horizontal());
    }

    #[test]
    fn flex_direction_vertical() {
        assert!(FlexDirection::Column.is_vertical());
        assert!(!FlexDirection::Row.is_vertical());
    }

    #[test]
    fn flex_direction_wraps() {
        assert!(FlexDirection::RowWrap.wraps());
        assert!(!FlexDirection::Row.wraps());
    }

    #[test]
    fn vstack_layout_defaults() {
        let layout = FlexLayout::vstack(8, true);
        assert!(layout.direction.is_vertical());
        assert!(layout.direction.wraps());
        assert_eq!(layout.gap, 8);
    }

    #[test]
    fn hstack_layout_defaults() {
        let layout = FlexLayout::hstack(16, false);
        assert!(layout.direction.is_horizontal());
        assert!(!layout.direction.wraps());
        assert_eq!(layout.gap, 16);
        assert_eq!(layout.cross_axis_alignment, CrossAxisAlignment::Center);
    }
}
