// src/ui/handlers/ui.rs

use crate::config::binds::config::Config;
use crate::config::colors::themes::Theme;
use crate::services::grpc_client::GrpcClient;
use crate::services::ui_service::UiService;
use crate::config::storage::storage::load_auth_data;
use crate::modes::common::commands::CommandHandler;
use crate::modes::handlers::event::{EventHandler, EventOutcome};
use crate::modes::handlers::mode_manager::{AppMode, ModeManager};
use crate::state::pages::canvas_state::CanvasState as LocalCanvasState; // Keep local one with alias
use canvas::canvas::CanvasState; // Import external library's CanvasState trait
use crate::state::pages::form::{FormState, FieldDefinition}; // Import FieldDefinition
use crate::state::pages::auth::AuthState;
use crate::state::pages::auth::LoginState;
use crate::state::pages::auth::RegisterState;
use crate::state::pages::admin::AdminState;
use crate::state::pages::admin::AdminFocus;
use crate::state::pages::intro::IntroState;
use crate::state::app::buffer::BufferState;
use crate::state::app::buffer::AppView;
use crate::state::app::state::AppState;
use crate::tui::terminal::{EventReader, TerminalCore};
use crate::ui::handlers::render::render_ui;
use crate::tui::functions::common::login::LoginResult;
use crate::tui::functions::common::register::RegisterResult;
use crate::ui::handlers::context::DialogPurpose;
use crate::tui::functions::common::login;
use crate::tui::functions::common::register;
use crate::utils::columns::filter_user_columns;
use anyhow::{Context, Result};
use crossterm::cursor::SetCursorStyle;
use crossterm::event as crossterm_event;
use tracing::{error, info, warn};
use tokio::sync::mpsc;
use std::time::{Instant, Duration};
#[cfg(feature = "ui-debug")]
use crate::state::app::state::DebugState;
#[cfg(feature = "ui-debug")]
use crate::utils::debug_logger::pop_next_debug_message;

// Rest of the file remains the same...
pub async fn run_ui() -> Result<()> {
    let config = Config::load().context("Failed to load configuration")?;
    let theme = Theme::from_str(&config.colors.theme);
    let mut terminal = TerminalCore::new().context("Failed to initialize terminal")?;
    let mut grpc_client = GrpcClient::new().await.context("Failed to create GrpcClient")?;
    let mut command_handler = CommandHandler::new();

    let (login_result_sender, mut login_result_receiver) = mpsc::channel::<LoginResult>(1);
    let (register_result_sender, mut register_result_receiver) = mpsc::channel::<RegisterResult>(1);
    let (save_table_result_sender, mut save_table_result_receiver) = mpsc::channel::<Result<String>>(1);
    let (save_logic_result_sender, _save_logic_result_receiver) = mpsc::channel::<Result<String>>(1);

    let mut event_handler = EventHandler::new(
        login_result_sender.clone(),
        register_result_sender.clone(),
        save_table_result_sender.clone(),
        save_logic_result_sender.clone(),
        grpc_client.clone(),
    )
    .await
    .context("Failed to create event handler")?;
    let event_reader = EventReader::new();

    let mut auth_state = AuthState::default();
    let mut login_state = LoginState::default();
    let mut register_state = RegisterState::default();
    let mut intro_state = IntroState::default();
    let mut admin_state = AdminState::default();
    let mut buffer_state = BufferState::default();
    let mut app_state = AppState::new().context("Failed to create initial app state")?;

    let mut auto_logged_in = false;
    match load_auth_data() {
        Ok(Some(stored_data)) => {
            auth_state.auth_token = Some(stored_data.access_token);
            auth_state.user_id = Some(stored_data.user_id);
            auth_state.role = Some(stored_data.role);
            auth_state.decoded_username = Some(stored_data.username);
            auto_logged_in = true;
            info!("Auth data loaded from file. User is auto-logged in.");
        }
        Ok(None) => {
            info!("No stored auth data found. User will see intro/login.");
        }
        Err(e) => {
            error!("Failed to load auth data: {}", e);
        }
    }

    let (initial_profile, initial_table, initial_columns_from_service) =
        UiService::initialize_app_state_and_form(&mut grpc_client, &mut app_state)
            .await
            .context("Failed to initialize app state and form")?;

    let initial_field_defs: Vec<FieldDefinition> = filter_user_columns(initial_columns_from_service)
        .into_iter()
        .map(|col_name| FieldDefinition {
            display_name: col_name.clone(),
            data_key: col_name,
            is_link: false,
            link_target_table: None,
        })
        .collect();

    let mut form_state = FormState::new(
        initial_profile.clone(),
        initial_table.clone(),
        initial_field_defs,
    );

    UiService::fetch_and_set_table_count(&mut grpc_client, &mut form_state)
        .await
        .context(format!(
            "Failed to fetch initial count for table {}.{}",
            initial_profile, initial_table
        ))?;

    if form_state.total_count > 0 {
        if let Err(e) = UiService::load_table_data_by_position(&mut grpc_client, &mut form_state).await {
            event_handler.command_message = format!("Error loading initial data: {}", e);
        }
    } else {
        form_state.reset_to_empty();
    }

    if auto_logged_in {
        buffer_state.history = vec![AppView::Form];
        buffer_state.active_index = 0;
        info!("Initial view set to Form due to auto-login.");
    }

    let mut last_frame_time = Instant::now();
    let mut current_fps = 0.0;
    let mut needs_redraw = true;
    let mut prev_view_profile_name = app_state.current_view_profile_name.clone();
    let mut prev_view_table_name = app_state.current_view_table_name.clone();
    let mut table_just_switched = false;

    loop {
        let position_before_event = form_state.current_position;
        let mut event_processed = false;

        // --- CHANNEL RECEIVERS ---

        // For main search palette
        match event_handler.search_result_receiver.try_recv() {
            Ok(hits) => {
                info!("--- 4. Main loop received message from channel. ---");
                if let Some(search_state) = app_state.search_state.as_mut() {
                    search_state.results = hits;
                    search_state.is_loading = false;
                }
                needs_redraw = true;
            }
            Err(mpsc::error::TryRecvError::Empty) => {
            }
            Err(mpsc::error::TryRecvError::Disconnected) => {
                error!("Search result channel disconnected!");
            }
        }

        // --- ADDED: For live form autocomplete ---
        match event_handler.autocomplete_result_receiver.try_recv() {
            Ok(hits) => {
                if form_state.autocomplete_active {
                    form_state.autocomplete_suggestions = hits;
                    form_state.autocomplete_loading = false;
                    if !form_state.autocomplete_suggestions.is_empty() {
                        form_state.selected_suggestion_index = Some(0);
                    } else {
                        form_state.selected_suggestion_index = None;
                    }
                    event_handler.command_message = format!("Found {} suggestions.", form_state.autocomplete_suggestions.len());
                }
                needs_redraw = true;
            }
            Err(mpsc::error::TryRecvError::Empty) => {}
            Err(mpsc::error::TryRecvError::Disconnected) => {
                error!("Autocomplete result channel disconnected!");
            }
        }


        if app_state.ui.show_search_palette {
            needs_redraw = true;
        }
        if crossterm_event::poll(std::time::Duration::from_millis(1))? {
            let event = event_reader.read_event().context("Failed to read terminal event")?;
            event_processed = true;
            let event_outcome_result = event_handler.handle_event(
                event,
                &config,
                &mut terminal,
                &mut command_handler,
                &mut form_state,
                &mut auth_state,
                &mut login_state,
                &mut register_state,
                &mut intro_state,
                &mut admin_state,
                &mut buffer_state,
                &mut app_state,
            ).await;

            let mut should_exit = false;
            match event_outcome_result {
                Ok(outcome) => match outcome {
                    EventOutcome::Ok(message) => {
                        if !message.is_empty() {
                            event_handler.command_message = message;
                        }
                    }
                    EventOutcome::Exit(message) => {
                        event_handler.command_message = message;
                        should_exit = true;
                    }
                    EventOutcome::DataSaved(save_outcome, message) => {
                        event_handler.command_message = message;
                        if let Err(e) = UiService::handle_save_outcome(
                            save_outcome,
                            &mut grpc_client,
                            &mut app_state,
                            &mut form_state,
                        ).await {
                            event_handler.command_message =
                                format!("Error handling save outcome: {}", e);
                        }
                    }
                    EventOutcome::ButtonSelected { .. } => {}
                    EventOutcome::TableSelected { path } => {
                        let parts: Vec<&str> = path.split('/').collect();
                        if parts.len() == 2 {
                            let profile_name = parts[0].to_string();
                            let table_name = parts[1].to_string();

                            app_state.set_current_view_table(profile_name, table_name);
                            buffer_state.update_history(AppView::Form);
                            event_handler.command_message = format!("Loading table: {}", path);
                        } else {
                            event_handler.command_message = format!("Invalid table path: {}", path);
                        }
                    }
                },
                Err(e) => {
                    event_handler.command_message = format!("Error: {}", e);
                }
            }
            if should_exit {
                return Ok(());
            }
        }

        match login_result_receiver.try_recv() {
            Ok(result) => {
                if login::handle_login_result(result, &mut app_state, &mut auth_state, &mut login_state) {
                    needs_redraw = true;
                }
            }
            Err(mpsc::error::TryRecvError::Empty) => {}
            Err(mpsc::error::TryRecvError::Disconnected) => {
                error!("Login result channel disconnected unexpectedly.");
            }
        }

        match register_result_receiver.try_recv() {
            Ok(result) => {
                if register::handle_registration_result(result, &mut app_state, &mut register_state) {
                    needs_redraw = true;
                }
            }
            Err(mpsc::error::TryRecvError::Empty) => {}
            Err(mpsc::error::TryRecvError::Disconnected) => {
                error!("Register result channel disconnected unexpectedly.");
            }
        }

        match save_table_result_receiver.try_recv() {
            Ok(result) => {
                app_state.hide_dialog();
                match result {
                    Ok(ref success_message) => {
                        app_state.show_dialog(
                            "Save Successful",
                            success_message,
                            vec!["OK".to_string()],
                            DialogPurpose::SaveTableSuccess,
                        );
                        admin_state.add_table_state.has_unsaved_changes = false;
                    }
                    Err(e) => {
                        event_handler.command_message = format!("Save failed: {}", e);
                    }
                }
                needs_redraw = true;
            }
            Err(mpsc::error::TryRecvError::Empty) => {}
            Err(mpsc::error::TryRecvError::Disconnected) => {
                error!("Save table result channel disconnected unexpectedly.");
            }
        }

        if let Some(active_view) = buffer_state.get_active_view() {
            app_state.ui.show_intro = false;
            app_state.ui.show_login = false;
            app_state.ui.show_register = false;
            app_state.ui.show_admin = false;
            app_state.ui.show_add_table = false;
            app_state.ui.show_add_logic = false;
            app_state.ui.show_form = false;
            match active_view {
                AppView::Intro => app_state.ui.show_intro = true,
                AppView::Login => app_state.ui.show_login = true,
                AppView::Register => app_state.ui.show_register = true,
                AppView::Admin => {
                    info!("Active view is Admin, refreshing profile tree...");
                    match grpc_client.get_profile_tree().await {
                        Ok(refreshed_tree) => {
                            app_state.profile_tree = refreshed_tree;
                        }
                        Err(e) => {
                            error!("Failed to refresh profile tree for Admin panel: {}", e);
                            event_handler.command_message = format!("Error refreshing admin data: {}", e);
                        }
                    }
                    app_state.ui.show_admin = true;
                    let profile_names = app_state.profile_tree.profiles.iter()
                        .map(|p| p.name.clone())
                        .collect();
                    admin_state.set_profiles(profile_names);

                    if admin_state.current_focus == AdminFocus::default() ||
                    !matches!(admin_state.current_focus,
                                AdminFocus::InsideProfilesList |
                                AdminFocus::Tables | AdminFocus::InsideTablesList |
                                AdminFocus::Button1 | AdminFocus::Button2 | AdminFocus::Button3) {
                        admin_state.current_focus = AdminFocus::ProfilesPane;
                    }
                    if admin_state.profile_list_state.selected().is_none() && !app_state.profile_tree.profiles.is_empty() {
                        admin_state.profile_list_state.select(Some(0));
                    }
                }
                AppView::AddTable => app_state.ui.show_add_table = true,
                AppView::AddLogic => app_state.ui.show_add_logic = true,
                AppView::Form => app_state.ui.show_form = true,
                AppView::Scratch => {}
            }
        }

        // Continue with the rest of the function...
        // (The rest remains the same, but now CanvasState trait methods are available)
        
        if app_state.ui.show_form {
            let current_view_profile = app_state.current_view_profile_name.clone();
            let current_view_table = app_state.current_view_table_name.clone();

            if prev_view_profile_name != current_view_profile
                || prev_view_table_name != current_view_table
            {
                if let (Some(prof_name), Some(tbl_name)) =
                    (current_view_profile.as_ref(), current_view_table.as_ref())
                {
                    app_state.show_loading_dialog(
                        "Loading Table",
                        &format!("Fetching data for {}.{}...", prof_name, tbl_name),
                    );
                    needs_redraw = true;

                    match UiService::load_table_view(
                        &mut grpc_client,
                        &mut app_state,
                        prof_name,
                        tbl_name,
                    )
                    .await
                    {
                        Ok(mut new_form_state) => {
                            if let Err(e) = UiService::fetch_and_set_table_count(
                                &mut grpc_client,
                                &mut new_form_state,
                            )
                            .await
                            {
                                app_state.update_dialog_content(
                                    &format!("Error fetching count: {}", e),
                                    vec!["OK".to_string()],
                                    DialogPurpose::LoginFailed,
                                );
                            } else if new_form_state.total_count > 0 {
                                if let Err(e) = UiService::load_table_data_by_position(
                                    &mut grpc_client,
                                    &mut new_form_state,
                                )
                                .await
                                {
                                    app_state.update_dialog_content(
                                        &format!("Error loading data: {}", e),
                                        vec!["OK".to_string()],
                                        DialogPurpose::LoginFailed,
                                    );
                                } else {
                                    app_state.hide_dialog();
                                }
                            } else {
                                new_form_state.reset_to_empty();
                                app_state.hide_dialog();
                            }

                            form_state = new_form_state;
                            prev_view_profile_name = current_view_profile;
                            prev_view_table_name = current_view_table;
                            table_just_switched = true;
                        }
                        Err(e) => {
                            app_state.update_dialog_content(
                                &format!("Error loading table: {}", e),
                                vec!["OK".to_string()],
                                DialogPurpose::LoginFailed,
                            );
                            app_state.current_view_profile_name =
                                prev_view_profile_name.clone();
                            app_state.current_view_table_name =
                                prev_view_table_name.clone();
                        }
                    }
                }
                needs_redraw = true;
            }
        }

        // Continue with the rest of the positioning logic...
        // Now we can use CanvasState methods like get_current_input(), current_field(), etc.
        
        if let Some((profile_name, table_name)) = app_state.pending_table_structure_fetch.take() {
            if app_state.ui.show_add_logic {
                if admin_state.add_logic_state.profile_name == profile_name &&
                admin_state.add_logic_state.selected_table_name.as_deref() == Some(table_name.as_str()) {
                    info!("Fetching table structure for {}.{}", profile_name, table_name);
                    let fetch_message = UiService::initialize_add_logic_table_data(
                        &mut grpc_client,
                        &mut admin_state.add_logic_state,
                        &app_state.profile_tree,
                    ).await.unwrap_or_else(|e| {
                        error!("Error initializing add_logic_table_data: {}", e);
                        format!("Error fetching table structure: {}", e)
                    });

                    if !fetch_message.contains("Error") && !fetch_message.contains("Warning") {
                        info!("{}", fetch_message);
                    } else {
                        event_handler.command_message = fetch_message;
                    }
                    needs_redraw = true;
                } else {
                    error!(
                        "Mismatch in pending_table_structure_fetch: app_state wants {}.{}, but add_logic_state is for {}.{:?}",
                        profile_name, table_name,
                        admin_state.add_logic_state.profile_name,
                        admin_state.add_logic_state.selected_table_name
                    );
                }
            } else {
                warn!(
                    "Pending table structure fetch for {}.{} but AddLogic view is not active. Fetch ignored.",
                    profile_name, table_name
                );
            }
        }

        if let Some(table_name) = admin_state.add_logic_state.script_editor_awaiting_column_autocomplete.clone() {
            if app_state.ui.show_add_logic {
                let profile_name = admin_state.add_logic_state.profile_name.clone();

                info!("Fetching columns for table selection: {}.{}", profile_name, table_name);
                match UiService::fetch_columns_for_table(&mut grpc_client, &profile_name, &table_name).await {
                    Ok(columns) => {
                        admin_state.add_logic_state.set_columns_for_table_autocomplete(columns.clone());
                        info!("Loaded {} columns for table '{}'", columns.len(), table_name);
                        event_handler.command_message = format!("Columns for '{}' loaded. Select a column.", table_name);
                    }
                    Err(e) => {
                        error!("Failed to fetch columns for {}.{}: {}", profile_name, table_name, e);
                        admin_state.add_logic_state.script_editor_awaiting_column_autocomplete = None;
                        admin_state.add_logic_state.deactivate_script_editor_autocomplete();
                        event_handler.command_message = format!("Error loading columns for '{}': {}", table_name, e);
                    }
                }
                needs_redraw = true;
            }
        }

        let position_changed = form_state.current_position != position_before_event;
        let mut position_logic_needs_redraw = false;

        if app_state.ui.show_form && !table_just_switched {
            if position_changed && !event_handler.is_edit_mode {
                position_logic_needs_redraw = true;

                if form_state.current_position > form_state.total_count {
                    form_state.reset_to_empty();
                    event_handler.command_message = format!("New entry for {}.{}", form_state.profile_name, form_state.table_name);
                } else {
                    match UiService::load_table_data_by_position(&mut grpc_client, &mut form_state).await {
                        Ok(load_message) => {
                            if event_handler.command_message.is_empty() || !load_message.starts_with("Error") {
                                event_handler.command_message = load_message;
                            }
                        }
                        Err(e) => {
                            event_handler.command_message = format!("Error loading data: {}", e);
                        }
                    }
                }

                let current_input_after_load_str = form_state.get_current_input();
                let current_input_len_after_load = current_input_after_load_str.chars().count();
                let max_cursor_pos = if current_input_len_after_load > 0 {
                    current_input_len_after_load.saturating_sub(1)
                } else {
                    0
                };
                form_state.current_cursor_pos = event_handler.ideal_cursor_column.min(max_cursor_pos);

            } else if !position_changed && !event_handler.is_edit_mode {
                let current_input_str = form_state.get_current_input();
                let current_input_len = current_input_str.chars().count();
                let max_cursor_pos = if current_input_len > 0 {
                    current_input_len.saturating_sub(1)
                } else {
                    0
                };
                form_state.current_cursor_pos = event_handler.ideal_cursor_column.min(max_cursor_pos);
            }
        } else if app_state.ui.show_register {
            if !event_handler.is_edit_mode {
                let current_input = register_state.get_current_input();
                let max_cursor_pos = if !current_input.is_empty() { current_input.len() - 1 } else { 0 };
                register_state.current_cursor_pos = event_handler.ideal_cursor_column.min(max_cursor_pos);
            }
        } else if app_state.ui.show_login {
            if !event_handler.is_edit_mode {
                let current_input = login_state.get_current_input();
                let max_cursor_pos = if !current_input.is_empty() { current_input.len() - 1 } else { 0 };
                login_state.current_cursor_pos = event_handler.ideal_cursor_column.min(max_cursor_pos);
            }
        }

        if position_logic_needs_redraw {
            needs_redraw = true;
        }

        if app_state.ui.dialog.is_loading {
            needs_redraw = true;
        }

        #[cfg(feature = "ui-debug")]
        {
            let can_display_next = match &app_state.debug_state {
                Some(current) => current.display_start_time.elapsed() >= Duration::from_secs(2),
                None => true,
            };

            if can_display_next {
                if let Some((new_message, is_error)) = pop_next_debug_message() {
                    app_state.debug_state = Some(DebugState {
                        displayed_message: new_message,
                        is_error,
                        display_start_time: Instant::now(),
                    });
                }
            }
        }

        if event_processed || needs_redraw || position_changed {
            let current_mode = ModeManager::derive_mode(&app_state, &event_handler, &admin_state);
            match current_mode {
                AppMode::Edit => { terminal.show_cursor()?; }
                AppMode::Highlight => { terminal.set_cursor_style(SetCursorStyle::SteadyBlock)?; terminal.show_cursor()?; }
                AppMode::ReadOnly => {
                    if !app_state.ui.focus_outside_canvas { terminal.set_cursor_style(SetCursorStyle::SteadyBlock)?; }
                    else { terminal.set_cursor_style(SetCursorStyle::SteadyUnderScore)?; }
                    terminal.show_cursor().context("Failed to show cursor in ReadOnly mode")?;
                }
                AppMode::General => {
                    if app_state.ui.focus_outside_canvas { terminal.set_cursor_style(SetCursorStyle::SteadyUnderScore)?; terminal.show_cursor()?; }
                    else { terminal.hide_cursor()?; }
                }
                AppMode::Command => { terminal.set_cursor_style(SetCursorStyle::SteadyUnderScore)?; terminal.show_cursor().context("Failed to show cursor in Command mode")?; }
            }

            terminal.draw(|f| {
                render_ui(
                    f,
                    &mut form_state,
                    &mut auth_state,
                    &login_state,
                    &register_state,
                    &intro_state,
                    &mut admin_state,
                    &buffer_state,
                    &theme,
                    event_handler.is_edit_mode,
                    &event_handler.highlight_state,
                    &event_handler.command_input,
                    event_handler.command_mode,
                    &event_handler.command_message,
                    &event_handler.navigation_state,
                    &app_state.current_dir,
                    current_fps,
                    &app_state,
                );
            }).context("Terminal draw call failed")?;
            needs_redraw = false;
        }

        let now = Instant::now();
        let frame_duration = now.duration_since(last_frame_time);
        last_frame_time = now;
        if frame_duration.as_secs_f64() > 1e-6 {
            current_fps = 1.0 / frame_duration.as_secs_f64();
        }

        table_just_switched = false;
    }
}
