// src/state/pages/form.rs

use crate::config::colors::themes::Theme;
use canvas::canvas::{CanvasState, CanvasAction, ActionContext, HighlightState};
use common::proto::komp_ac::search::search_response::Hit;
use ratatui::layout::Rect;
use ratatui::Frame;
use std::collections::HashMap;

fn json_value_to_string(value: &serde_json::Value) -> String {
    match value {
        serde_json::Value::String(s) => s.clone(),
        serde_json::Value::Number(n) => n.to_string(),
        serde_json::Value::Bool(b) => b.to_string(),
        _ => String::new(),
    }
}

#[derive(Debug, Clone)]
pub struct FieldDefinition {
    pub display_name: String,
    pub data_key: String,
    pub is_link: bool,
    pub link_target_table: Option<String>,
}

#[derive(Clone)]
pub struct FormState {
    pub id: i64,
    pub profile_name: String,
    pub table_name: String,
    pub total_count: u64,
    pub current_position: u64,
    pub fields: Vec<FieldDefinition>,
    pub values: Vec<String>,
    pub current_field: usize,
    pub has_unsaved_changes: bool,
    pub current_cursor_pos: usize,
    pub autocomplete_active: bool,
    pub autocomplete_suggestions: Vec<Hit>,
    pub selected_suggestion_index: Option<usize>,
    pub autocomplete_loading: bool,
    pub link_display_map: HashMap<usize, String>,
}

impl FormState {
    // Add this method
    pub fn deactivate_autocomplete(&mut self) {
        self.autocomplete_active = false;
        self.autocomplete_suggestions.clear();
        self.selected_suggestion_index = None;
        self.autocomplete_loading = false;
    }

    pub fn new(
        profile_name: String,
        table_name: String,
        fields: Vec<FieldDefinition>,
    ) -> Self {
        let values = vec![String::new(); fields.len()];
        FormState {
            id: 0,
            profile_name,
            table_name,
            total_count: 0,
            current_position: 1,
            fields,
            values,
            current_field: 0,
            has_unsaved_changes: false,
            current_cursor_pos: 0,
            autocomplete_active: false,
            autocomplete_suggestions: Vec::new(),
            selected_suggestion_index: None,
            autocomplete_loading: false,
            link_display_map: HashMap::new(),
        }
    }

    pub fn get_display_name_for_hit(&self, hit: &Hit) -> String {
        if let Ok(content_map) =
            serde_json::from_str::<HashMap<String, serde_json::Value>>(
                &hit.content_json,
            )
        {
            const IGNORED_KEYS: &[&str] = &["id", "deleted", "created_at"];
            let mut keys: Vec<_> = content_map
                .keys()
                .filter(|k| !IGNORED_KEYS.contains(&k.as_str()))
                .cloned()
                .collect();
            keys.sort();

            let values: Vec<_> = keys
                .iter()
                .map(|key| {
                    content_map
                        .get(key)
                        .map(json_value_to_string)
                        .unwrap_or_default()
                })
                .filter(|s| !s.is_empty())
                .take(1)
                .collect();

            let display_part = values.first().cloned().unwrap_or_default();
            if display_part.is_empty() {
                format!("ID: {}", hit.id)
            } else {
                format!("{} | ID: {}", display_part, hit.id)
            }
        } else {
            format!("ID: {} (parse error)", hit.id)
        }
    }

    pub fn render(
        &self,
        f: &mut Frame,
        area: Rect,
        theme: &Theme,
        is_edit_mode: bool,
        highlight_state: &HighlightState, // Now using canvas::HighlightState
    ) {
        let fields_str_slice: Vec<&str> =
            self.fields().iter().map(|s| *s).collect();
        let values_str_slice: Vec<&String> = self.values.iter().collect();

        crate::components::form::form::render_form(
            f,
            area,
            self,
            &fields_str_slice,
            &self.current_field,
            &values_str_slice,
            &self.table_name,
            theme,
            is_edit_mode,
            highlight_state,
            self.total_count,
            self.current_position,
        );
    }

    pub fn reset_to_empty(&mut self) {
        self.id = 0;
        self.values.iter_mut().for_each(|v| v.clear());
        self.current_field = 0;
        self.current_cursor_pos = 0;
        self.has_unsaved_changes = false;
        if self.total_count > 0 {
            self.current_position = self.total_count + 1;
        } else {
            self.current_position = 1;
        }
        self.deactivate_autocomplete();
        self.link_display_map.clear();
    }

    pub fn get_current_input(&self) -> &str {
        self.values
            .get(self.current_field)
            .map(|s| s.as_str())
            .unwrap_or("")
    }

    pub fn get_current_input_mut(&mut self) -> &mut String {
        self.link_display_map.remove(&self.current_field);
        self.values
            .get_mut(self.current_field)
            .expect("Invalid current_field index")
    }

    pub fn update_from_response(
        &mut self,
        response_data: &HashMap<String, String>,
        new_position: u64,
    ) {
        self.values = self
            .fields
            .iter()
            .map(|field_def| {
                response_data
                    .get(&field_def.data_key)
                    .cloned()
                    .unwrap_or_default()
            })
            .collect();

        let id_str_opt = response_data
            .iter()
            .find(|(k, _)| k.eq_ignore_ascii_case("id"))
            .map(|(_, v)| v);

        if let Some(id_str) = id_str_opt {
            if let Ok(parsed_id) = id_str.parse::<i64>() {
                self.id = parsed_id;
            } else {
                tracing::error!(
                    "Failed to parse 'id' field '{}' for table {}.{}",
                    id_str,
                    self.profile_name,
                    self.table_name
                );
                self.id = 0;
            }
        } else {
            self.id = 0;
        }

        self.current_position = new_position;
        self.has_unsaved_changes = false;
        self.current_field = 0;
        self.current_cursor_pos = 0;
        self.deactivate_autocomplete();
        self.link_display_map.clear();
    }

    // NEW: Keep the rich suggestions methods for compatibility
    pub fn get_rich_suggestions(&self) -> Option<&[Hit]> {
        if self.autocomplete_active {
            Some(&self.autocomplete_suggestions)
        } else {
            None
        }
    }

    pub fn activate_rich_suggestions(&mut self, suggestions: Vec<Hit>) {
        self.autocomplete_suggestions = suggestions;
        self.autocomplete_active = !self.autocomplete_suggestions.is_empty();
        self.selected_suggestion_index = if self.autocomplete_active { Some(0) } else { None };
        self.autocomplete_loading = false;
    }
}

impl CanvasState for FormState {
    fn current_field(&self) -> usize {
        self.current_field
    }

    fn current_cursor_pos(&self) -> usize {
        self.current_cursor_pos
    }

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

    fn inputs(&self) -> Vec<&String> {
        self.values.iter().collect()
    }

    fn get_current_input(&self) -> &str {
        FormState::get_current_input(self)
    }

    fn get_current_input_mut(&mut self) -> &mut String {
        FormState::get_current_input_mut(self)
    }

    fn fields(&self) -> Vec<&str> {
        self.fields
            .iter()
            .map(|f| f.display_name.as_str())
            .collect()
    }

    fn set_current_field(&mut self, index: usize) {
        if index < self.fields.len() {
            self.current_field = index;
        }
        self.deactivate_autocomplete();
    }

    fn set_current_cursor_pos(&mut self, pos: usize) {
        self.current_cursor_pos = pos;
    }

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

    // --- FEATURE-SPECIFIC ACTION HANDLING ---
    fn handle_feature_action(&mut self, action: &CanvasAction, _context: &ActionContext) -> Option<String> {
        match action {
            CanvasAction::SelectSuggestion => {
                if let Some(selected_idx) = self.selected_suggestion_index {
                    if let Some(hit) = self.autocomplete_suggestions.get(selected_idx).cloned() {
                        // Extract the value from the selected suggestion
                        if let Ok(content_map) = serde_json::from_str::<HashMap<String, serde_json::Value>>(&hit.content_json) {
                            let current_field_def = &self.fields[self.current_field];
                            if let Some(value) = content_map.get(&current_field_def.data_key) {
                                let new_value = json_value_to_string(value);
                                let display_name = self.get_display_name_for_hit(&hit);
                                *self.get_current_input_mut() = new_value.clone();
                                self.set_current_cursor_pos(new_value.len());
                                self.set_has_unsaved_changes(true);
                                self.deactivate_autocomplete();
                                return Some(format!("Selected: {}", display_name));
                            }
                        }
                    }
                }
                None
            }
            _ => None, // Let canvas handle other actions
        }
    }

    fn get_display_value_for_field(&self, index: usize) -> &str {
        if let Some(display_text) = self.link_display_map.get(&index) {
            return display_text.as_str();
        }
        self.inputs()
            .get(index)
            .map(|s| s.as_str())
            .unwrap_or("")
    }

    fn has_display_override(&self, index: usize) -> bool {
        self.link_display_map.contains_key(&index)
    }
}
