// src/state/app/state.rs

use anyhow::Result;
use common::proto::komp_ac::table_definition::ProfileTreeResponse;
// NEW: Import the types we need for the cache
use common::proto::komp_ac::table_structure::TableStructureResponse;
use crate::modes::handlers::mode_manager::AppMode;
use crate::state::app::search::SearchState;
use crate::ui::handlers::context::DialogPurpose;
use std::collections::HashMap;
use std::env;
use std::sync::Arc;
#[cfg(feature = "ui-debug")]
use std::time::Instant;

// --- DialogState and UiState are unchanged ---
pub struct DialogState {
    pub dialog_show: bool,
    pub dialog_title: String,
    pub dialog_message: String,
    pub dialog_buttons: Vec<String>,
    pub dialog_active_button_index: usize,
    pub purpose: Option<DialogPurpose>,
    pub is_loading: bool,
}

pub struct UiState {
    pub show_sidebar: bool,
    pub show_buffer_list: bool,
    pub show_intro: bool,
    pub show_admin: bool,
    pub show_add_table: bool,
    pub show_add_logic: bool,
    pub show_form: bool,
    pub show_login: bool,
    pub show_register: bool,
    pub show_search_palette: bool,
    pub focus_outside_canvas: bool,
    pub dialog: DialogState,
}

#[cfg(feature = "ui-debug")]
#[derive(Debug, Clone)]
pub struct DebugState {
    pub displayed_message: String,
    pub is_error: bool,
    pub display_start_time: Instant,
}

pub struct AppState {
    // Core editor state
    pub current_dir: String,
    pub profile_tree: ProfileTreeResponse,
    pub selected_profile: Option<String>,
    pub current_mode: AppMode,
    pub current_view_profile_name: Option<String>,
    pub current_view_table_name: Option<String>,

    // NEW: The "Rulebook" cache. We use Arc for efficient sharing.
    pub schema_cache: HashMap<String, Arc<TableStructureResponse>>,

    pub focused_button_index: usize,
    pub pending_table_structure_fetch: Option<(String, String)>,

    pub search_state: Option<SearchState>,

    // UI preferences
    pub ui: UiState,

    #[cfg(feature = "ui-debug")]
    pub debug_state: Option<DebugState>,
}

impl AppState {
    pub fn new() -> Result<Self> {
        let current_dir = env::current_dir()?.to_string_lossy().to_string();
        Ok(AppState {
            current_dir,
            profile_tree: ProfileTreeResponse::default(),
            selected_profile: None,
            current_view_profile_name: None,
            current_view_table_name: None,
            current_mode: AppMode::General,
            schema_cache: HashMap::new(), // NEW: Initialize the cache
            focused_button_index: 0,
            pending_table_structure_fetch: None,
            search_state: None,
            ui: UiState::default(),

            #[cfg(feature = "ui-debug")]
            debug_state: None,
        })
    }

    // --- ALL YOUR EXISTING METHODS ARE UNTOUCHED ---

    pub fn update_mode(&mut self, mode: AppMode) {
        self.current_mode = mode;
    }

    pub fn set_current_view_table(&mut self, profile_name: String, table_name: String) {
        self.current_view_profile_name = Some(profile_name);
        self.current_view_table_name = Some(table_name);
    }

    pub fn show_dialog(
        &mut self,
        title: &str,
        message: &str,
        buttons: Vec<String>,
        purpose: DialogPurpose,
    ) {
        self.ui.dialog.dialog_title = title.to_string();
        self.ui.dialog.dialog_message = message.to_string();
        self.ui.dialog.dialog_buttons = buttons;
        self.ui.dialog.dialog_active_button_index = 0;
        self.ui.dialog.purpose = Some(purpose);
        self.ui.dialog.is_loading = false;
        self.ui.dialog.dialog_show = true;
        self.ui.focus_outside_canvas = true;
    }

    pub fn show_loading_dialog(&mut self, title: &str, message: &str) {
        self.ui.dialog.dialog_title = title.to_string();
        self.ui.dialog.dialog_message = message.to_string();
        self.ui.dialog.dialog_buttons.clear();
        self.ui.dialog.dialog_active_button_index = 0;
        self.ui.dialog.purpose = None;
        self.ui.dialog.is_loading = true;
        self.ui.dialog.dialog_show = true;
        self.ui.focus_outside_canvas = true;
    }

    pub fn update_dialog_content(
        &mut self,
        message: &str,
        buttons: Vec<String>,
        purpose: DialogPurpose,
    ) {
        if self.ui.dialog.dialog_show {
            self.ui.dialog.dialog_message = message.to_string();
            self.ui.dialog.dialog_buttons = buttons;
            self.ui.dialog.dialog_active_button_index = 0;
            self.ui.dialog.purpose = Some(purpose);
            self.ui.dialog.is_loading = false;
        }
    }

    pub fn hide_dialog(&mut self) {
        self.ui.dialog.dialog_show = false;
        self.ui.dialog.dialog_title.clear();
        self.ui.dialog.dialog_message.clear();
        self.ui.dialog.dialog_buttons.clear();
        self.ui.dialog.dialog_active_button_index = 0;
        self.ui.dialog.purpose = None;
        self.ui.focus_outside_canvas = false;
        self.ui.dialog.is_loading = false;
    }

    pub fn next_dialog_button(&mut self) {
        if !self.ui.dialog.dialog_buttons.is_empty() {
            let next_index = (self.ui.dialog.dialog_active_button_index + 1)
                % self.ui.dialog.dialog_buttons.len();
            self.ui.dialog.dialog_active_button_index = next_index;
        }
    }

    pub fn previous_dialog_button(&mut self) {
        if !self.ui.dialog.dialog_buttons.is_empty() {
            let len = self.ui.dialog.dialog_buttons.len();
            let prev_index =
                (self.ui.dialog.dialog_active_button_index + len - 1) % len;
            self.ui.dialog.dialog_active_button_index = prev_index;
        }
    }

    pub fn get_active_dialog_button_label(&self) -> Option<&str> {
        self.ui.dialog
            .dialog_buttons
            .get(self.ui.dialog.dialog_active_button_index)
            .map(|s| s.as_str())
    }
}

impl Default for UiState {
    fn default() -> Self {
        Self {
            show_sidebar: false,
            show_intro: true,
            show_admin: false,
            show_add_table: false,
            show_add_logic: false,
            show_form: false,
            show_login: false,
            show_register: false,
            show_buffer_list: true,
            show_search_palette: false, // ADDED
            focus_outside_canvas: false,
            dialog: DialogState::default(),
        }
    }
}

impl Default for DialogState {
    fn default() -> Self {
        Self {
            dialog_show: false,
            dialog_title: String::new(),
            dialog_message: String::new(),
            dialog_buttons: Vec::new(),
            dialog_active_button_index: 0,
            purpose: None,
            is_loading: false,
        }
    }
}
