use anyhow::Result;
use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
use std::sync::mpsc::Sender;

use crate::app::{App, SubmitAction};
use crate::tui::events::common::{
    copy_to_clipboard, pasted_images_dir, read_from_clipboard, read_image_from_clipboard,
    uuid_or_timestamp,
};
use crate::tui::{
    WorkerEvent, handle_function_action, spawn_generation_worker, spawn_models_worker,
};

pub(crate) fn handle_chat_key(
    app: &mut App,
    sender: &Sender<WorkerEvent>,
    key: KeyEvent,
) -> Result<()> {
    if app.ui.show_trust_modal {
        return handle_trust_modal_key(app, key);
    }

    if matches!(
        app.proc.pending,
        Some(crate::app::PendingTask::ConfirmFunction { .. })
    ) {
        if app
            .core
            .keybindings
            .matches(crate::tui::keybindings::TuiAction::Quit, key)
        {
            app.should_quit = true;
            return Ok(());
        }
        match key.code {
            KeyCode::Char('y') | KeyCode::Char('Y') => {
                if let Some(action) = app.answer_function_confirmation(true) {
                    handle_function_action(action, sender);
                }
            }
            KeyCode::Char('n') | KeyCode::Char('N') => {
                if let Some(action) = app.answer_function_confirmation(false) {
                    handle_function_action(action, sender);
                }
            }
            KeyCode::Char('j') | KeyCode::Down => {
                app.ui
                    .confirm_scroll
                    .set(app.ui.confirm_scroll.get().saturating_add(1));
            }
            KeyCode::Char('k') | KeyCode::Up => {
                app.ui
                    .confirm_scroll
                    .set(app.ui.confirm_scroll.get().saturating_sub(1));
            }
            KeyCode::PageDown => {
                app.ui
                    .confirm_scroll
                    .set(app.ui.confirm_scroll.get().saturating_add(10));
            }
            KeyCode::PageUp => {
                app.ui
                    .confirm_scroll
                    .set(app.ui.confirm_scroll.get().saturating_sub(10));
            }
            _ => {
                if app
                    .core
                    .keybindings
                    .matches(crate::tui::keybindings::TuiAction::Cancel, key)
                    && let Some(action) = app.answer_function_confirmation(false)
                {
                    handle_function_action(action, sender);
                }
            }
        }
        return Ok(());
    }

    if app.ui.model_picker_open {
        return handle_model_picker_key(app, key);
    }

    if app.ui.theme_picker_open {
        return handle_theme_picker_key(app, key);
    }

    if app.ui.agent_picker_open {
        return handle_agent_picker_key(app, key);
    }

    if app.chat.shell_focused {
        let is_ctrl_c = (key.code == KeyCode::Char('c')
            && key.modifiers.contains(KeyModifiers::CONTROL))
            || app
                .core
                .keybindings
                .matches(crate::tui::keybindings::TuiAction::Quit, key);
        let is_esc = app
            .core
            .keybindings
            .matches(crate::tui::keybindings::TuiAction::Cancel, key);

        if is_ctrl_c || is_esc {
            handle_interrupt_signal(app);
            return Ok(());
        }

        if key.code == KeyCode::Tab {
            app.chat.shell_focused = false;
            for m in &mut app.chat.messages {
                if m.is_shell {
                    *m.cached_wrapped.borrow_mut() = None;
                }
            }
            app.status = "Ready".to_owned();
            return Ok(());
        }

        if app
            .core
            .keybindings
            .matches(crate::tui::keybindings::TuiAction::ScrollUp, key)
        {
            app.chat.scroll = app.chat.scroll.saturating_add(1);
            return Ok(());
        }
        if app
            .core
            .keybindings
            .matches(crate::tui::keybindings::TuiAction::ScrollDown, key)
        {
            app.chat.scroll = app.chat.scroll.saturating_sub(1);
            return Ok(());
        }
        if app
            .core
            .keybindings
            .matches(crate::tui::keybindings::TuiAction::PageUp, key)
        {
            app.chat.scroll = app.chat.scroll.saturating_add(15);
            return Ok(());
        }
        if app
            .core
            .keybindings
            .matches(crate::tui::keybindings::TuiAction::PageDown, key)
        {
            app.chat.scroll = app.chat.scroll.saturating_sub(15);
            return Ok(());
        }

        let mut written = false;
        let mut written_pid = None;

        // 1. Try to write to active persistent session stdin
        let active_session_id = if app.chat.shell_focused {
            app.chat.focused_shell_session_id.clone()
        } else {
            crate::tui::ACTIVE_PERSISTENT_SESSION_ID.lock().clone()
        };

        if let Some(ref session_id) = active_session_id
            && let Some(registry_mutex) = crate::tui::PERSISTENT_SESSIONS.get()
            && let Some(session) = registry_mutex.lock().get_mut(session_id)
        {
            use std::io::Write;
            let data = match key.code {
                KeyCode::Char(c) => Some(c.to_string()),
                KeyCode::Enter => Some("\n".to_owned()),
                KeyCode::Backspace => Some("\x08".to_owned()),
                _ => None,
            };
            if let Some(s) = data {
                let _ = session.stdin.write_all(s.as_bytes());
                let _ = session.stdin.flush();
                written = true;
                written_pid = Some(session.pid);
            }
        }

        // 2. Try to write to non-persistent foreground process stdin
        if !written {
            let mut guard = crate::tui::RUNNING_PROCESS_STDIN.lock();
            if let Some(ref mut stdin) = guard.as_mut() {
                use std::io::Write;
                let data = match key.code {
                    KeyCode::Char(c) => Some(c.to_string()),
                    KeyCode::Enter => Some("\n".to_owned()),
                    KeyCode::Backspace => Some("\x08".to_owned()),
                    _ => None,
                };
                if let Some(s) = data {
                    let _ = stdin.write_all(s.as_bytes());
                    let _ = stdin.flush();
                    written = true;
                    {
                        let pid_guard = crate::tui::RUNNING_PROCESS_PID.lock();
                        written_pid = *pid_guard;
                    }
                }
            }
        }

        // 3. Try to write to non-persistent background process stdin
        if !written
            && app.chat.shell_focused
            && let Some(pid) = app.chat.focused_shell_pid
        {
            let bg_registry = crate::tui::BACKGROUND_PROCESSES.get();
            if let Some(registry_mutex) = bg_registry
                && let Some(proc) = registry_mutex.lock().get_mut(&pid)
                && let Some(ref mut stdin) = proc.stdin
            {
                use std::io::Write;
                let data = match key.code {
                    KeyCode::Char(c) => Some(c.to_string()),
                    KeyCode::Enter => Some("\n".to_owned()),
                    KeyCode::Backspace => Some("\x08".to_owned()),
                    _ => None,
                };
                if let Some(s) = data {
                    let _ = stdin.write_all(s.as_bytes());
                    let _ = stdin.flush();
                    written = true;
                    written_pid = Some(pid);
                }
            }
        }

        if written {
            // Find the shell message line and truncate "\nRunning...\n" if it's there
            let mut found_msg = None;
            if let Some(ref session_id) = active_session_id {
                found_msg = app
                    .chat
                    .messages
                    .iter_mut()
                    .rev()
                    .find(|m| m.is_shell && m.shell_session_id.as_ref() == Some(session_id));
            }
            if found_msg.is_none()
                && let Some(wp) = written_pid
            {
                found_msg = app
                    .chat
                    .messages
                    .iter_mut()
                    .rev()
                    .find(|m| m.is_shell && m.shell_pid == Some(wp));
            }
            if found_msg.is_none() {
                found_msg = app.chat.messages.iter_mut().rev().find(|m| m.is_shell);
            }
            if let Some(msg) = found_msg {
                if msg.text.ends_with("\nRunning...\n") {
                    msg.text.truncate(msg.text.len() - 11);
                }
                match key.code {
                    KeyCode::Char(c) => {
                        msg.text.push(c);
                    }
                    KeyCode::Enter => {
                        msg.text.push('\n');
                    }
                    KeyCode::Backspace => {
                        msg.text.pop();
                    }
                    _ => {}
                }
                *msg.cached_wrapped.borrow_mut() = None;
            }
        }

        return Ok(());
    }

    if app
        .core
        .keybindings
        .matches(crate::tui::keybindings::TuiAction::Quit, key)
    {
        let is_running_process = crate::tui::RUNNING_PROCESS_PID.lock().is_some();
        let is_active_persistent = crate::tui::ACTIVE_PERSISTENT_SESSION_ID.lock().is_some();

        let mut has_running_command_in_history = false;
        for msg in &app.chat.history {
            if msg.role == "function" {
                for part in &msg.parts {
                    if let Some(resp) = part.get("functionResponse")
                        && resp.get("name").and_then(|v| v.as_str()) == Some("sh")
                        && let Some(response_val) = resp.get("response")
                    {
                        let status = response_val.get("status");
                        let error_val = response_val
                            .get("error")
                            .and_then(|v| v.as_str())
                            .unwrap_or("");
                        let is_aborted = error_val.contains("terminated by user")
                            || error_val.contains("Ctrl+C");

                        let is_running = status.and_then(|s| s.as_str()) == Some("running")
                            || error_val == "Command timed out / is still running"
                            || (status.is_none()
                                && !is_aborted
                                && response_val.get("exit_code").is_none());

                        if is_running {
                            has_running_command_in_history = true;
                            break;
                        }
                    }
                }
            }
        }

        if app.proc.pending.is_some()
            || app.chat.focused_shell_pid.is_some()
            || is_running_process
            || is_active_persistent
            || app.proc.cancel_token.is_some()
            || has_running_command_in_history
        {
            handle_interrupt_signal(app);
            return Ok(());
        } else {
            app.should_quit = true;
            return Ok(());
        }
    }

    if app
        .core
        .keybindings
        .matches(crate::tui::keybindings::TuiAction::Cancel, key)
    {
        handle_interrupt_signal(app);
        return Ok(());
    }

    if app
        .core
        .keybindings
        .matches(crate::tui::keybindings::TuiAction::ToggleSetup, key)
    {
        app.open_setup();
        return Ok(());
    }

    if app
        .core
        .keybindings
        .matches(crate::tui::keybindings::TuiAction::ToggleModels, key)
    {
        if let Some(config) = app.begin_load_chat_models() {
            spawn_models_worker(config, sender.clone());
        }
        return Ok(());
    }

    if app
        .core
        .keybindings
        .matches(crate::tui::keybindings::TuiAction::ToggleSessions, key)
    {
        app.open_sessions();
        return Ok(());
    }

    if app
        .core
        .keybindings
        .matches(crate::tui::keybindings::TuiAction::Submit, key)
    {
        if let Some(action) = app.submit_chat_input() {
            match action {
                SubmitAction::Generate(request) => {
                    spawn_generation_worker(
                        request.config,
                        request.history,
                        request.cancel_token,
                        request.generation_id,
                        request.dev_mode,
                        sender.clone(),
                    );
                }
                SubmitAction::LoadModels(config) => {
                    spawn_models_worker(config, sender.clone());
                }
                SubmitAction::ExecuteFunction { name, args, config } => {
                    handle_function_action(
                        crate::app::FunctionAction::Execute { name, args, config },
                        sender,
                    );
                }
            }
        }
        return Ok(());
    }

    if app
        .core
        .keybindings
        .matches(crate::tui::keybindings::TuiAction::ScrollUp, key)
    {
        let suggestions = app.command_suggestions();
        if !suggestions.is_empty() {
            app.chat.suggestion_idx = if app.chat.suggestion_idx == 0 {
                suggestions.len().saturating_sub(1)
            } else {
                app.chat.suggestion_idx - 1
            };
            return Ok(());
        }

        if app.chat.input.contains('\n') {
            let old_cursor = app.chat.cursor;
            app.chat.move_cursor_up();
            if app.chat.cursor == old_cursor {
                app.chat.scroll = app.chat.scroll.saturating_add(1);
            }
        } else {
            app.chat.scroll = app.chat.scroll.saturating_add(1);
        }
        return Ok(());
    }

    if app
        .core
        .keybindings
        .matches(crate::tui::keybindings::TuiAction::ScrollDown, key)
    {
        let suggestions = app.command_suggestions();
        if !suggestions.is_empty() {
            app.chat.suggestion_idx = (app.chat.suggestion_idx + 1) % suggestions.len();
            return Ok(());
        }

        if app.chat.input.contains('\n') {
            let old_cursor = app.chat.cursor;
            app.chat.move_cursor_down();
            if app.chat.cursor == old_cursor {
                app.chat.scroll = app.chat.scroll.saturating_sub(1);
            }
        } else {
            app.chat.scroll = app.chat.scroll.saturating_sub(1);
        }
        return Ok(());
    }

    if app
        .core
        .keybindings
        .matches(crate::tui::keybindings::TuiAction::PageUp, key)
    {
        app.chat.scroll = app.chat.scroll.saturating_add(15);
        return Ok(());
    }

    if app
        .core
        .keybindings
        .matches(crate::tui::keybindings::TuiAction::PageDown, key)
    {
        app.chat.scroll = app.chat.scroll.saturating_sub(15);
        return Ok(());
    }

    if app
        .core
        .keybindings
        .matches(crate::tui::keybindings::TuiAction::HistoryUp, key)
    {
        app.chat.navigate_history_up();
        return Ok(());
    }

    if app
        .core
        .keybindings
        .matches(crate::tui::keybindings::TuiAction::HistoryDown, key)
    {
        app.chat.navigate_history_down();
        return Ok(());
    }

    if app
        .core
        .keybindings
        .matches(crate::tui::keybindings::TuiAction::Paste, key)
    {
        if let Ok(Some(image_bytes)) = read_image_from_clipboard()
            && let Ok(dir) = pasted_images_dir()
        {
            let filename = format!("image_{}.png", uuid_or_timestamp());
            let path = dir.join(&filename);
            if std::fs::write(&path, &image_bytes).is_ok() {
                let ref_str = format!(" @{} ", filename);
                app.chat.insert_text(&ref_str);
                app.status = format!("Pasted image saved to {}", filename);
                return Ok(());
            }
        }
        if let Ok(text) = read_from_clipboard() {
            app.chat.insert_text(&text);
        }
        return Ok(());
    }

    if app
        .core
        .keybindings
        .matches(crate::tui::keybindings::TuiAction::TodoScrollUp, key)
    {
        app.chat.todo_scroll = app.chat.todo_scroll.saturating_sub(1);
        return Ok(());
    }

    if app
        .core
        .keybindings
        .matches(crate::tui::keybindings::TuiAction::TodoScrollDown, key)
    {
        app.chat.todo_scroll = app.chat.todo_scroll.saturating_add(1);
        return Ok(());
    }

    match (key.code, key.modifiers) {
        (KeyCode::Char('z'), KeyModifiers::CONTROL) => {
            app.chat.undo();
        }
        (KeyCode::Char('r'), KeyModifiers::CONTROL) => {
            app.chat.redo();
        }
        (KeyCode::Tab, KeyModifiers::CONTROL) | (KeyCode::Char('t'), KeyModifiers::CONTROL) => {
            app.toggle_dev_mode();
        }
        (KeyCode::Char('k'), KeyModifiers::CONTROL) => {
            let text = app.chat.input.clone();
            if !text.is_empty() {
                if copy_to_clipboard(&text).is_ok() {
                    app.status = "Copied input to clipboard".to_owned();
                }
                app.chat.save_history();
                app.chat.input.clear();
                app.chat.cursor = 0;
                app.chat.input_scroll = 0;
            }
        }
        (KeyCode::Char('l'), KeyModifiers::CONTROL) => {
            let mut last_response = None;
            for msg in app.chat.messages.iter().rev() {
                if msg.author == "Darwin" && !msg.is_tool && !msg.is_shell && !msg.pending {
                    let mut text = msg.text.trim();
                    if text.starts_with("(empty)") {
                        text = text["(empty)".len()..].trim();
                    }
                    let mut clean_text = text.to_owned();
                    if clean_text.starts_with("Thinking...") {
                        clean_text = clean_text["Thinking...".len()..].to_owned();
                    } else if clean_text.starts_with("Thinking:") {
                        if let Some(first_newline_idx) = clean_text.find('\n') {
                            clean_text = clean_text[first_newline_idx + 1..].to_owned();
                        } else {
                            clean_text = clean_text["Thinking:".len()..].to_owned();
                        }
                    } else if clean_text.starts_with("░ Thinking...") {
                        clean_text = clean_text["░ Thinking...".len()..].to_owned();
                    } else if clean_text.starts_with("░ Thinking:") {
                        if let Some(first_newline_idx) = clean_text.find('\n') {
                            clean_text = clean_text[first_newline_idx + 1..].to_owned();
                        } else {
                            clean_text = clean_text["░ Thinking:".len()..].to_owned();
                        }
                    }
                    let final_text = clean_text.trim().to_owned();
                    if !final_text.is_empty() {
                        last_response = Some(final_text);
                        break;
                    }
                }
            }
            if let Some(text) = last_response {
                if copy_to_clipboard(&text).is_ok() {
                    app.status = "Copied last response to clipboard".to_owned();
                }
            } else {
                app.status = "No assistant response to copy".to_owned();
            }
        }
        (KeyCode::Tab, _) => {
            let suggestions = app.command_suggestions();
            if !suggestions.is_empty() {
                app.accept_command_suggestion();
            } else {
                app.chat.shell_focused = !app.chat.shell_focused;
                for m in &mut app.chat.messages {
                    if m.is_shell {
                        *m.cached_wrapped.borrow_mut() = None;
                    }
                }
                if app.chat.shell_focused {
                    let last_shell = app.chat.messages.iter().rev().find(|m| m.is_shell);
                    if let Some(msg) = last_shell {
                        app.chat.focused_shell_session_id = msg.shell_session_id.clone();
                        app.chat.focused_shell_pid = msg.shell_pid;
                    } else {
                        app.chat.focused_shell_session_id = None;
                        app.chat.focused_shell_pid = None;
                    }
                    app.chat.scroll = 0; // Automatically scroll to the bottom to show the last shell block
                    app.status = "Shell/Messages focused. Press Tab to return, or Ctrl+C to abort running command.".to_owned();
                } else {
                    app.chat.focused_shell_session_id = None;
                    app.chat.focused_shell_pid = None;
                    app.status = "Ready".to_owned();
                }
            }
        }
        (KeyCode::Enter, modifiers) if !modifiers.is_empty() => {
            app.chat.insert_char('\n');
        }
        (KeyCode::Backspace, _) => app.chat.remove_char(),
        (KeyCode::Delete, _) => app.chat.delete_char(),
        (KeyCode::Left, _) => app.chat.move_cursor_left(),
        (KeyCode::Right, _) => app.chat.move_cursor_right(),
        (KeyCode::Home, _) => app.chat.move_cursor_start(),
        (KeyCode::End, _) => app.chat.move_cursor_end(),
        (KeyCode::Char(value), modifiers)
            if !modifiers.contains(KeyModifiers::CONTROL)
                && !modifiers.contains(KeyModifiers::ALT) =>
        {
            app.chat.insert_char(value);
        }
        _ => {}
    }

    Ok(())
}

fn handle_model_picker_key(app: &mut App, key: KeyEvent) -> Result<()> {
    if app
        .core
        .keybindings
        .matches(crate::tui::keybindings::TuiAction::Cancel, key)
    {
        app.cancel_models();
        return Ok(());
    }
    if app
        .core
        .keybindings
        .matches(crate::tui::keybindings::TuiAction::ToggleModels, key)
    {
        app.cancel_models();
        return Ok(());
    }

    match key.code {
        KeyCode::Esc => {
            app.cancel_models();
        }
        KeyCode::Enter => {
            app.apply_selected_model();
        }
        KeyCode::Up => {
            app.select_previous_model();
        }
        KeyCode::Down => {
            app.select_next_model();
        }
        KeyCode::PageUp => {
            let len = app.ui.models.filtered_indices().len();
            for _ in 0..5 {
                if len > 0 {
                    app.ui.models.selected =
                        app.ui.models.selected.checked_sub(1).unwrap_or(len - 1);
                }
            }
        }
        KeyCode::PageDown => {
            let len = app.ui.models.filtered_indices().len();
            for _ in 0..5 {
                if len > 0 {
                    app.ui.models.selected = (app.ui.models.selected + 1) % len;
                }
            }
        }
        KeyCode::Backspace => {
            app.ui.models.pop_query();
        }
        KeyCode::Char(c)
            if !key.modifiers.contains(KeyModifiers::CONTROL)
                && !key.modifiers.contains(KeyModifiers::ALT) =>
        {
            app.ui.models.push_query(c);
        }
        _ => {}
    }
    Ok(())
}

fn handle_theme_picker_key(app: &mut App, key: KeyEvent) -> Result<()> {
    if app
        .core
        .keybindings
        .matches(crate::tui::keybindings::TuiAction::Cancel, key)
    {
        app.cancel_themes();
        return Ok(());
    }

    match key.code {
        KeyCode::Esc => {
            app.cancel_themes();
        }
        KeyCode::Enter => {
            app.apply_selected_theme();
        }
        KeyCode::Up => {
            app.select_previous_theme();
        }
        KeyCode::Down => {
            app.select_next_theme();
        }
        KeyCode::PageUp => {
            let len = app.ui.theme_picker.filtered_indices().len();
            for _ in 0..5 {
                if len > 0 {
                    app.ui.theme_picker.selected = app
                        .ui
                        .theme_picker
                        .selected
                        .checked_sub(1)
                        .unwrap_or(len - 1);
                }
            }
        }
        KeyCode::PageDown => {
            let len = app.ui.theme_picker.filtered_indices().len();
            for _ in 0..5 {
                if len > 0 {
                    app.ui.theme_picker.selected = (app.ui.theme_picker.selected + 1) % len;
                }
            }
        }
        KeyCode::Backspace => {
            app.ui.theme_picker.pop_query();
        }
        KeyCode::Char(c)
            if !key.modifiers.contains(KeyModifiers::CONTROL)
                && !key.modifiers.contains(KeyModifiers::ALT) =>
        {
            app.ui.theme_picker.push_query(c);
        }
        _ => {}
    }
    Ok(())
}

fn handle_agent_picker_key(app: &mut App, key: KeyEvent) -> Result<()> {
    if app
        .core
        .keybindings
        .matches(crate::tui::keybindings::TuiAction::Cancel, key)
    {
        app.cancel_agents();
        return Ok(());
    }

    match key.code {
        KeyCode::Esc => {
            app.cancel_agents();
        }
        KeyCode::Enter => {
            app.apply_selected_agent();
        }
        KeyCode::Up => {
            app.select_previous_agent();
        }
        KeyCode::Down => {
            app.select_next_agent();
        }
        KeyCode::PageUp => {
            let len = app.ui.agent_picker.filtered_indices().len();
            for _ in 0..5 {
                if len > 0 {
                    app.ui.agent_picker.selected = app
                        .ui
                        .agent_picker
                        .selected
                        .checked_sub(1)
                        .unwrap_or(len - 1);
                }
            }
        }
        KeyCode::PageDown => {
            let len = app.ui.agent_picker.filtered_indices().len();
            for _ in 0..5 {
                if len > 0 {
                    app.ui.agent_picker.selected = (app.ui.agent_picker.selected + 1) % len;
                }
            }
        }
        KeyCode::Backspace => {
            app.ui.agent_picker.pop_query();
        }
        KeyCode::Char(c)
            if !key.modifiers.contains(KeyModifiers::CONTROL)
                && !key.modifiers.contains(KeyModifiers::ALT) =>
        {
            app.ui.agent_picker.push_query(c);
        }
        _ => {}
    }
    Ok(())
}

fn handle_interrupt_signal(app: &mut App) {
    app.cancel_generation();

    let mut target_pid = {
        let mut guard = crate::tui::RUNNING_PROCESS_PID.lock();
        guard.take()
    };
    if target_pid.is_none() {
        target_pid = app.chat.focused_shell_pid;
    }
    let mut target_session_id = None;

    if let Some(ref session_id) = app.chat.focused_shell_session_id {
        target_session_id = Some(session_id.clone());
    } else if let Some(session_id) = crate::tui::ACTIVE_PERSISTENT_SESSION_ID.lock().as_ref() {
        target_session_id = Some(session_id.clone());
    }

    let mut history_target = None;
    for i in (0..app.chat.history.len()).rev() {
        if app.chat.history[i].role == "function" {
            let mut found = false;
            for j in 0..app.chat.history[i].parts.len() {
                let part = &app.chat.history[i].parts[j];
                if let Some(resp) = part.get("functionResponse")
                    && resp.get("name").and_then(|v| v.as_str()) == Some("sh")
                    && let Some(response_val) = resp.get("response")
                {
                    let status = response_val.get("status");
                    let error_val = response_val
                        .get("error")
                        .and_then(|v| v.as_str())
                        .unwrap_or("");
                    let is_aborted =
                        error_val.contains("terminated by user") || error_val.contains("Ctrl+C");

                    let is_running = status.and_then(|s| s.as_str()) == Some("running")
                        || error_val == "Command timed out / is still running"
                        || (status.is_none()
                            && !is_aborted
                            && response_val.get("exit_code").is_none());

                    if is_running {
                        let resp_pid = response_val
                            .get("pid")
                            .and_then(|v| v.as_u64())
                            .map(|v| v as u32);

                        let mut persistent_session_id = None;
                        for k in (0..i).rev() {
                            if app.chat.history[k].role == "model" {
                                for call_part in &app.chat.history[k].parts {
                                    if let Some(call) = call_part.get("functionCall")
                                        && call.get("name").and_then(|v| v.as_str()) == Some("sh")
                                    {
                                        if let Some(args) = call.get("args") {
                                            persistent_session_id = args
                                                .get("persistent_session_id")
                                                .and_then(|v| v.as_str())
                                                .map(|s| s.to_owned());
                                        }
                                        break;
                                    }
                                }
                                break;
                            }
                        }

                        history_target = Some((i, j, persistent_session_id, resp_pid));
                        found = true;
                        break;
                    }
                }
            }
            if found {
                break;
            }
        }
    }

    if let Some((_, _, ref p_sess_id, resp_pid)) = history_target {
        if target_session_id.is_none() && p_sess_id.is_some() {
            target_session_id = p_sess_id.clone();
        }
        if target_pid.is_none() && resp_pid.is_some() {
            target_pid = resp_pid;
        }
    }

    let mut killed = false;

    if let Some(ref session_id) = target_session_id {
        let registry = crate::tui::PERSISTENT_SESSIONS.get();
        if let Some(registry_mutex) = registry
            && let Some(session) = registry_mutex.lock().get(session_id)
        {
            let p_pid = session.pid;
            #[cfg(unix)]
            {
                let _ = std::process::Command::new("kill")
                    .arg("-2")
                    .arg(format!("-{}", p_pid))
                    .stdout(std::process::Stdio::null())
                    .stderr(std::process::Stdio::null())
                    .status();
            }
            #[cfg(not(unix))]
            {
                let _ = std::process::Command::new("taskkill")
                    .arg("/F")
                    .arg("/PID")
                    .arg(p_pid.to_string())
                    .stdout(std::process::Stdio::null())
                    .stderr(std::process::Stdio::null())
                    .status();
            }
            killed = true;
        }
    }

    if !killed && let Some(pid) = target_pid {
        #[cfg(unix)]
        {
            let _ = std::process::Command::new("kill")
                .arg("-9")
                .arg(format!("-{}", pid))
                .stdout(std::process::Stdio::null())
                .stderr(std::process::Stdio::null())
                .status();
        }
        #[cfg(not(unix))]
        {
            let _ = std::process::Command::new("taskkill")
                .arg("/F")
                .arg("/PID")
                .arg(pid.to_string())
                .stdout(std::process::Stdio::null())
                .stderr(std::process::Stdio::null())
                .status();
        }
    }

    if let Some((i, j, _, _)) = history_target {
        if let Some(resp) = app.chat.history[i].parts[j].get_mut("functionResponse")
            && let Some(response_val) = resp.get_mut("response")
            && let Some(obj) = response_val.as_object_mut()
        {
            obj.insert(
                "error".to_owned(),
                serde_json::json!("Process terminated by user via Ctrl+C"),
            );
            obj.insert("status".to_owned(), serde_json::Value::Null);
        }
    } else if let Some(pid) = target_pid {
        for msg in &mut app.chat.history {
            if msg.role == "function" {
                for part in &mut msg.parts {
                    if let Some(resp) = part.get_mut("functionResponse")
                        && resp.get("name").and_then(|v| v.as_str()) == Some("sh")
                        && let Some(response_val) = resp.get_mut("response")
                    {
                        let resp_pid = response_val
                            .get("pid")
                            .and_then(|v| v.as_u64())
                            .map(|v| v as u32);
                        if resp_pid == Some(pid)
                            && let Some(obj) = response_val.as_object_mut()
                        {
                            obj.insert(
                                "error".to_owned(),
                                serde_json::json!("Process terminated by user via Ctrl+C"),
                            );
                            obj.insert("status".to_owned(), serde_json::Value::Null);
                        }
                    }
                }
            }
        }
    }

    app.chat.shell_focused = false;
    app.chat.focused_shell_session_id = None;
    app.chat.focused_shell_pid = None;
    for m in &mut app.chat.messages {
        if m.is_shell {
            *m.cached_wrapped.borrow_mut() = None;
        }
    }

    app.chat.messages = crate::app::session::rebuild_messages_from_history(
        &app.chat.history,
        app.chat.config.show_thoughts,
    );
    app.save_session();
    app.status = "Aborted by user".to_owned();
}

fn handle_trust_modal_key(app: &mut App, key: KeyEvent) -> Result<()> {
    // Tab / arrow keys / h-l to move the focus between Yes / No buttons
    match key.code {
        KeyCode::Left | KeyCode::Char('h') | KeyCode::BackTab => {
            app.ui.trust_modal_selected_yes = true;
        }
        KeyCode::Right | KeyCode::Char('l') | KeyCode::Tab => {
            app.ui.trust_modal_selected_yes = false;
        }
        KeyCode::Char('y') | KeyCode::Char('Y') => {
            app.answer_trust_modal(true);
        }
        KeyCode::Char('n') | KeyCode::Char('N') => {
            app.answer_trust_modal(false);
        }
        KeyCode::Enter => {
            app.answer_trust_modal(app.ui.trust_modal_selected_yes);
        }
        KeyCode::Esc => {
            app.answer_trust_modal(false);
        }
        _ => {}
    }
    Ok(())
}
