use crate::gui::SoundpadGui;
use egui::{
    Align, AtomExt, Button, CollapsingHeader, Color32, ComboBox, CursorIcon, FontFamily, Label,
    Layout, RichText, ScrollArea, Sense, Slider, TextEdit, Ui, Vec2,
};
use egui_dnd::dnd;
use egui_extras::{Column, TableBuilder};
use egui_material_icons::icons::*;
use pwsp::types::socket::Request;
use pwsp::types::{audio_player::TrackInfo, gui::AppState};
use pwsp::utils::gui::{format_time_pair, make_request_async};
use std::{
    path::{Path, PathBuf},
    time::Instant,
};

enum TrackAction {
    Pause(u32),
    Resume(u32),
    ToggleLoop(u32),
    Stop(u32),
}

enum HotkeyAction {
    Remove(String),
    Capture(String),
    ClearChord(String),
    Play(String),
}

impl SoundpadGui {
    fn get_volume_icon(volume: f32) -> &'static str {
        if volume > 0.7 {
            ICON_VOLUME_UP.codepoint
        } else if volume <= 0.0 {
            ICON_VOLUME_OFF.codepoint
        } else if volume < 0.3 {
            ICON_VOLUME_MUTE.codepoint
        } else {
            ICON_VOLUME_DOWN.codepoint
        }
    }

    pub fn draw(&mut self, ui: &mut Ui) {
        self.draw_header(ui);
        self.draw_body(ui);
        ui.separator();
        self.draw_footer(ui);
    }

    pub fn draw_waiting_for_daemon(&mut self, ui: &mut Ui) {
        ui.centered_and_justified(|ui| {
            ui.label(
                RichText::new("Waiting for PWSP daemon to start...")
                    .size(34.0)
                    .monospace(),
            );
        });
    }

    pub fn draw_hotkey_capture(&mut self, ui: &mut Ui) {
        ui.vertical_centered(|ui| {
            ui.add_space(ui.available_height() / 3.0);
            ui.label(
                RichText::new("Press a key combination (e.g. Ctrl+Alt+1)")
                    .size(18.0)
                    .color(Color32::YELLOW)
                    .monospace(),
            );
            ui.add_space(10.0);
            let target = if let Some(slot) = &self.app_state.assigning_hotkey_slot {
                format!("for slot '{}'", slot)
            } else if let Some(path) = &self.app_state.assigning_hotkey_for_file {
                format!(
                    "for '{}'",
                    path.file_name().unwrap_or_default().to_string_lossy()
                )
            } else {
                String::new()
            };
            ui.label(RichText::new(target).size(16.0));
            ui.add_space(10.0);
            ui.label("Press Escape to cancel");
        });
    }

    pub fn draw_settings(&mut self, ui: &mut Ui) {
        ui.vertical(|ui| {
            ui.spacing_mut().item_spacing.y = 5.0;
            // --------- Back Button and Title ----------
            ui.horizontal_top(|ui| {
                let back_button = Button::new(ICON_ARROW_BACK).frame(false);
                let back_button_response = ui.add(back_button);
                if back_button_response.clicked() {
                    self.app_state.show_settings = false;
                }

                ui.add_space(ui.available_width() / 2.0 - 40.0);

                ui.label(RichText::new("Settings").color(Color32::WHITE).monospace());
            });
            // --------------------------------

            ui.separator();
            ui.add_space(20.0);

            // --------- Checkboxes ----------
            let save_volume_response =
                ui.checkbox(&mut self.config.save_volume, "Always remember volume");
            let save_input_response =
                ui.checkbox(&mut self.config.save_input, "Always remember microphone");
            let save_scale_response = ui.checkbox(
                &mut self.config.save_scale_factor,
                "Always remember UI scale factor",
            );
            let pause_on_exit_response = ui.checkbox(
                &mut self.config.pause_on_exit,
                "Pause audio playback when the window is closed",
            );

            if save_volume_response.changed()
                || save_input_response.changed()
                || save_scale_response.changed()
                || pause_on_exit_response.changed()
            {
                self.config.save_to_file().ok();
            }
            // --------------------------------

            ui.with_layout(Layout::bottom_up(Align::Min), |ui| {
                ui.label(format!("GUI version: {}", env!("CARGO_PKG_VERSION")));
            });
        });
    }

    pub fn draw_hotkeys(&mut self, ui: &mut Ui) {
        ui.vertical(|ui| {
            ui.spacing_mut().item_spacing.y = 5.0;

            // --- Header ---
            ui.horizontal(|ui| {
                let back_button = Button::new(ICON_ARROW_BACK).frame(false);
                if ui.add(back_button).clicked() {
                    self.app_state.show_hotkeys = false;
                }

                ui.vertical_centered(|ui| {
                    ui.label(RichText::new("Hotkeys").color(Color32::WHITE).monospace());
                });
            });

            ui.separator();

            // --- Search and Add Command ---
            ui.horizontal(|ui| {
                ui.menu_button(format!("{} Add Command", ICON_ADD.codepoint), |ui| {
                    let mut selected_cmd = None;
                    if ui.button("Toggle Pause").clicked() {
                        selected_cmd = Some(("cmd_toggle_pause", Request::toggle_pause(None)));
                    }
                    if ui.button("Stop Playback").clicked() {
                        selected_cmd = Some(("cmd_stop", Request::stop(None)));
                    }
                    if ui.button("Pause Playback").clicked() {
                        selected_cmd = Some(("cmd_pause", Request::pause(None)));
                    }
                    if ui.button("Resume Playback").clicked() {
                        selected_cmd = Some(("cmd_resume", Request::resume(None)));
                    }
                    if ui.button("Toggle Loop").clicked() {
                        selected_cmd = Some(("cmd_toggle_loop", Request::toggle_loop(None)));
                    }

                    if let Some((slot_name, req)) = selected_cmd {
                        make_request_async(Request::set_hotkey_action(slot_name, &req));
                        self.app_state
                            .hotkey_config
                            .set_slot(slot_name.to_string(), req);
                        self.app_state.assigning_hotkey_slot = Some(slot_name.to_string());
                        self.app_state.hotkey_capture_active = true;
                        ui.close();
                    }
                });

                ui.add_space(10.0);

                ui.add(
                    TextEdit::singleline(&mut self.app_state.hotkey_search_query)
                        .hint_text("Search hotkeys...")
                        .desired_width(f32::INFINITY),
                );
            });

            ui.separator();
            ui.add_space(5.0);

            let conflicts = self.app_state.hotkey_config.find_conflicts();
            let conflict_slots: std::collections::HashSet<&str> =
                conflicts.into_iter().flat_map(|(a, b)| [a, b]).collect();

            let search = self.app_state.hotkey_search_query.to_lowercase();
            let mut action: Option<HotkeyAction> = None;

            let slots: Vec<_> = self
                .app_state
                .hotkey_config
                .slots
                .iter()
                .filter(|s| {
                    if search.is_empty() {
                        return true;
                    }
                    s.slot.to_lowercase().contains(&search)
                        || format!("{:?}", s.action).to_lowercase().contains(&search)
                        || s.key_chord
                            .as_deref()
                            .unwrap_or("")
                            .to_lowercase()
                            .contains(&search)
                })
                .cloned()
                .collect();

            let available_width = ui.available_width();
            let col_width = (available_width / 4.0).max(80.0);

            TableBuilder::new(ui)
                .striped(true)
                .column(Column::exact(col_width).clip(true)) // Slot
                .column(Column::exact(col_width).clip(true)) // Sound / Action name
                .column(Column::exact(col_width).clip(true)) // Key Chord
                .column(Column::exact(col_width).clip(true)) // Actions
                .header(30.0, |mut header| {
                    header.col(|ui| {
                        ui.label(
                            RichText::new("Slot")
                                .strong()
                                .monospace()
                                .color(Color32::LIGHT_GRAY),
                        );
                    });
                    header.col(|ui| {
                        ui.label(
                            RichText::new("Sound")
                                .strong()
                                .monospace()
                                .color(Color32::LIGHT_GRAY),
                        );
                    });
                    header.col(|ui| {
                        ui.label(
                            RichText::new("Key Chord")
                                .strong()
                                .monospace()
                                .color(Color32::LIGHT_GRAY),
                        );
                    });
                    header.col(|ui| {
                        ui.label(
                            RichText::new("Actions")
                                .strong()
                                .monospace()
                                .color(Color32::LIGHT_GRAY),
                        );
                    });
                })
                .body(|mut body| {
                    if slots.is_empty() {
                        body.row(30.0, |mut row| {
                            row.col(|_| {});
                            row.col(|ui| {
                                ui.label(
                                    RichText::new("No hotkey slots configured.")
                                        .color(Color32::GRAY),
                                );
                            });
                            row.col(|_| {});
                            row.col(|_| {});
                        });
                        return;
                    }

                    for slot in &slots {
                        body.row(30.0, |mut row| {
                            // Column 1: Slot
                            row.col(|ui| {
                                ui.horizontal(|ui| {
                                    if conflict_slots.contains(slot.slot.as_str()) {
                                        ui.label(
                                            RichText::new(ICON_WARNING.codepoint)
                                                .color(Color32::from_rgb(255, 165, 0)),
                                        )
                                        .on_hover_text("Key chord conflict");
                                    }
                                    ui.add(
                                        Label::new(RichText::new(&slot.slot).monospace())
                                            .truncate(),
                                    );
                                });
                            });

                            // Column 2: Sound / Action name
                            row.col(|ui| {
                                let action_name = match slot.action.name.as_str() {
                                    "play" => {
                                        if let Some(file_path_str) =
                                            slot.action.args.get("file_path")
                                        {
                                            Path::new(file_path_str)
                                                .file_name()
                                                .unwrap_or_default()
                                                .to_string_lossy()
                                                .to_string()
                                        } else {
                                            "Play".to_string()
                                        }
                                    }
                                    "toggle_pause" => "Toggle Pause".to_string(),
                                    "pause" => "Pause Playback".to_string(),
                                    "resume" => "Resume Playback".to_string(),
                                    "stop" => "Stop Playback".to_string(),
                                    "toggle_loop" => "Toggle Loop".to_string(),
                                    other => other.to_string(),
                                };
                                ui.add(
                                    Label::new(RichText::new(action_name).monospace()).truncate(),
                                );
                            });

                            // Column 3: Key Chord
                            row.col(|ui| {
                                let chord_text = slot.key_chord.as_deref().unwrap_or("(none)");
                                ui.add(
                                    Label::new(RichText::new(chord_text).monospace().color(
                                        if slot.key_chord.is_some() {
                                            Color32::from_rgb(100, 200, 100)
                                        } else {
                                            Color32::GRAY
                                        },
                                    ))
                                    .truncate(),
                                );
                            });

                            // Column 4: Actions
                            row.col(|ui| {
                                ui.horizontal(|ui| {
                                    if ui
                                        .add(Button::new(ICON_DELETE).frame(false))
                                        .on_hover_text("Remove slot")
                                        .clicked()
                                    {
                                        action = Some(HotkeyAction::Remove(slot.slot.clone()));
                                    }
                                    if ui
                                        .add(Button::new(ICON_KEYBOARD).frame(false))
                                        .on_hover_text("Set key chord")
                                        .clicked()
                                    {
                                        action = Some(HotkeyAction::Capture(slot.slot.clone()));
                                    }
                                    if slot.key_chord.is_some()
                                        && ui
                                            .add(Button::new(ICON_BACKSPACE).frame(false))
                                            .on_hover_text("Clear key chord")
                                            .clicked()
                                    {
                                        action = Some(HotkeyAction::ClearChord(slot.slot.clone()));
                                    }
                                    if ui
                                        .add(Button::new(ICON_PLAY_ARROW).frame(false))
                                        .on_hover_text("Play")
                                        .clicked()
                                    {
                                        action = Some(HotkeyAction::Play(slot.slot.clone()));
                                    }
                                });
                            });
                        });
                    }
                });

            if let Some(action) = action {
                match action {
                    HotkeyAction::Remove(slot) => {
                        make_request_async(Request::clear_hotkey(&slot));
                        self.app_state.hotkey_config.remove_slot(&slot);
                    }
                    HotkeyAction::Capture(slot) => {
                        self.app_state.assigning_hotkey_slot = Some(slot);
                        self.app_state.hotkey_capture_active = true;
                    }
                    HotkeyAction::ClearChord(slot) => {
                        make_request_async(Request::clear_hotkey_key(&slot));
                        self.app_state.hotkey_config.set_key_chord(&slot, None);
                    }
                    HotkeyAction::Play(slot) => {
                        self.play_hotkey_slot(&slot);
                    }
                }
            }
        });
    }

    fn draw_header(&mut self, ui: &mut Ui) {
        ui.vertical_centered_justified(|ui| {
            if self.audio_player_state.tracks.is_empty() {
                ui.label("No tracks playing");
                return;
            }

            let tracks = self.audio_player_state.tracks.clone();
            let mut action = None;

            for track in tracks {
                CollapsingHeader::new(
                    RichText::new(
                        track
                            .path
                            .file_stem()
                            .unwrap_or_default()
                            .to_str()
                            .unwrap_or_default(),
                    )
                    .color(Color32::WHITE)
                    .family(FontFamily::Monospace),
                )
                .default_open(true)
                .show(ui, |ui| {
                    if let Some(act) = Self::draw_track_control(ui, &mut self.app_state, &track) {
                        action = Some(act);
                    }
                });
                ui.separator();
            }

            if let Some(action) = action {
                match action {
                    TrackAction::Pause(id) => self.pause(Some(id)),
                    TrackAction::Resume(id) => self.resume(Some(id)),
                    TrackAction::ToggleLoop(id) => self.toggle_loop(Some(id)),
                    TrackAction::Stop(id) => self.stop(Some(id)),
                }
            }
        });
    }

    fn draw_track_control(
        ui: &mut Ui,
        app_state: &mut AppState,
        track: &TrackInfo,
    ) -> Option<TrackAction> {
        let ui_state = app_state.track_ui_states.entry(track.id).or_default();

        let should_update_position = !ui_state.position_dragged
            && ui_state
                .ignore_position_update_until
                .map(|t| Instant::now() > t)
                .unwrap_or(true);

        if should_update_position {
            ui_state.position_slider_value = track.position;
        }

        let should_update_volume = !ui_state.volume_dragged
            && ui_state
                .ignore_volume_update_until
                .map(|t| Instant::now() > t)
                .unwrap_or(true);

        if should_update_volume {
            ui_state.volume_slider_value = track.volume;
        }

        let mut action = None;

        ui.horizontal_top(|ui| {
            // ---------- Play Button ----------
            let play_button = Button::new(if track.paused {
                ICON_PLAY_ARROW
            } else {
                ICON_PAUSE
            })
            .corner_radius(15.0);

            let play_button_response = ui.add_sized([30.0, 30.0], play_button);
            if play_button_response.clicked() {
                if track.paused {
                    action = Some(TrackAction::Resume(track.id));
                } else {
                    action = Some(TrackAction::Pause(track.id));
                }
            }
            // --------------------------------

            // ---------- Loop Button ----------
            let loop_button = Button::new(
                RichText::new(if track.looped {
                    ICON_REPEAT_ONE
                } else {
                    ICON_REPEAT
                })
                .size(18.0),
            )
            .frame(false);

            let loop_button_response = ui.add_sized([15.0, 30.0], loop_button);
            if loop_button_response.clicked() {
                action = Some(TrackAction::ToggleLoop(track.id));
            }
            // --------------------------------

            // ---------- Position Slider ----------
            let duration = track.duration.unwrap_or(1.0);
            let position_slider = Slider::new(&mut ui_state.position_slider_value, 0.0..=duration)
                .show_value(false)
                .step_by(0.01);

            let default_slider_width = ui.spacing().slider_width;
            let position_slider_width = ui.available_width()
                - (30.0 * 3.0)
                - default_slider_width
                - (ui.spacing().item_spacing.x * 6.0);
            ui.spacing_mut().slider_width = position_slider_width;
            let position_slider_response = ui.add_sized([30.0, 30.0], position_slider);
            if position_slider_response.drag_stopped() {
                ui_state.position_dragged = true;
            }
            // --------------------------------

            // ---------- Time Label ----------
            let time_label =
                Label::new(RichText::new(format_time_pair(track.position, duration)).monospace());
            ui.add_sized([30.0, 30.0], time_label);
            // --------------------------------

            // ---------- Volume Icon ----------
            let volume_icon = Self::get_volume_icon(track.volume);
            let volume_label = Label::new(RichText::new(volume_icon).size(18.0));
            ui.add_sized([30.0, 30.0], volume_label)
                .on_hover_text(format!("Volume: {:.0}%", track.volume * 100.0));
            // --------------------------------

            // ---------- Volume Slider ----------
            let volume_slider = Slider::new(&mut ui_state.volume_slider_value, 0.0..=1.0)
                .show_value(false)
                .step_by(0.01);

            ui.spacing_mut().slider_width = default_slider_width - 30.0;
            ui.spacing_mut().item_spacing.x = 0.0;

            let volume_slider_response = ui.add_sized([30.0, 30.0], volume_slider);
            if volume_slider_response.drag_stopped() {
                ui_state.volume_dragged = true;
            }
            // --------------------------------

            // ---------- Stop Button ---------
            let stop_button = Button::new(ICON_CLOSE).frame(false);
            let stop_button_response = ui.add_sized([30.0, 30.0], stop_button);
            if stop_button_response.clicked() {
                action = Some(TrackAction::Stop(track.id));
            }
            // --------------------------------
        });

        action
    }

    fn draw_body(&mut self, ui: &mut Ui) {
        let left_panel_width = self
            .config
            .left_panel_width
            .max(100.0)
            .min(ui.available_width() - 100.0);
        let dirs_size = Vec2::new(left_panel_width, ui.available_height() - 40.0);

        ui.horizontal(|ui| {
            self.draw_dirs(ui, dirs_size);

            let (rect, response) = ui.allocate_at_least(
                Vec2::new(ui.spacing().item_spacing.x, ui.available_height()),
                Sense::click_and_drag(),
            );

            if ui.is_rect_visible(rect) {
                let stroke = ui.visuals().widgets.noninteractive.bg_stroke;
                ui.painter().vline(rect.center().x, rect.y_range(), stroke);
            }

            let vertical_separator_response =
                response.on_hover_and_drag_cursor(CursorIcon::ResizeHorizontal);

            if vertical_separator_response.dragged() {
                self.config.left_panel_width += vertical_separator_response.drag_delta().x;
                self.config.left_panel_width = self.config.left_panel_width.clamp(100.0, 500.0);
            }

            if vertical_separator_response.drag_stopped() {
                self.config.save_to_file().ok();
            }

            let files_size = Vec2::new(ui.available_width(), ui.available_height() - 40.0);
            self.draw_files(ui, files_size);
        });
    }

    fn draw_dirs(&mut self, ui: &mut Ui, area_size: Vec2) {
        ui.vertical(|ui| {
            ui.set_min_width(area_size.x);
            ui.set_min_height(area_size.y);

            ScrollArea::vertical().id_salt(0).show(ui, |ui| {
                ui.set_min_width(area_size.x);

                let mut dirs = self.app_state.dirs.clone();

                dnd(ui, "dnd_directories").show_vec(&mut dirs, |ui, item, handle, _state| {
                    let path = item.clone();
                    ui.horizontal(|ui| {
                        handle.ui(ui, |ui| {
                            ui.label(ICON_DRAG_INDICATOR.codepoint);
                        });
                        let name = path
                            .file_name()
                            .map(|s| s.to_string_lossy().to_string())
                            .unwrap_or_else(|| path.to_string_lossy().to_string());

                        let mut dir_button_text = RichText::new(name.clone());
                        if let Some(current_dir) = &self.app_state.current_dir
                            && current_dir.eq(&path)
                        {
                            dir_button_text = dir_button_text.color(Color32::WHITE);
                        }

                        let dir_button =
                            Button::new(dir_button_text.atom_max_width(area_size.x)).frame(false);

                        let dir_button_response = ui.add(dir_button);
                        if dir_button_response.clicked() {
                            self.open_dir(&path);
                        }

                        let delete_dir_button = Button::new(ICON_DELETE).frame(false);
                        let delete_dir_button_response =
                            ui.add_sized([18.0, 18.0], delete_dir_button);
                        if delete_dir_button_response.clicked() {
                            self.app_state.dirs_to_remove.insert(path.clone());
                        }

                        // Context menu
                        dir_button_response.context_menu(|ui| {
                            if ui
                                .button(format!("{} {}", ICON_OPEN_IN_NEW.codepoint, "Show"))
                                .clicked()
                            {
                                self.open_dir(&path);
                            }

                            if ui
                                .button(format!(
                                    "{} {}",
                                    ICON_OPEN_IN_BROWSER.codepoint, "Open in File Manager"
                                ))
                                .clicked()
                                && let Err(e) = opener::open(&path)
                            {
                                eprintln!("Failed to open file manager: {}", e);
                            }

                            ui.separator();

                            if ui
                                .button(format!("{} {}", ICON_DELETE.codepoint, "Remove"))
                                .clicked()
                            {
                                self.app_state.dirs_to_remove.insert(path.clone());
                            }
                        });
                    });
                });
                self.app_state.dirs = dirs;

                ui.horizontal(|ui| {
                    let add_dirs_button = Button::new(ICON_ADD).frame(false);
                    let add_dirs_button_response = ui.add_sized([18.0, 18.0], add_dirs_button);
                    if add_dirs_button_response.clicked() {
                        self.add_dirs();
                    }
                });

                ui.with_layout(Layout::bottom_up(Align::Min), |ui| {
                    let play_file_button = Button::new("Play file");
                    let play_file_button_response = ui.add(play_file_button);
                    if play_file_button_response.clicked() {
                        self.open_file();
                    }
                });
            });
        });
    }

    fn draw_files(&mut self, ui: &mut Ui, area_size: Vec2) {
        ui.vertical(|ui| {
            ui.horizontal(|ui| {
                let search_field_response = ui.add_sized(
                    [ui.available_width(), 22.0],
                    TextEdit::singleline(&mut self.app_state.search_query).hint_text("Search..."),
                );

                if self.app_state.force_focus_search {
                    search_field_response.request_focus();
                    self.app_state.force_focus_search = false;
                }

                self.app_state.search_field_id = Some(search_field_response.id);
            });

            ui.separator();

            ScrollArea::vertical().id_salt(1).show(ui, |ui| {
                ui.set_min_width(area_size.x);
                ui.set_min_height(area_size.y);

                ui.vertical(|ui| {
                    let files = self.get_filtered_files();

                    for entry_path in files {
                        let file_name = entry_path
                            .file_name()
                            .unwrap_or_default()
                            .to_string_lossy()
                            .to_string();

                        ui.horizontal(|ui| {
                            // Hotkey badge
                            let hotkey_badge = self.get_hotkey_badge(&entry_path);
                            if let Some(badge) = &hotkey_badge {
                                ui.label(
                                    RichText::new(badge)
                                        .small()
                                        .monospace()
                                        .color(Color32::from_rgb(100, 200, 100)),
                                );
                            }

                            let mut file_button_text = RichText::new(&file_name);
                            if let Some(current_file) = &self.app_state.selected_file
                                && current_file.eq(&entry_path)
                            {
                                file_button_text = file_button_text.color(Color32::WHITE);
                            }

                            let file_button = Button::new(file_button_text).frame(false).truncate();
                            let file_button_response = ui.add(file_button);
                            if file_button_response.clicked() {
                                ui.input(|i| {
                                    if i.modifiers.ctrl {
                                        self.play_file(&entry_path, true);
                                    } else if i.modifiers.shift
                                        && let Some(last_track) =
                                            self.audio_player_state.tracks.last()
                                    {
                                        self.stop(Some(last_track.id));
                                        self.play_file(&entry_path, true);
                                    } else {
                                        self.play_file(&entry_path, false);
                                    }
                                });
                                self.app_state.selected_file = Some(entry_path.clone());
                            }

                            // Context menu
                            file_button_response.context_menu(|ui| {
                                if ui
                                    .button(format!("{} {}", ICON_BOLT.codepoint, "Play Solo"))
                                    .clicked()
                                {
                                    self.play_file(&entry_path, false);
                                    self.app_state.selected_file = Some(entry_path.clone());
                                }

                                if ui
                                    .button(format!("{} {}", ICON_ADD.codepoint, "Add New"))
                                    .clicked()
                                {
                                    self.play_file(&entry_path, true);
                                    self.app_state.selected_file = Some(entry_path.clone());
                                }

                                if ui
                                    .button(format!(
                                        "{} {}",
                                        ICON_SWAP_HORIZ.codepoint, "Replace Last"
                                    ))
                                    .clicked()
                                    && let Some(last_track) = self.audio_player_state.tracks.last()
                                {
                                    self.stop(Some(last_track.id));
                                    self.play_file(&entry_path, true);
                                    self.app_state.selected_file = Some(entry_path.clone());
                                }

                                ui.separator();

                                if ui
                                    .button(format!(
                                        "{} {}",
                                        ICON_OPEN_IN_BROWSER.codepoint, "Show in File Manager"
                                    ))
                                    .clicked()
                                    && let Err(e) = opener::reveal(&entry_path)
                                {
                                    eprintln!("Failed to open file manager: {}", e);
                                }

                                ui.separator();

                                if ui
                                    .button(format!(
                                        "{} {}",
                                        ICON_KEYBOARD.codepoint, "Assign Hotkey"
                                    ))
                                    .clicked()
                                {
                                    self.app_state.assigning_hotkey_for_file =
                                        Some(entry_path.clone());
                                    self.app_state.hotkey_capture_active = true;
                                    ui.close();
                                }
                            });
                        });
                    }
                });
            });
        });
    }

    fn get_hotkey_badge(&self, path: &PathBuf) -> Option<String> {
        for slot in &self.app_state.hotkey_config.slots {
            if slot.action.name == "play"
                && let Some(file_path_str) = slot.action.args.get("file_path")
                && Path::new(file_path_str) == path.as_path()
            {
                if let Some(chord) = &slot.key_chord {
                    return Some(format!("[{}]", chord));
                } else {
                    return Some(format!("[{}]", slot.slot));
                }
            }
        }
        None
    }

    fn draw_footer(&mut self, ui: &mut Ui) {
        ui.add_space(5.0);
        ui.horizontal(|ui| {
            // ---------- Microphone selection ----------
            let mics = &self.audio_player_state.all_inputs_sorted;

            let mut selected_input = self.audio_player_state.current_input.to_owned();
            let prev_input = selected_input.to_owned();
            ComboBox::from_label("Choose microphone")
                .height(30.0)
                .selected_text(
                    self.audio_player_state
                        .all_inputs
                        .get(&selected_input)
                        .unwrap_or(&String::new()),
                )
                .show_ui(ui, |ui| {
                    for (name, nick) in mics {
                        ui.selectable_value(&mut selected_input, name.clone(), nick);
                    }
                });

            if selected_input != prev_input {
                self.set_input(selected_input);
            }
            // --------------------------------

            // ---------- Master Volume Slider ----------
            let volume_icon = Self::get_volume_icon(self.audio_player_state.volume);
            let volume_label = Label::new(RichText::new(volume_icon).size(18.0));
            ui.add_sized([18.0, 18.0], volume_label)
                .on_hover_text(format!(
                    "Master Volume: {:.0}%",
                    self.audio_player_state.volume * 100.0
                ));

            let should_update_volume = !self.app_state.volume_dragged
                && self
                    .app_state
                    .ignore_volume_update_until
                    .map(|t| Instant::now() > t)
                    .unwrap_or(true);

            if should_update_volume {
                self.app_state.volume_slider_value = self.audio_player_state.volume;
            }

            let volume_slider = Slider::new(&mut self.app_state.volume_slider_value, 0.0..=1.0)
                .show_value(false)
                .step_by(0.01);
            let volume_slider_response = ui.add_sized([150.0, 18.0], volume_slider);
            if volume_slider_response.drag_stopped() {
                self.app_state.volume_dragged = true;
            }
            // ------------------------------------------

            ui.add_space(ui.available_width() - 18.0 * 2.0 - ui.spacing().item_spacing.x * 2.0);

            // ---------- Hotkeys button ----------
            let hotkeys_button =
                Button::new(ICON_KEYBOARD.atom_size(Vec2::new(18.0, 18.0))).frame(false);
            let hotkeys_button_response = ui.add_sized([18.0, 18.0], hotkeys_button);
            if hotkeys_button_response.clicked() {
                self.app_state.show_hotkeys = true;
            }
            hotkeys_button_response.on_hover_text("Hotkeys (H)");
            // --------------------------------

            // ---------- Settings button ----------
            let settings_button =
                Button::new(ICON_SETTINGS.atom_size(Vec2::new(18.0, 18.0))).frame(false);
            let settings_button_response = ui.add_sized([18.0, 18.0], settings_button);
            if settings_button_response.clicked() {
                self.app_state.show_settings = true;
            }
            // --------------------------------
        });
    }
}
