// src/modes/canvas/edit.rs
use crate::config::binds::config::Config;
use crate::functions::modes::edit::{
    add_logic_e, add_table_e, form_e,
};
use crate::modes::handlers::event::EventHandler;
use crate::services::grpc_client::GrpcClient;
use crate::state::app::state::AppState;
use crate::state::pages::admin::AdminState;
use crate::state::pages::{
    auth::{LoginState, RegisterState},
    form::FormState,
};
use canvas::canvas::CanvasState;
use canvas::{canvas::CanvasAction, dispatcher::ActionDispatcher, canvas::ActionResult};
use anyhow::Result;
use common::proto::komp_ac::search::search_response::Hit;
use crossterm::event::{KeyCode, KeyEvent};
use tokio::sync::mpsc;
use tracing::info;

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum EditEventOutcome {
    Message(String),
    ExitEditMode,
}

/// Helper function to spawn a non-blocking search task for autocomplete.
async fn trigger_form_autocomplete_search(
    form_state: &mut FormState,
    grpc_client: &mut GrpcClient,
    sender: mpsc::UnboundedSender<Vec<Hit>>,
) {
    if let Some(field_def) = form_state.fields.get(form_state.current_field) {
        if field_def.is_link {
            if let Some(target_table) = &field_def.link_target_table {
                // 1. Update state for immediate UI feedback
                form_state.autocomplete_loading = true;
                form_state.autocomplete_active = true;
                form_state.autocomplete_suggestions.clear();
                form_state.selected_suggestion_index = None;

                // 2. Clone everything needed for the background task
                let query = form_state.get_current_input().to_string();
                let table_to_search = target_table.clone();
                let mut grpc_client_clone = grpc_client.clone();

                info!(
                    "[Autocomplete] Spawning search in '{}' for query: '{}'",
                    table_to_search, query
                );

                // 3. Spawn the non-blocking task
                tokio::spawn(async move {
                    match grpc_client_clone
                        .search_table(table_to_search, query)
                        .await
                    {
                        Ok(response) => {
                            // Send results back through the channel
                            let _ = sender.send(response.hits);
                        }
                        Err(e) => {
                            tracing::error!(
                                "[Autocomplete] Search failed: {:?}",
                                e
                            );
                            // Send an empty vec on error so the UI can stop loading
                            let _ = sender.send(vec![]);
                        }
                    }
                });
            }
        }
    }
}

pub async fn handle_form_edit_with_canvas(
    key_event: KeyEvent,
    config: &Config,
    form_state: &mut FormState,
    ideal_cursor_column: &mut usize,
) -> Result<String> {
    // Try canvas action from key first
    if let Some(canvas_action) = CanvasAction::from_key(key_event.code) {
        match ActionDispatcher::dispatch(canvas_action, form_state, ideal_cursor_column).await {
            Ok(ActionResult::Success(msg)) => {
                return Ok(msg.unwrap_or_default());
            }
            Ok(ActionResult::HandledByFeature(msg)) => {
                return Ok(msg);
            }
            Ok(ActionResult::Error(msg)) => {
                return Ok(format!("Error: {}", msg));
            }
            Ok(ActionResult::RequiresContext(msg)) => {
                return Ok(format!("Context needed: {}", msg));
            }
            Err(_) => {
                // Fall through to try config mapping
            }
        }
    }

    // Try config-mapped action
    if let Some(action_str) = config.get_edit_action_for_key(key_event.code, key_event.modifiers) {
        let canvas_action = CanvasAction::from_string(&action_str);
        match ActionDispatcher::dispatch(canvas_action, form_state, ideal_cursor_column).await {
            Ok(ActionResult::Success(msg)) => {
                return Ok(msg.unwrap_or_default());
            }
            Ok(ActionResult::HandledByFeature(msg)) => {
                return Ok(msg);
            }
            Ok(ActionResult::Error(msg)) => {
                return Ok(format!("Error: {}", msg));
            }
            Ok(ActionResult::RequiresContext(msg)) => {
                return Ok(format!("Context needed: {}", msg));
            }
            Err(e) => {
                return Ok(format!("Action failed: {}", e));
            }
        }
    }

    Ok(String::new())
}

/// NEW: Unified canvas action handler for any CanvasState (LoginState, RegisterState, etc.)
/// This replaces the old auth_e::execute_edit_action calls with the new canvas library
async fn handle_canvas_state_edit<S: CanvasState>(
    key: KeyEvent,
    config: &Config,
    state: &mut S,
    ideal_cursor_column: &mut usize,
) -> Result<String> {
    // Try direct key mapping first (same pattern as FormState)
    if let Some(canvas_action) = CanvasAction::from_key(key.code) {
        match ActionDispatcher::dispatch(canvas_action, state, ideal_cursor_column).await {
            Ok(ActionResult::Success(msg)) => {
                return Ok(msg.unwrap_or_default());
            }
            Ok(ActionResult::HandledByFeature(msg)) => {
                return Ok(msg);
            }
            Ok(ActionResult::Error(msg)) => {
                return Ok(format!("Error: {}", msg));
            }
            Ok(ActionResult::RequiresContext(msg)) => {
                return Ok(format!("Context needed: {}", msg));
            }
            Err(_) => {
                // Fall through to try config mapping
            }
        }
    }

    // Try config-mapped action (same pattern as FormState)
    if let Some(action_str) = config.get_edit_action_for_key(key.code, key.modifiers) {
        let canvas_action = CanvasAction::from_string(&action_str);
        match ActionDispatcher::dispatch(canvas_action, state, ideal_cursor_column).await {
            Ok(ActionResult::Success(msg)) => {
                return Ok(msg.unwrap_or_default());
            }
            Ok(ActionResult::HandledByFeature(msg)) => {
                return Ok(msg);
            }
            Ok(ActionResult::Error(msg)) => {
                return Ok(format!("Error: {}", msg));
            }
            Ok(ActionResult::RequiresContext(msg)) => {
                return Ok(format!("Context needed: {}", msg));
            }
            Err(e) => {
                return Ok(format!("Action failed: {}", e));
            }
        }
    }

    Ok(String::new())
}

#[allow(clippy::too_many_arguments)]
pub async fn handle_edit_event(
    key: KeyEvent,
    config: &Config,
    form_state: &mut FormState,
    login_state: &mut LoginState,
    register_state: &mut RegisterState,
    admin_state: &mut AdminState,
    current_position: &mut u64,
    total_count: u64,
    event_handler: &mut EventHandler,
    app_state: &AppState,
) -> Result<EditEventOutcome> {
    // --- AUTOCOMPLETE-SPECIFIC KEY HANDLING ---
    if app_state.ui.show_form && form_state.autocomplete_active {
        if let Some(action) =
            config.get_edit_action_for_key(key.code, key.modifiers)
        {
            match action {
                "suggestion_down" => {
                    if !form_state.autocomplete_suggestions.is_empty() {
                        let current =
                            form_state.selected_suggestion_index.unwrap_or(0);
                        let next = (current + 1)
                            % form_state.autocomplete_suggestions.len();
                        form_state.selected_suggestion_index = Some(next);
                    }
                    return Ok(EditEventOutcome::Message(String::new()));
                }
                "suggestion_up" => {
                    if !form_state.autocomplete_suggestions.is_empty() {
                        let current =
                            form_state.selected_suggestion_index.unwrap_or(0);
                        let prev = if current == 0 {
                            form_state.autocomplete_suggestions.len() - 1
                        } else {
                            current - 1
                        };
                        form_state.selected_suggestion_index = Some(prev);
                    }
                    return Ok(EditEventOutcome::Message(String::new()));
                }
                "exit" => {
                    form_state.deactivate_autocomplete();
                    return Ok(EditEventOutcome::Message(
                        "Autocomplete cancelled".to_string(),
                    ));
                }
                "enter_decider" => {
                    if let Some(selected_idx) =
                        form_state.selected_suggestion_index
                    {
                        if let Some(selection) = form_state
                            .autocomplete_suggestions
                            .get(selected_idx)
                            .cloned()
                        {
                            // --- THIS IS THE CORE LOGIC CHANGE ---

                            // 1. Get the friendly display name for the UI
                            let display_name =
                                form_state.get_display_name_for_hit(&selection);

                            // 2. Store the REAL ID in the form's values
                            let current_input =
                                form_state.get_current_input_mut();
                            *current_input = selection.id.to_string();

                            // 3. Set the persistent display override in the map
                            form_state.link_display_map.insert(
                                form_state.current_field,
                                display_name,
                            );

                            // 4. Finalize state
                            form_state.deactivate_autocomplete();
                            form_state.set_has_unsaved_changes(true);
                            return Ok(EditEventOutcome::Message(
                                "Selection made".to_string(),
                            ));
                        }
                    }
                    form_state.deactivate_autocomplete();
                    // Fall through to default 'enter' behavior
                }
                _ => {} // Let other keys fall through to the live search logic
            }
        }
    }

    // --- LIVE AUTOCOMPLETE TRIGGER LOGIC ---
    let mut trigger_search = false;

    if app_state.ui.show_form {
        // Manual trigger
        if let Some("trigger_autocomplete") =
            config.get_edit_action_for_key(key.code, key.modifiers)
        {
            if !form_state.autocomplete_active {
                trigger_search = true;
            }
        }
        // Live search trigger while typing
        else if form_state.autocomplete_active {
            if let KeyCode::Char(_) | KeyCode::Backspace = key.code {
                let action = if let KeyCode::Backspace = key.code {
                    "delete_char_backward"
                } else {
                    "insert_char"
                };
                // FIX: Pass &mut event_handler.ideal_cursor_column
                form_e::execute_edit_action(
                    action,
                    key,
                    form_state,
                    &mut event_handler.ideal_cursor_column,
                )
                .await?;
                trigger_search = true;
            }
        }
    }

    if trigger_search {
        trigger_form_autocomplete_search(
            form_state,
            &mut event_handler.grpc_client,
            event_handler.autocomplete_result_sender.clone(),
        )
        .await;
        return Ok(EditEventOutcome::Message("Searching...".to_string()));
    }

    // --- GENERAL EDIT MODE EVENT HANDLING (IF NOT AUTOCOMPLETE) ---

    if let Some(action_str) =
        config.get_edit_action_for_key(key.code, key.modifiers)
    {
        // Handle Enter key (next field)
        if action_str == "enter_decider" {
            // FIX: Pass &mut event_handler.ideal_cursor_column
            let msg = form_e::execute_edit_action(
                "next_field",
                key,
                form_state,
                &mut event_handler.ideal_cursor_column,
            )
            .await?;
            return Ok(EditEventOutcome::Message(msg));
        }

        // Handle exiting edit mode
        if action_str == "exit" {
            return Ok(EditEventOutcome::ExitEditMode);
        }

        // Handle all other edit actions - NOW USING CANVAS LIBRARY
        let msg = if app_state.ui.show_login {
            // NEW: Use unified canvas handler instead of auth_e::execute_edit_action
            handle_canvas_state_edit(
                key,
                config,
                login_state,
                &mut event_handler.ideal_cursor_column,
            )
            .await?
        } else if app_state.ui.show_add_table {
            // NEW: Use unified canvas handler instead of add_table_e::execute_edit_action
            handle_canvas_state_edit(
                key,
                config,
                &mut admin_state.add_table_state,
                &mut event_handler.ideal_cursor_column,
            )
            .await?
        } else if app_state.ui.show_add_logic {
            // FIX: Pass &mut event_handler.ideal_cursor_column
            add_logic_e::execute_edit_action(
                action_str,
                key,
                &mut admin_state.add_logic_state,
                &mut event_handler.ideal_cursor_column,
            )
            .await?
        } else if app_state.ui.show_register {
            // NEW: Use unified canvas handler instead of auth_e::execute_edit_action
            handle_canvas_state_edit(
                key,
                config,
                register_state,
                &mut event_handler.ideal_cursor_column,
            )
            .await?
        } else {
            // FIX: Pass &mut event_handler.ideal_cursor_column
            form_e::execute_edit_action(
                action_str,
                key,
                form_state,
                &mut event_handler.ideal_cursor_column,
            )
            .await?
        };
        return Ok(EditEventOutcome::Message(msg));
    }

    // --- FALLBACK FOR CHARACTER INSERTION (IF NO OTHER BINDING MATCHED) ---
    if let KeyCode::Char(_) = key.code {
        let msg = if app_state.ui.show_login {
            // NEW: Use unified canvas handler instead of auth_e::execute_edit_action
            handle_canvas_state_edit(
                key,
                config,
                login_state,
                &mut event_handler.ideal_cursor_column,
            )
            .await?
        } else if app_state.ui.show_add_table {
            // NEW: Use unified canvas handler instead of add_table_e::execute_edit_action
            handle_canvas_state_edit(
                key,
                config,
                &mut admin_state.add_table_state,
                &mut event_handler.ideal_cursor_column,
            )
            .await?
        } else if app_state.ui.show_add_logic {
            // FIX: Pass &mut event_handler.ideal_cursor_column
            add_logic_e::execute_edit_action(
                "insert_char",
                key,
                &mut admin_state.add_logic_state,
                &mut event_handler.ideal_cursor_column,
            )
            .await?
        } else if app_state.ui.show_register {
            // NEW: Use unified canvas handler instead of auth_e::execute_edit_action
            handle_canvas_state_edit(
                key,
                config,
                register_state,
                &mut event_handler.ideal_cursor_column,
            )
            .await?
        } else {
            // FIX: Pass &mut event_handler.ideal_cursor_column
            form_e::execute_edit_action(
                "insert_char",
                key,
                form_state,
                &mut event_handler.ideal_cursor_column,
            )
            .await?
        };
        return Ok(EditEventOutcome::Message(msg));
    }

    Ok(EditEventOutcome::Message(String::new())) // No action taken
}
