// src/state/pages/add_logic.rs
use crate::config::binds::config::{EditorConfig, EditorKeybindingMode};
use crate::state::pages::canvas_state::CanvasState;
use crate::components::common::text_editor::{TextEditor, VimState};
use std::cell::RefCell;
use std::rc::Rc;
use tui_textarea::TextArea;

#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum AddLogicFocus {
    #[default]
    InputLogicName,
    InputTargetColumn,
    InputDescription,
    ScriptContentPreview,
    InsideScriptContent,
    SaveButton,
    CancelButton,
}

#[derive(Clone, Debug)]
pub struct AddLogicState {
    pub profile_name: String,
    pub selected_table_id: Option<i64>,
    pub selected_table_name: Option<String>,
    pub logic_name_input: String,
    pub target_column_input: String,
    pub script_content_editor: Rc<RefCell<TextArea<'static>>>,
    pub description_input: String,
    pub current_focus: AddLogicFocus,
    pub last_canvas_field: usize,
    pub logic_name_cursor_pos: usize,
    pub target_column_cursor_pos: usize,
    pub description_cursor_pos: usize,
    pub has_unsaved_changes: bool,
    pub editor_keybinding_mode: EditorKeybindingMode,
    pub vim_state: VimState,

    // New fields for Target Column Autocomplete
    pub table_columns_for_suggestions: Vec<String>, // All columns for the table
    pub target_column_suggestions: Vec<String>,     // Filtered suggestions
    pub show_target_column_suggestions: bool,
    pub selected_target_column_suggestion_index: Option<usize>,
    pub in_target_column_suggestion_mode: bool,

    // Script Editor Autocomplete
    pub script_editor_autocomplete_active: bool,
    pub script_editor_suggestions: Vec<String>,
    pub script_editor_selected_suggestion_index: Option<usize>,
    pub script_editor_trigger_position: Option<(usize, usize)>, // (line, column)
    pub all_table_names: Vec<String>,
    pub script_editor_filter_text: String,
    
    // New fields for same-profile table names and column autocomplete
    pub same_profile_table_names: Vec<String>, // Tables from same profile only
    pub script_editor_awaiting_column_autocomplete: Option<String>, // Table name waiting for column fetch
}

impl AddLogicState {
    pub fn new(editor_config: &EditorConfig) -> Self {
        let editor = TextEditor::new_textarea(editor_config);
        AddLogicState {
            profile_name: "default".to_string(),
            selected_table_id: None,
            selected_table_name: None,
            logic_name_input: String::new(),
            target_column_input: String::new(),
            script_content_editor: Rc::new(RefCell::new(editor)),
            description_input: String::new(),
            current_focus: AddLogicFocus::InputLogicName,
            last_canvas_field: 2,
            logic_name_cursor_pos: 0,
            target_column_cursor_pos: 0,
            description_cursor_pos: 0,
            has_unsaved_changes: false,
            editor_keybinding_mode: editor_config.keybinding_mode.clone(),
            vim_state: VimState::default(),

            table_columns_for_suggestions: Vec::new(),
            target_column_suggestions: Vec::new(),
            show_target_column_suggestions: false,
            selected_target_column_suggestion_index: None,
            in_target_column_suggestion_mode: false,

            script_editor_autocomplete_active: false,
            script_editor_suggestions: Vec::new(),
            script_editor_selected_suggestion_index: None,
            script_editor_trigger_position: None,
            all_table_names: Vec::new(),
            script_editor_filter_text: String::new(),
            
            same_profile_table_names: Vec::new(),
            script_editor_awaiting_column_autocomplete: None,
        }
    }

    pub const INPUT_FIELD_COUNT: usize = 3;

    /// Updates the target_column_suggestions based on current input.
    pub fn update_target_column_suggestions(&mut self) {
        let current_input = self.target_column_input.to_lowercase();
        if self.table_columns_for_suggestions.is_empty() {
            self.target_column_suggestions.clear();
            self.show_target_column_suggestions = false;
            self.selected_target_column_suggestion_index = None;
            return;
        }

        if current_input.is_empty() {
            self.target_column_suggestions = self.table_columns_for_suggestions.clone();
        } else {
            self.target_column_suggestions = self
                .table_columns_for_suggestions
                .iter()
                .filter(|name| name.to_lowercase().contains(&current_input))
                .cloned()
                .collect();
        }

        self.show_target_column_suggestions = !self.target_column_suggestions.is_empty();
        if self.show_target_column_suggestions {
            if let Some(selected_idx) = self.selected_target_column_suggestion_index {
                if selected_idx >= self.target_column_suggestions.len() {
                    self.selected_target_column_suggestion_index = Some(0);
                }
            } else {
                self.selected_target_column_suggestion_index = Some(0);
            }
        } else {
            self.selected_target_column_suggestion_index = None;
        }
    }

    /// Updates script editor suggestions based on current filter text
    pub fn update_script_editor_suggestions(&mut self) {
        let mut suggestions = vec!["sql".to_string()];

        if self.selected_table_name.is_some() {
            suggestions.extend(self.table_columns_for_suggestions.clone());
        }

        let current_selected_table_name = self.selected_table_name.as_deref();
        suggestions.extend(
            self.same_profile_table_names
                .iter()
                .filter(|tn| Some(tn.as_str()) != current_selected_table_name)
                .cloned()
        );

        if self.script_editor_filter_text.is_empty() {
            self.script_editor_suggestions = suggestions;
        } else {
            let filter_lower = self.script_editor_filter_text.to_lowercase();
            self.script_editor_suggestions = suggestions
                .into_iter()
                .filter(|suggestion| suggestion.to_lowercase().contains(&filter_lower))
                .collect();
        }

        // Update selection index
        if self.script_editor_suggestions.is_empty() {
            self.script_editor_selected_suggestion_index = None;
            self.script_editor_autocomplete_active = false;
        } else if let Some(selected_idx) = self.script_editor_selected_suggestion_index {
            if selected_idx >= self.script_editor_suggestions.len() {
                self.script_editor_selected_suggestion_index = Some(0);
            }
        } else {
            self.script_editor_selected_suggestion_index = Some(0);
        }
    }

    /// Checks if a suggestion is a table name (for triggering column autocomplete)
    pub fn is_table_name_suggestion(&self, suggestion: &str) -> bool {
        // Not "sql"
        if suggestion == "sql" {
            return false;
        }
        if self.table_columns_for_suggestions.contains(&suggestion.to_string()) {
            return false;
        }
        self.same_profile_table_names.contains(&suggestion.to_string())
    }
    
    /// Sets table columns for autocomplete suggestions
    pub fn set_table_columns(&mut self, columns: Vec<String>) {
        self.table_columns_for_suggestions = columns.clone();
        if !columns.is_empty() {
            self.update_target_column_suggestions();
        }
    }

    /// Sets all available table names for autocomplete suggestions
    pub fn set_all_table_names(&mut self, table_names: Vec<String>) {
        self.all_table_names = table_names;
    }

    /// Sets table names from the same profile for autocomplete suggestions
    pub fn set_same_profile_table_names(&mut self, table_names: Vec<String>) {
        self.same_profile_table_names = table_names;
    }

    /// Triggers waiting for column autocomplete for a specific table
    pub fn trigger_column_autocomplete_for_table(&mut self, table_name: String) {
        self.script_editor_awaiting_column_autocomplete = Some(table_name);
    }

    /// Updates autocomplete with columns for a specific table
    pub fn set_columns_for_table_autocomplete(&mut self, columns: Vec<String>) {
        self.script_editor_suggestions = columns;
        self.script_editor_selected_suggestion_index = if self.script_editor_suggestions.is_empty() {
            None
        } else {
            Some(0)
        };
        self.script_editor_autocomplete_active = !self.script_editor_suggestions.is_empty();
        self.script_editor_awaiting_column_autocomplete = None;
    }

    /// Deactivates script editor autocomplete and clears related state
    pub fn deactivate_script_editor_autocomplete(&mut self) {
        self.script_editor_autocomplete_active = false;
        self.script_editor_suggestions.clear();
        self.script_editor_selected_suggestion_index = None;
        self.script_editor_trigger_position = None;
        self.script_editor_filter_text.clear();
    }
}

impl Default for AddLogicState {
    fn default() -> Self {
        Self::new(&EditorConfig::default())
    }
}

impl CanvasState for AddLogicState {
    fn current_field(&self) -> usize {
        match self.current_focus {
            AddLogicFocus::InputLogicName => 0,
            AddLogicFocus::InputTargetColumn => 1,
            AddLogicFocus::InputDescription => 2,
            _ => self.last_canvas_field,
        }
    }

    fn current_cursor_pos(&self) -> usize {
        match self.current_focus {
            AddLogicFocus::InputLogicName => self.logic_name_cursor_pos,
            AddLogicFocus::InputTargetColumn => self.target_column_cursor_pos,
            AddLogicFocus::InputDescription => self.description_cursor_pos,
            _ => 0,
        }
    }

    fn has_unsaved_changes(&self) -> bool {
        self.has_unsaved_changes
    }

    fn inputs(&self) -> Vec<&String> {
        vec![
            &self.logic_name_input,
            &self.target_column_input,
            &self.description_input,
        ]
    }

    fn get_current_input(&self) -> &str {
        match self.current_focus {
            AddLogicFocus::InputLogicName => &self.logic_name_input,
            AddLogicFocus::InputTargetColumn => &self.target_column_input,
            AddLogicFocus::InputDescription => &self.description_input,
            _ => "",
        }
    }

    fn get_current_input_mut(&mut self) -> &mut String {
        match self.current_focus {
            AddLogicFocus::InputLogicName => &mut self.logic_name_input,
            AddLogicFocus::InputTargetColumn => &mut self.target_column_input,
            AddLogicFocus::InputDescription => &mut self.description_input,
            _ => &mut self.logic_name_input,
        }
    }

    fn fields(&self) -> Vec<&str> {
        vec!["Logic Name", "Target Column", "Description"]
    }

    fn set_current_field(&mut self, index: usize) {
        let new_focus = match index {
            0 => AddLogicFocus::InputLogicName,
            1 => AddLogicFocus::InputTargetColumn,
            2 => AddLogicFocus::InputDescription,
            _ => return,
        };
        if self.current_focus != new_focus {
            if self.current_focus == AddLogicFocus::InputTargetColumn {
                self.in_target_column_suggestion_mode = false;
                self.show_target_column_suggestions = false;
            }
            self.current_focus = new_focus;
            self.last_canvas_field = index;
        }
    }

    fn set_current_cursor_pos(&mut self, pos: usize) {
        match self.current_focus {
            AddLogicFocus::InputLogicName => {
                self.logic_name_cursor_pos = pos.min(self.logic_name_input.len());
            }
            AddLogicFocus::InputTargetColumn => {
                self.target_column_cursor_pos = pos.min(self.target_column_input.len());
            }
            AddLogicFocus::InputDescription => {
                self.description_cursor_pos = pos.min(self.description_input.len());
            }
            _ => {}
        }
    }

    fn set_has_unsaved_changes(&mut self, changed: bool) {
        self.has_unsaved_changes = changed;
    }

    fn get_suggestions(&self) -> Option<&[String]> {
        if self.current_field() == 1
            && self.in_target_column_suggestion_mode
            && self.show_target_column_suggestions
        {
            Some(&self.target_column_suggestions)
        } else {
            None
        }
    }

    fn get_selected_suggestion_index(&self) -> Option<usize> {
        if self.current_field() == 1
            && self.in_target_column_suggestion_mode
            && self.show_target_column_suggestions
        {
            self.selected_target_column_suggestion_index
        } else {
            None
        }
    }
}
