use nalgebra_glm::{Vec2, Vec4};

use crate::ecs::text::components::TextProperties;
use crate::render::wgpu::passes::geometry::{UiLayer, UiRect};

use super::super::types::{Rect, UiId, UiResponse};
use super::types::{ImmediateUi, UiWidget};

impl ImmediateUi {
    pub fn dropdown(&mut self, id: &str, options: &[&str], selected: &mut usize) -> UiResponse {
        let uid = self.make_id(id);
        let font_size = self.style.font_size;

        let max_option_len = options.iter().map(|s| s.len()).max().unwrap_or(0);
        let dropdown_width =
            (max_option_len as f32 * font_size * 0.55 + self.style.padding * 4.0).max(120.0);
        let dropdown_height = self.style.button_height;

        let rect = self.layout_stack.allocate(Vec2::new(
            dropdown_width,
            dropdown_height + self.style.spacing,
        ));
        let dropdown_rect = Rect::new(rect.x(), rect.y(), dropdown_width, dropdown_height);

        let state = self.get_state(uid);
        let is_open = state.open;

        let header_response = self.interact(uid, dropdown_rect);

        let mut response = UiResponse::none(uid, dropdown_rect);
        response.hovered = header_response.hovered;
        response.active = header_response.active;

        if header_response.clicked {
            let mut new_state = state;
            new_state.open = !is_open;
            self.set_state(uid, new_state);
        }

        let bg_color = if header_response.active || is_open {
            self.style.background_color_active
        } else if header_response.hovered {
            self.style.background_color_hovered
        } else {
            self.style.background_color
        };

        self.add_rect(UiRect {
            position: Vec2::new(dropdown_rect.x(), dropdown_rect.y()),
            size: dropdown_rect.size(),
            color: bg_color,
            corner_radius: self.style.corner_radius,
            border_width: self.style.border_width,
            border_color: self.style.border_color,
            clip_rect: None,
            ..Default::default()
        });

        let current_text = options.get(*selected).copied().unwrap_or("--");
        let arrow = if is_open { "^" } else { "v" };
        let display_text = format!("{} {}", current_text, arrow);
        let text_x = dropdown_rect.x() + self.style.padding;
        let text_y = dropdown_rect.y() + (dropdown_height - font_size) * 0.5;

        let text_color = if header_response.hovered || is_open {
            Vec4::new(1.0, 0.95, 0.7, 1.0)
        } else {
            self.style.text_color
        };

        let props = TextProperties {
            font_size,
            color: text_color,
            ..Default::default()
        };

        self.add_text(&display_text, Vec2::new(text_x, text_y), props);

        if is_open && !options.is_empty() {
            let option_height = dropdown_height;
            let popup_height = options.len() as f32 * option_height;
            let popup_y = dropdown_rect.max.y;

            self.deferred_rects.push(UiRect {
                position: Vec2::new(dropdown_rect.x() + 4.0, popup_y + 4.0),
                size: Vec2::new(dropdown_width, popup_height),
                color: Vec4::new(0.0, 0.0, 0.0, 0.5),
                corner_radius: self.style.corner_radius,
                border_width: 0.0,
                border_color: Vec4::new(0.0, 0.0, 0.0, 0.0),
                clip_rect: None,
                layer: UiLayer::Popups,
                z_index: 0,
            });

            self.deferred_rects.push(UiRect {
                position: Vec2::new(dropdown_rect.x(), popup_y),
                size: Vec2::new(dropdown_width, popup_height),
                color: Vec4::new(0.22, 0.22, 0.24, 1.0),
                corner_radius: self.style.corner_radius,
                border_width: 1.0,
                border_color: Vec4::new(0.5, 0.5, 0.55, 1.0),
                clip_rect: None,
                layer: UiLayer::Popups,
                z_index: 1,
            });

            let mut clicked_outside = self.mouse_just_pressed;
            for (index, option) in options.iter().enumerate() {
                let option_rect = Rect::new(
                    dropdown_rect.x(),
                    popup_y + index as f32 * option_height,
                    dropdown_width,
                    option_height,
                );

                let option_id = UiId::with_parent(uid, &format!("_opt_{}", index));
                let option_response = self.interact_unclipped(option_id, option_rect);

                if option_response.hovered || option_response.active {
                    clicked_outside = false;
                }

                let is_selected = index == *selected;
                let option_bg = if option_response.active {
                    Vec4::new(0.3, 0.5, 0.8, 1.0)
                } else if option_response.hovered {
                    Vec4::new(0.25, 0.25, 0.3, 1.0)
                } else if is_selected {
                    Vec4::new(0.2, 0.2, 0.25, 1.0)
                } else {
                    Vec4::new(0.0, 0.0, 0.0, 0.0)
                };

                if option_bg.w > 0.0 {
                    self.deferred_rects.push(UiRect {
                        position: option_rect.min,
                        size: option_rect.size(),
                        color: option_bg,
                        corner_radius: 0.0,
                        border_width: 0.0,
                        border_color: Vec4::new(0.0, 0.0, 0.0, 0.0),
                        clip_rect: None,
                        layer: UiLayer::Popups,
                        z_index: 2,
                    });
                }

                let option_text_x = option_rect.x() + self.style.padding;
                let option_text_y = option_rect.y() + (option_height - font_size) * 0.5;

                let option_text_color = if is_selected {
                    Vec4::new(0.4, 0.8, 1.0, 1.0)
                } else {
                    self.style.text_color
                };

                self.deferred_widgets.push(UiWidget {
                    text: option.to_string(),
                    position: Vec2::new(option_text_x, option_text_y),
                    properties: TextProperties {
                        font_size,
                        color: option_text_color,
                        ..Default::default()
                    },
                    clip_rect: None,
                    layer: UiLayer::Popups,
                    z_index: 3,
                });

                if option_response.clicked {
                    *selected = index;
                    response.changed = true;
                    let mut new_state = self.get_state(uid);
                    new_state.open = false;
                    self.set_state(uid, new_state);
                }
            }

            if clicked_outside && !header_response.hovered && !header_response.active {
                let mut new_state = self.get_state(uid);
                new_state.open = false;
                self.set_state(uid, new_state);
            }
        }

        response
    }

    pub fn dropdown_with_label(
        &mut self,
        label: &str,
        options: &[&str],
        selected: &mut usize,
    ) -> UiResponse {
        let start_cursor = self.layout_stack.cursor();
        let font_size = self.style.font_size;
        let label_width = label.len() as f32 * font_size * 0.55 + self.style.spacing;

        let props = TextProperties {
            font_size,
            color: self.style.text_color,
            ..Default::default()
        };

        self.add_text(
            label,
            Vec2::new(start_cursor.x, start_cursor.y + 7.0),
            props,
        );

        let temp_cursor = start_cursor + Vec2::new(label_width, 0.0);
        if let Some(layout) = self.layout_stack.current_mut() {
            layout.set_cursor(temp_cursor);
        }

        let response = self.dropdown(label, options, selected);

        if let Some(layout) = self.layout_stack.current_mut() {
            layout.set_cursor(Vec2::new(
                start_cursor.x,
                response.rect.max.y + self.style.spacing,
            ));
        }

        response
    }

    pub fn theme_dropdown(&mut self) -> UiResponse {
        let uid = self.make_id("theme_dropdown");
        let font_size = self.style.font_size;

        let max_theme_name_len = self
            .theme_state
            .presets
            .iter()
            .map(|t| t.name.len())
            .max()
            .unwrap_or(10);
        let dropdown_width =
            (max_theme_name_len as f32 * font_size * 0.55 + self.style.padding * 4.0).max(150.0);
        let dropdown_height = self.style.button_height;

        let rect = self.layout_stack.allocate(Vec2::new(
            dropdown_width,
            dropdown_height + self.style.spacing,
        ));
        let dropdown_rect = Rect::new(rect.x(), rect.y(), dropdown_width, dropdown_height);

        let state = self.get_state(uid);
        let is_open = state.open;

        let header_response = self.interact(uid, dropdown_rect);

        let mut response = UiResponse::none(uid, dropdown_rect);
        response.hovered = header_response.hovered;
        response.active = header_response.active;

        if header_response.clicked {
            let mut new_state = state;
            new_state.open = !is_open;
            self.set_state(uid, new_state);
        }

        let bg_color = if header_response.active || is_open {
            self.style.background_color_active
        } else if header_response.hovered {
            self.style.background_color_hovered
        } else {
            self.style.background_color
        };

        self.add_rect(UiRect {
            position: Vec2::new(dropdown_rect.x(), dropdown_rect.y()),
            size: dropdown_rect.size(),
            color: bg_color,
            corner_radius: self.style.corner_radius,
            border_width: self.style.border_width,
            border_color: self.style.border_color,
            clip_rect: None,
            ..Default::default()
        });

        let current_text = &self.theme_state.current_theme.name;
        let arrow = if is_open { "^" } else { "v" };
        let display_text = format!("{} {}", current_text, arrow);
        let text_x = dropdown_rect.x() + self.style.padding;
        let text_y = dropdown_rect.y() + (dropdown_height - font_size) * 0.5;

        let text_color = if header_response.hovered || is_open {
            Vec4::new(1.0, 0.95, 0.7, 1.0)
        } else {
            self.style.text_color
        };

        let props = TextProperties {
            font_size,
            color: text_color,
            ..Default::default()
        };

        self.add_text(&display_text, Vec2::new(text_x, text_y), props);

        let preset_count = self.theme_state.presets.len();
        if is_open && preset_count > 0 {
            let option_height = dropdown_height;
            let popup_height = preset_count as f32 * option_height;
            let popup_y = dropdown_rect.max.y;

            self.deferred_rects.push(UiRect {
                position: Vec2::new(dropdown_rect.x() + 4.0, popup_y + 4.0),
                size: Vec2::new(dropdown_width, popup_height),
                color: Vec4::new(0.0, 0.0, 0.0, 0.5),
                corner_radius: self.style.corner_radius,
                border_width: 0.0,
                border_color: Vec4::new(0.0, 0.0, 0.0, 0.0),
                clip_rect: None,
                layer: UiLayer::Popups,
                z_index: 0,
            });

            self.deferred_rects.push(UiRect {
                position: Vec2::new(dropdown_rect.x(), popup_y),
                size: Vec2::new(dropdown_width, popup_height),
                color: Vec4::new(0.22, 0.22, 0.24, 1.0),
                corner_radius: self.style.corner_radius,
                border_width: 1.0,
                border_color: Vec4::new(0.5, 0.5, 0.55, 1.0),
                clip_rect: None,
                layer: UiLayer::Popups,
                z_index: 1,
            });

            let mut clicked_outside = self.mouse_just_pressed;
            let selected_index = self.theme_state.selected_preset_index;
            let preset_names: Vec<_> = self
                .theme_state
                .presets
                .iter()
                .map(|p| p.name.clone())
                .collect();
            let first_light_index = self.theme_state.presets.iter().position(|p| !p.dark_mode);

            for (index, preset_name) in preset_names.iter().enumerate() {
                let option_rect = Rect::new(
                    dropdown_rect.x(),
                    popup_y + index as f32 * option_height,
                    dropdown_width,
                    option_height,
                );

                let option_id = UiId::with_parent(uid, &format!("_theme_{}", index));
                let option_response = self.interact_unclipped(option_id, option_rect);

                if option_response.hovered || option_response.active {
                    clicked_outside = false;
                    self.theme_state.set_preview(Some(index));
                }

                let is_selected = selected_index == Some(index);
                let is_light_section_start = first_light_index == Some(index);
                let option_bg = if option_response.active {
                    Vec4::new(0.3, 0.5, 0.8, 1.0)
                } else if option_response.hovered {
                    Vec4::new(0.25, 0.25, 0.3, 1.0)
                } else if is_selected {
                    Vec4::new(0.2, 0.2, 0.25, 1.0)
                } else {
                    Vec4::new(0.0, 0.0, 0.0, 0.0)
                };

                if is_light_section_start && index > 0 {
                    self.deferred_rects.push(UiRect {
                        position: Vec2::new(
                            dropdown_rect.x() + self.style.padding,
                            popup_y + index as f32 * option_height - 1.0,
                        ),
                        size: Vec2::new(dropdown_width - self.style.padding * 2.0, 1.0),
                        color: Vec4::new(0.5, 0.5, 0.5, 0.5),
                        corner_radius: 0.0,
                        border_width: 0.0,
                        border_color: Vec4::new(0.0, 0.0, 0.0, 0.0),
                        clip_rect: None,
                        layer: UiLayer::Popups,
                        z_index: 2,
                    });
                }

                if option_bg.w > 0.0 {
                    self.deferred_rects.push(UiRect {
                        position: option_rect.min,
                        size: option_rect.size(),
                        color: option_bg,
                        corner_radius: 0.0,
                        border_width: 0.0,
                        border_color: Vec4::new(0.0, 0.0, 0.0, 0.0),
                        clip_rect: None,
                        layer: UiLayer::Popups,
                        z_index: 2,
                    });
                }

                let option_text_x = option_rect.x() + self.style.padding;
                let option_text_y = option_rect.y() + (option_height - font_size) * 0.5;

                let display_name = if is_selected {
                    format!("* {}", preset_name)
                } else {
                    format!("   {}", preset_name)
                };

                let option_text_color = if is_selected {
                    Vec4::new(0.4, 0.8, 1.0, 1.0)
                } else {
                    self.style.text_color
                };

                self.deferred_widgets.push(UiWidget {
                    text: display_name,
                    position: Vec2::new(option_text_x, option_text_y),
                    properties: TextProperties {
                        font_size,
                        color: option_text_color,
                        ..Default::default()
                    },
                    clip_rect: None,
                    layer: UiLayer::Popups,
                    z_index: 3,
                });

                if option_response.clicked {
                    self.theme_state.select_theme(index);
                    response.changed = true;
                    let mut new_state = self.get_state(uid);
                    new_state.open = false;
                    self.set_state(uid, new_state);
                }
            }

            if clicked_outside && !header_response.hovered && !header_response.active {
                let mut new_state = self.get_state(uid);
                new_state.open = false;
                self.set_state(uid, new_state);
            }
        }

        response
    }

    pub fn theme_dropdown_with_label(&mut self, label: &str) -> UiResponse {
        let start_cursor = self.layout_stack.cursor();
        let font_size = self.style.font_size;
        let label_width = label.len() as f32 * font_size * 0.55 + self.style.spacing;

        let props = TextProperties {
            font_size,
            color: self.style.text_color,
            ..Default::default()
        };

        self.add_text(
            label,
            Vec2::new(start_cursor.x, start_cursor.y + 7.0),
            props,
        );

        let temp_cursor = start_cursor + Vec2::new(label_width, 0.0);
        if let Some(layout) = self.layout_stack.current_mut() {
            layout.set_cursor(temp_cursor);
        }

        let response = self.theme_dropdown();

        if let Some(layout) = self.layout_stack.current_mut() {
            layout.set_cursor(Vec2::new(
                start_cursor.x,
                response.rect.max.y + self.style.spacing,
            ));
        }

        response
    }

    pub fn menu(&mut self, label: &str, items: &[&str]) -> Option<usize> {
        let uid = self.make_id(label);
        let font_size = self.style.font_size;

        let button_width = label.len() as f32 * font_size * 0.55 + self.style.padding * 2.0;
        let button_height = self.style.button_height;

        let rect = self
            .layout_stack
            .allocate(Vec2::new(button_width, button_height + self.style.spacing));
        let button_rect = Rect::new(rect.x(), rect.y(), button_width, button_height);

        let state = self.get_state(uid);
        let is_open = state.open;

        let response = self.interact(uid, button_rect);

        if response.clicked {
            let mut new_state = state;
            new_state.open = !is_open;
            self.set_state(uid, new_state);
        }

        let bg_color = if response.active || is_open {
            self.style.background_color_active
        } else if response.hovered {
            self.style.background_color_hovered
        } else {
            Vec4::new(0.0, 0.0, 0.0, 0.0)
        };

        if bg_color.w > 0.0 {
            self.add_rect(UiRect {
                position: button_rect.min,
                size: button_rect.size(),
                color: bg_color,
                corner_radius: self.style.corner_radius,
                border_width: 0.0,
                border_color: Vec4::new(0.0, 0.0, 0.0, 0.0),
                clip_rect: None,
                ..Default::default()
            });
        }

        let text_x = button_rect.x() + self.style.padding;
        let text_y = button_rect.y() + (button_height - font_size) * 0.5;

        let text_color = if response.hovered || is_open {
            Vec4::new(1.0, 1.0, 1.0, 1.0)
        } else {
            Vec4::new(0.9, 0.9, 0.9, 1.0)
        };

        let props = TextProperties {
            font_size,
            color: text_color,
            ..Default::default()
        };

        self.add_text(label, Vec2::new(text_x, text_y), props);

        let mut clicked_item: Option<usize> = None;

        if is_open && !items.is_empty() {
            let max_item_len = items.iter().map(|s| s.len()).max().unwrap_or(0);
            let popup_width = (max_item_len as f32 * font_size * 0.55 + self.style.padding * 4.0)
                .max(button_width)
                .max(120.0);
            let item_height = button_height;
            let popup_height = items.len() as f32 * item_height;
            let popup_y = button_rect.max.y;

            self.deferred_rects.push(UiRect {
                position: Vec2::new(button_rect.x() + 4.0, popup_y + 4.0),
                size: Vec2::new(popup_width, popup_height),
                color: Vec4::new(0.0, 0.0, 0.0, 0.5),
                corner_radius: self.style.corner_radius,
                border_width: 0.0,
                border_color: Vec4::new(0.0, 0.0, 0.0, 0.0),
                clip_rect: None,
                layer: UiLayer::Popups,
                z_index: 0,
            });

            self.deferred_rects.push(UiRect {
                position: Vec2::new(button_rect.x(), popup_y),
                size: Vec2::new(popup_width, popup_height),
                color: Vec4::new(0.22, 0.22, 0.24, 1.0),
                corner_radius: self.style.corner_radius,
                border_width: 1.0,
                border_color: Vec4::new(0.5, 0.5, 0.55, 1.0),
                clip_rect: None,
                layer: UiLayer::Popups,
                z_index: 1,
            });

            let mut clicked_outside = self.mouse_just_pressed;
            for (index, item) in items.iter().enumerate() {
                let item_rect = Rect::new(
                    button_rect.x(),
                    popup_y + index as f32 * item_height,
                    popup_width,
                    item_height,
                );

                let item_id = UiId::with_parent(uid, &format!("_item_{}", index));
                let item_response = self.interact(item_id, item_rect);

                if item_response.hovered || item_response.active {
                    clicked_outside = false;
                }

                let item_bg = if item_response.active {
                    Vec4::new(0.3, 0.5, 0.8, 1.0)
                } else if item_response.hovered {
                    Vec4::new(0.25, 0.25, 0.3, 1.0)
                } else {
                    Vec4::new(0.0, 0.0, 0.0, 0.0)
                };

                if item_bg.w > 0.0 {
                    self.deferred_rects.push(UiRect {
                        position: item_rect.min,
                        size: item_rect.size(),
                        color: item_bg,
                        corner_radius: 0.0,
                        border_width: 0.0,
                        border_color: Vec4::new(0.0, 0.0, 0.0, 0.0),
                        clip_rect: None,
                        layer: UiLayer::Popups,
                        z_index: 2,
                    });
                }

                let item_text_x = item_rect.x() + self.style.padding;
                let item_text_y = item_rect.y() + (item_height - font_size) * 0.5;

                self.deferred_widgets.push(UiWidget {
                    text: item.to_string(),
                    position: Vec2::new(item_text_x, item_text_y),
                    properties: TextProperties {
                        font_size,
                        color: self.style.text_color,
                        ..Default::default()
                    },
                    clip_rect: None,
                    layer: UiLayer::Popups,
                    z_index: 3,
                });

                if item_response.clicked {
                    clicked_item = Some(index);
                    let mut new_state = self.get_state(uid);
                    new_state.open = false;
                    self.set_state(uid, new_state);
                }
            }

            if clicked_outside && !response.hovered && !response.active {
                let mut new_state = self.get_state(uid);
                new_state.open = false;
                self.set_state(uid, new_state);
            }
        }

        clicked_item
    }
}
