use crate::ecs::text::components::VerticalAlignment;
use crate::ecs::ui::types::Rect;
use crate::ecs::world::World;
use crate::render::wgpu::passes::geometry::UiLayer;
use nalgebra_glm::{Vec2, Vec4};

use super::ShellState;

pub fn shell_retained_ui<C>(shell: &mut ShellState<C>, world: &mut World) {
    if !shell.should_render() {
        return;
    }

    let screen_size = world
        .resources
        .window
        .handle
        .as_ref()
        .map(|handle| {
            let size = handle.inner_size();
            Vec2::new(size.width as f32, size.height as f32)
        })
        .unwrap_or(Vec2::new(1920.0, 1080.0));
    let screen_width = screen_size.x;
    let screen_height = screen_size.y;

    let mouse_pos = Vec2::new(
        world.resources.input.mouse.position.x,
        world.resources.input.mouse.position.y,
    );
    let mouse_down = world
        .resources
        .input
        .mouse
        .state
        .contains(crate::ecs::world::resources::MouseState::LEFT_CLICKED);
    let mouse_just_pressed = world
        .resources
        .input
        .mouse
        .state
        .contains(crate::ecs::world::resources::MouseState::LEFT_JUST_PRESSED);

    let min_height = 100.0;
    let max_height = screen_height * 0.9;
    shell.height = shell.height.clamp(min_height, max_height);
    let shell_height = shell.height;
    let current_height = shell_height * shell.animation_progress;

    let resize_handle_height = 8.0;
    let resize_area = Rect::new(
        0.0,
        current_height - resize_handle_height,
        screen_width,
        resize_handle_height * 2.0,
    );
    let mouse_in_resize = resize_area.contains(mouse_pos) && shell.animation_progress > 0.95;

    if mouse_in_resize && mouse_just_pressed && !shell.dragging_resize {
        shell.dragging_resize = true;
        shell.drag_start_y = mouse_pos.y;
        shell.drag_start_height = shell.height;
    }

    if shell.dragging_resize {
        if mouse_down {
            let delta = mouse_pos.y - shell.drag_start_y;
            shell.height = (shell.drag_start_height + delta).clamp(min_height, max_height);
        } else {
            shell.dragging_resize = false;
        }
    }

    let bg_color = Vec4::new(0.06, 0.06, 0.08, 0.95);
    let header_color = Vec4::new(0.39, 0.78, 0.39, 1.0);
    let command_color = Vec4::new(0.59, 0.78, 1.0, 1.0);
    let output_color = Vec4::new(0.78, 0.78, 0.78, 1.0);
    let border_color = Vec4::new(0.4, 0.4, 0.45, 1.0);
    let transparent = Vec4::new(0.0, 0.0, 0.0, 0.0);

    let panel_clip = Rect::new(0.0, 0.0, screen_width, current_height);

    let ui = &mut world.resources.retained_ui;

    ui.draw_overlay_rect(crate::render::wgpu::passes::geometry::UiRect {
        position: Vec2::new(0.0, 0.0),
        size: Vec2::new(screen_width, current_height),
        color: bg_color,
        corner_radius: 0.0,
        border_width: 0.0,
        border_color: transparent,
        rotation: 0.0,
        clip_rect: Some(panel_clip),
        layer: UiLayer::Tooltips,
        z_index: 0,
        shadow: None,
        effect_kind: 0,
        effect_params: [0.0; 4],
        quad_corners: None,
    });

    let padding = 10.0;
    let font_size = 14.0;
    let line_height_ratio = 1.4_f32;
    let line_height = (font_size * line_height_ratio).round();
    let input_height = 32.0;
    let separator_height = 1.0;
    let scrollbar_width = 8.0;
    let scrollbar_inset = 2.0;
    let output_top_padding = 8.0;
    let output_bottom_padding = 4.0;

    let bottom_separator_y = current_height - input_height - separator_height;
    ui.draw_overlay_rect(crate::render::wgpu::passes::geometry::UiRect {
        position: Vec2::new(0.0, bottom_separator_y),
        size: Vec2::new(screen_width, separator_height),
        color: border_color,
        corner_radius: 0.0,
        border_width: 0.0,
        border_color: transparent,
        rotation: 0.0,
        clip_rect: Some(panel_clip),
        layer: UiLayer::Tooltips,
        z_index: 1,
        shadow: None,
        effect_kind: 0,
        effect_params: [0.0; 4],
        quad_corners: None,
    });

    let output_top = output_top_padding;
    let output_bottom = bottom_separator_y - output_bottom_padding;
    let output_height = (output_bottom - output_top).max(0.0);
    let output_clip = Rect::new(0.0, output_top, screen_width, output_height);

    let mut total_content_height = 0.0;
    for line in &shell.output {
        let line_count = if line.text.is_empty() {
            1
        } else {
            line.text.split('\n').count()
        };
        total_content_height += line_count as f32 * line_height;
    }

    let max_scroll = (total_content_height - output_height).max(0.0);

    if shell.scroll_to_bottom {
        shell.scroll_offset = max_scroll;
        shell.scroll_to_bottom = false;
    }

    let pointer_in_output =
        output_height > 0.0 && output_clip.contains(mouse_pos) && shell.animation_progress > 0.95;
    if pointer_in_output {
        let wheel_y = world.resources.input.mouse.wheel_delta.y;
        if wheel_y.abs() > 0.0 {
            shell.scroll_offset -= wheel_y * line_height * 3.0;
        }
    }

    let scrollbar_visible = output_height > 0.0 && total_content_height > output_height;
    let scrollbar_x = screen_width - scrollbar_width - scrollbar_inset;
    let scrollbar_track_y = output_top;
    let scrollbar_track_height = output_height;
    let scrollbar_track = Rect::new(
        scrollbar_x,
        scrollbar_track_y,
        scrollbar_width,
        scrollbar_track_height,
    );
    let thumb_height = if scrollbar_visible {
        (output_height / total_content_height) * scrollbar_track_height
    } else {
        scrollbar_track_height
    }
    .max(20.0);
    if scrollbar_visible
        && mouse_just_pressed
        && scrollbar_track.contains(mouse_pos)
        && shell.animation_progress > 0.95
    {
        shell.dragging_scrollbar = true;
        let thumb_y = scrollbar_track_y
            + if max_scroll > 0.0 {
                (shell.scroll_offset / max_scroll) * (scrollbar_track_height - thumb_height)
            } else {
                0.0
            };
        shell.scrollbar_drag_grab_offset =
            if mouse_pos.y >= thumb_y && mouse_pos.y < thumb_y + thumb_height {
                mouse_pos.y - thumb_y
            } else {
                thumb_height * 0.5
            };
    }
    if shell.dragging_scrollbar {
        if mouse_down {
            let target_thumb_top = mouse_pos.y - shell.scrollbar_drag_grab_offset;
            let max_thumb_top = scrollbar_track_height - thumb_height;
            let normalized = if max_thumb_top > 0.0 {
                ((target_thumb_top - scrollbar_track_y) / max_thumb_top).clamp(0.0, 1.0)
            } else {
                0.0
            };
            shell.scroll_offset = normalized * max_scroll;
        } else {
            shell.dragging_scrollbar = false;
        }
    }

    shell.scroll_offset = shell.scroll_offset.clamp(0.0, max_scroll);

    if output_height > 0.0 {
        let mut y_pos = output_top - shell.scroll_offset;
        for line in &shell.output {
            let color = if line.is_command {
                command_color
            } else {
                output_color
            };

            let segments: Vec<&str> = if line.text.is_empty() {
                vec![""]
            } else {
                line.text.split('\n').collect()
            };

            for text_line in segments {
                if y_pos + line_height > output_top && y_pos < output_bottom {
                    ui.draw_overlay_text(
                        text_line,
                        Vec2::new(padding, y_pos),
                        crate::ecs::text::components::TextProperties {
                            font_size,
                            color,
                            vertical_alignment: VerticalAlignment::Top,
                            line_height: line_height_ratio,
                            ..Default::default()
                        },
                        Some(output_clip),
                        UiLayer::Tooltips,
                        2,
                    );
                }
                y_pos += line_height;
            }
        }
    }

    if scrollbar_visible {
        ui.draw_overlay_rect(crate::render::wgpu::passes::geometry::UiRect {
            position: Vec2::new(scrollbar_x, scrollbar_track_y),
            size: Vec2::new(scrollbar_width, scrollbar_track_height),
            color: Vec4::new(0.12, 0.12, 0.14, 0.6),
            corner_radius: scrollbar_width * 0.5,
            border_width: 0.0,
            border_color: transparent,
            rotation: 0.0,
            clip_rect: Some(panel_clip),
            layer: UiLayer::Tooltips,
            z_index: 3,
            shadow: None,
            effect_kind: 0,
            effect_params: [0.0; 4],
            quad_corners: None,
        });
        let thumb_normalized = if max_scroll > 0.0 {
            shell.scroll_offset / max_scroll
        } else {
            0.0
        };
        let thumb_y =
            scrollbar_track_y + thumb_normalized * (scrollbar_track_height - thumb_height);
        let thumb_color = if shell.dragging_scrollbar {
            Vec4::new(0.7, 0.85, 1.0, 0.95)
        } else if scrollbar_track.contains(mouse_pos) && shell.animation_progress > 0.95 {
            Vec4::new(0.55, 0.6, 0.7, 0.95)
        } else {
            Vec4::new(0.4, 0.42, 0.5, 0.85)
        };
        ui.draw_overlay_rect(crate::render::wgpu::passes::geometry::UiRect {
            position: Vec2::new(scrollbar_x, thumb_y),
            size: Vec2::new(scrollbar_width, thumb_height),
            color: thumb_color,
            corner_radius: scrollbar_width * 0.5,
            border_width: 0.0,
            border_color: transparent,
            rotation: 0.0,
            clip_rect: Some(panel_clip),
            layer: UiLayer::Tooltips,
            z_index: 4,
            shadow: None,
            effect_kind: 0,
            effect_params: [0.0; 4],
            quad_corners: None,
        });
    }

    let input_text_height = font_size * line_height_ratio;
    let input_y = current_height - input_height + (input_height - input_text_height) * 0.5;

    ui.draw_overlay_text(
        ">",
        Vec2::new(padding, input_y),
        crate::ecs::text::components::TextProperties {
            font_size,
            color: header_color,
            vertical_alignment: VerticalAlignment::Top,
            line_height: line_height_ratio,
            ..Default::default()
        },
        Some(panel_clip),
        UiLayer::Tooltips,
        2,
    );

    let cursor = if shell.visible && shell.animation_progress > 0.9 {
        "_"
    } else {
        ""
    };
    let input_display = format!("{}{}", shell.input_buffer, cursor);
    ui.draw_overlay_text(
        &input_display,
        Vec2::new(padding + font_size + 4.0, input_y),
        crate::ecs::text::components::TextProperties {
            font_size,
            color: output_color,
            vertical_alignment: VerticalAlignment::Top,
            line_height: line_height_ratio,
            ..Default::default()
        },
        Some(panel_clip),
        UiLayer::Tooltips,
        2,
    );

    ui.draw_overlay_rect(crate::render::wgpu::passes::geometry::UiRect {
        position: Vec2::new(0.0, current_height - 2.0),
        size: Vec2::new(screen_width, 2.0),
        color: border_color,
        corner_radius: 0.0,
        border_width: 0.0,
        border_color: transparent,
        rotation: 0.0,
        clip_rect: Some(panel_clip),
        layer: UiLayer::Tooltips,
        z_index: 3,
        shadow: None,
        effect_kind: 0,
        effect_params: [0.0; 4],
        quad_corners: None,
    });

    if shell.animation_progress > 0.95 {
        let handle_color = if shell.dragging_resize || mouse_in_resize {
            Vec4::new(0.6, 0.8, 1.0, 1.0)
        } else {
            Vec4::new(0.5, 0.5, 0.55, 0.8)
        };
        let handle_width = 40.0;
        let handle_height_px = 3.0;
        ui.draw_overlay_rect(crate::render::wgpu::passes::geometry::UiRect {
            position: Vec2::new((screen_width - handle_width) * 0.5, current_height + 4.0),
            size: Vec2::new(handle_width, handle_height_px),
            color: handle_color,
            corner_radius: 1.5,
            border_width: 0.0,
            border_color: transparent,
            rotation: 0.0,
            clip_rect: None,
            layer: UiLayer::Tooltips,
            z_index: 10,
            shadow: None,
            effect_kind: 0,
            effect_params: [0.0; 4],
            quad_corners: None,
        });
    }

    if shell.visible && shell.animation_progress > 0.9 {
        if shell.pending_enter {
            shell.pending_enter = false;
            shell.execute_command(world);
        }

        if shell.pending_up {
            shell.pending_up = false;
            shell.history_up();
        }

        if shell.pending_down {
            shell.pending_down = false;
            shell.history_down();
        }

        if shell.pending_escape {
            shell.pending_escape = false;
            shell.visible = false;
        }
    }
}
