#pragma once
#include "widget/mwidget.h"
#include "geometry/geometry.h"
#include "misc/mirage_type.h"

/**
 * @brief 为单个子部件布局的通用函数
 *
 * @param in_allotted_geometry 分配给容器的几何区域
 * @param child_widget 子部件
 * @param h_alignment 水平对齐方式
 * @param v_alignment 垂直对齐方式
 * @param margin 边距
 */
void arrange_single_child(
	const geometry_t& in_allotted_geometry,
	const std::shared_ptr<mwidget_interface>& child_widget,
	horizontal_alignment_t h_alignment,
	vertical_alignment_t v_alignment,
	const margin_t& margin = margin_t() // 默认为空边距
);

template<typename T>
concept has_vertical_alignment = requires {
	T().vertical_alignment();
};
template<typename T>
concept has_horizontal_alignment = requires {
	T().horizontal_alignment();
};

template<orientation_t LayoutOrientation, typename SlotType>
void arrange_box_children(
	const geometry_t& in_allotted_geometry,
	float in_layout_scale_multiplier,
	visibility_t in_visibility_filter,
	const std::vector<SlotType>& child_slots,
	flow_direction_t flow_dir = flow_direction_t::left_to_right
){
	const auto& container_size = in_allotted_geometry.get_local_size();
	if (container_size.x() <= 0 || container_size.y() <= 0) {
		return;
	}

	// 确定主轴方向和是否反向
	constexpr bool is_horizontal = LayoutOrientation == orientation_t::horizontal;
	const bool is_reversed = flow_dir == flow_direction_t::right_to_left;

	// 第一轮：收集可见部件信息并计算自动尺寸
	struct slot_widget_info {
		std::shared_ptr<mwidget_interface> widget;
		const SlotType*                    slot;
		float                              size{};
		float                              margin_start{};       // 主轴起始边缘的margin
		float                              margin_end{};         // 主轴结束边缘的margin
		float                              margin_cross_start{}; // 交叉轴起始边缘的margin
		float                              margin_cross_end{};   // 交叉轴结束边缘的margin
	};

	std::vector<slot_widget_info> visible_widgets;
	float                         total_auto_size      = 0.0f;
	float                         total_stretch_factor = 0.0f;
	float                         total_margins        = 0.0f; // 主轴方向上所有边距的总和

	for (const auto& child_slot : child_slots) {
		const auto& widget = child_slot.get();
		// 无效部件或不可见部件跳过
		if (!widget)
			continue;

		if (!has_any_flag(widget->get_visibility(), in_visibility_filter))
			continue;

		const auto& margin        = child_slot.margin();
		const float margin_left   = margin.left;
		const float margin_right  = margin.right;
		const float margin_top    = margin.top;
		const float margin_bottom = margin.bottom;

		float margin_start, margin_end, margin_cross_start, margin_cross_end;
		if (is_horizontal) {
			margin_start       = margin_left;
			margin_end         = margin_right;
			margin_cross_start = margin_top;
			margin_cross_end   = margin_bottom;
		} else {
			margin_start       = margin_top;
			margin_end         = margin_bottom;
			margin_cross_start = margin_left;
			margin_cross_end   = margin_right;
		}

		total_margins += margin_start + margin_end;
		slot_widget_info info{ widget,
		                       &child_slot,
		                       0.0f,
		                       margin_start,
		                       margin_end,
		                       margin_cross_start,
		                       margin_cross_end
		};

		const auto& size_attr = child_slot.size();
		if (size_attr.is_auto_size()) {
			// 缓存部件的期望大小
			widget->cache_desired_size(in_layout_scale_multiplier);
			const auto& desired_size = widget->get_desired_size().value();

			info.size = is_horizontal ? desired_size.x() : desired_size.y();
			total_auto_size += info.size;
		} else {
			total_stretch_factor += size_attr.stretch();
		}

		visible_widgets.push_back(info);
	}

	if (visible_widgets.empty())
		return;

	// 计算拉伸部件的可用空间（需要减去所有margin）
	const float container_primary_size = is_horizontal ? container_size.x() : container_size.y();
	const float remaining_space = std::max(0.0f, container_primary_size - total_auto_size - total_margins);

	// 第二轮：计算拉伸部件的最终尺寸
	for (auto& info : visible_widgets) {
		const auto& size_attr = info.slot->size();
		if (!size_attr.is_auto_size()) {
			const float stretch_factor = size_attr.stretch();
			if (total_stretch_factor > 0.0f) {
				info.size = remaining_space * (stretch_factor / total_stretch_factor);
			} else {
				info.size = 0.0f;
			}
		}
	}

		// 第三轮：排列部件
	float position = 0.0f;

	if (is_reversed)
		std::reverse(visible_widgets.begin(), visible_widgets.end());

	for (const auto& info : visible_widgets) {
		position += info.margin_start;

		// 获取部件期望的大小（需要同时考虑主轴和交叉轴）
		// 确保获取最新的期望尺寸，因为布局可能会嵌套调用
		info.widget->cache_desired_size(in_layout_scale_multiplier);
		const auto& desired_size = info.widget->get_desired_size().value();

		Eigen::Vector2f pos = Eigen::Vector2f::Zero();
		Eigen::Vector2f size = Eigen::Vector2f::Zero(); // 初始化为0

		if (is_horizontal) {
			// --- 主轴 (X) ---
			size.x() = info.size; // 主轴尺寸由之前的计算确定 (Auto 或 Stretch)
			if (is_reversed)
				pos.x() = container_primary_size - position - info.size;
			else
				pos.x() = position;

			// --- 交叉轴 (Y) ---
			pos.y()                      = info.margin_cross_start;
			const float available_height = container_size.y() - (info.margin_cross_start + info.margin_cross_end);
			const float widget_height    = desired_size.y(); // 控件期望的高度
			float       final_height     = available_height; // 默认拉伸交叉轴

			if constexpr (has_vertical_alignment<SlotType>) {
				const auto& v_alignment = info.slot->vertical_alignment();
				// **如果指定了具体的对齐方式（非拉伸），则使用控件期望的高度**
				// （这里假设 Top/Center/Bottom 意味着不拉伸，需要根据你的枚举定义调整）
				bool use_desired_height = (v_alignment == vertical_alignment_t::top ||
				                           v_alignment == vertical_alignment_t::center ||
				                           v_alignment == vertical_alignment_t::bottom);

				if (use_desired_height) {
					final_height = std::min(widget_height, available_height); // 使用期望高度，但不超过可用空间
					if (available_height > widget_height) { // 只有在有剩余空间时才需要调整对齐位置
						if (v_alignment == vertical_alignment_t::center) {
							pos.y() += (available_height - widget_height) / 2.0f;
						} else if (v_alignment == vertical_alignment_t::bottom) {
							pos.y() += (available_height - widget_height);
						}
						// Top 对齐: pos.y() 初始值就是正确的
					}
				}
				// else: 拉伸对齐，保持 final_height = available_height
			}
			// else (SlotType 没有垂直对齐属性): 默认行为是拉伸，final_height = available_height

			size.y() = final_height; // **传递给子控件的最终高度**

		} else { // 垂直布局
			// --- 主轴 (Y) ---
			size.y() = info.size; // 主轴尺寸由之前的计算确定 (Auto 或 Stretch)
			if (is_reversed)
				pos.y() = container_primary_size - position - info.size;
			else
				pos.y() = position;

			// --- 交叉轴 (X) ---
			pos.x()                     = info.margin_cross_start;
			const float available_width = container_size.x() - (info.margin_cross_start + info.margin_cross_end);
			const float widget_width    = desired_size.x(); // 控件期望的宽度
			float       final_width     = available_width;  // 默认拉伸交叉轴

			if constexpr (has_horizontal_alignment<SlotType>) {
				const auto& h_alignment = info.slot->horizontal_alignment();
				// **如果指定了具体的对齐方式（非拉伸），则使用控件期望的宽度**
				// （这里假设 Left/Center/Right 意味着不拉伸）
				bool use_desired_width = (h_alignment == horizontal_alignment_t::left ||
				                          h_alignment == horizontal_alignment_t::center ||
				                          h_alignment == horizontal_alignment_t::right);

				if (use_desired_width) {
					final_width = std::min(widget_width, available_width); // 使用期望宽度，但不超过可用空间
					if (available_width > widget_width) { // 只有在有剩余空间时才需要调整对齐位置
						if (h_alignment == horizontal_alignment_t::center) {
							pos.x() += (available_width - widget_width) / 2.0f;
						} else if (h_alignment == horizontal_alignment_t::right) {
							pos.x() += (available_width - widget_width);
						}
						// **Left 对齐**: pos.x() 初始值就是正确的
					}
				}
				// else: 拉伸对齐，保持 final_width = available_width
			}
			// else (SlotType 没有水平对齐属性): 默认行为是拉伸，final_width = available_width

			size.x() = final_width; // **传递给子控件的最终宽度**
		}

		// 确保尺寸不为负
		size.x() = std::max(0.0f, size.x());
		size.y() = std::max(0.0f, size.y());

		// 使用计算好的位置和尺寸创建子控件的几何信息
		const auto& child_geometry = in_allotted_geometry.make_child(pos, size);
		info.widget->set_geometry(child_geometry);
		info.widget->arrange_children(child_geometry); // 子控件在其分配到的几何区域内进行布局

		position += info.size + info.margin_end;
	}
}

// 计算水平或垂直框的期望大小
template<orientation_t LayoutOrientation, typename SlotType>
Eigen::Vector2f compute_box_desired_size(const std::vector<SlotType>& child_slots) {
    Eigen::Vector2f desired_size = Eigen::Vector2f::Zero();

    for (const auto& slot : child_slots) {
        const auto& widget = slot.get();
        if (widget && has_any_flag(widget->get_visibility(), visibility_t::any_visible)) {
        	widget->cache_desired_size(widget->get_dpi_scale());
            Eigen::Vector2f widget_desired_size = widget->get_desired_size().value();
            if constexpr (LayoutOrientation == orientation_t::horizontal) {
                desired_size.x() += widget_desired_size.x();
                desired_size.y() = std::max(desired_size.y(), widget_desired_size.y());
            } else {
                desired_size.x() = std::max(desired_size.x(), widget_desired_size.x());
                desired_size.y() += widget_desired_size.y();
            }
        }
    }

    return desired_size;
}