//! Dashboard state management
//!
//! Manages the current state of the dashboard UI including
//! selected categories, actions, modes, and user interaction state.

use std::collections::HashMap;
use std::time::Instant;

use rustelo_core_types::RouteConfigToml;
use serde::{Deserialize, Serialize};

use super::config::{DashboardConfig, MenuAction, MenuCategory};
use crate::manager::app::App;

/// Dashboard operation modes
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum DashboardMode {
    Main,          // Main dashboard view
    ActionResult,  // Showing action execution results
    Help,          // Help/shortcuts view
    Settings,      // Settings/preferences view
    PageGenerator, // Page generator mode
    PageEditor,    // Page editor mode
    PageSelector,  // Page file selector for editing
}

/// Page editor panel types
#[derive(Debug, Clone, PartialEq)]
pub enum PageEditorPanel {
    RouteConfig,    // Route configuration panel
    I18nFiles,      // Internationalization files panel
    SourceFiles,    // Source code files panel
    EditorSelector, // Editor selection panel
}

/// Route configuration data (alias to shared type)
pub type RouteConfig = RouteConfigToml;

/// JSON Data Document from build-tools generation
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RoutesDataDocument {
    pub generated_at: String,
    pub total_routes: usize,
    pub routes: Vec<PageRouteInfo>,
    pub metadata: RoutesMetadata,
}

/// Metadata about routes collection
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RoutesMetadata {
    pub languages: Vec<String>,
    pub components: Vec<String>,
    pub menu_groups: Vec<String>,
}

/// Page route information from JSON
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PageRouteInfo {
    pub path: String,
    pub component: String,
    pub page_component: String,
    pub unified_component: String,
    pub language: String,
    pub enabled: bool,
    pub priority: f64,
    pub requires_auth: Option<bool>,
    pub title_key: Option<String>,
    pub description_key: Option<String>,
    pub keywords: Vec<String>,
    pub menu_group: Option<String>,
    pub menu_order: Option<i32>,
    pub menu_icon: Option<String>,
    pub parameters: Vec<RouteParameter>,
    pub props: HashMap<String, toml::Value>,
}

/// Route parameter information
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RouteParameter {
    pub name: String,
    pub param_type: String,
    pub source: String,
    pub optional: bool,
    pub description: Option<String>,
}

/// Dashboard application state
#[derive(Debug)]
pub struct DashboardState {
    // Navigation state
    pub selected_category_index: usize,
    pub selected_action_index: usize,
    pub mode: DashboardMode,

    // Application state
    pub should_quit: bool,
    pub terminal_size: (u16, u16),
    pub last_refresh: Instant,

    // Status and messaging
    pub status_message: Option<String>,
    pub error_message: Option<String>,
    pub action_result: Option<String>,

    // UI state
    pub show_shortcuts: bool,
    pub show_descriptions: bool,

    // Chat prompt interface
    pub chat_input: String,
    pub chat_focused: bool,
    pub chat_history: Vec<String>,

    // Panel focus (categories vs actions)
    pub categories_focused: bool,

    // Language settings
    pub current_language: String,
    pub available_languages: Vec<String>,

    // Page generator/editor state
    pub page_app: Option<App>,
    pub page_editing_name: Option<String>,
    pub page_editing_component: Option<String>,
    pub page_files: Vec<(String, String)>, // (display_name, file_path)
    pub selected_file_index: usize,

    // Multi-panel page editor state
    pub page_editor_panel: PageEditorPanel,
    pub route_config_data: Option<RouteConfig>,
    pub i18n_files: Vec<(String, String)>, // (display_name, file_path)
    pub source_files: Vec<(String, String)>, // (display_name, file_path)
    pub selected_panel_item_index: usize,

    // Simple page creation form state
    pub page_name_input: String,

    // Page selector state
    pub available_pages: Vec<String>,
    pub selected_page_index: usize,

    // Route configuration state
    pub route_configs: Vec<RouteConfigToml>,
}

impl DashboardState {
    /// Create new dashboard state
    pub fn new(
        _config: &DashboardConfig,
        current_language: String,
        available_languages: Vec<String>,
    ) -> Self {
        Self {
            selected_category_index: 0,
            selected_action_index: 0,
            mode: DashboardMode::Main,
            should_quit: false,
            terminal_size: (80, 24), // Default size
            last_refresh: Instant::now(),
            status_message: None,
            error_message: None,
            action_result: None,
            show_shortcuts: true,
            show_descriptions: true,
            chat_input: String::new(),
            chat_focused: false,
            chat_history: Vec::new(),
            categories_focused: true, // Start with categories focused
            current_language,
            available_languages,
            page_app: None,
            page_editing_name: None,
            page_editing_component: None,
            page_files: Vec::new(),
            selected_file_index: 0,

            // Multi-panel page editor state
            page_editor_panel: PageEditorPanel::RouteConfig,
            route_config_data: None,
            i18n_files: Vec::new(),
            source_files: Vec::new(),
            selected_panel_item_index: 0,

            page_name_input: "MyNewPage".to_string(),
            available_pages: Vec::new(),
            selected_page_index: 0,
            route_configs: Vec::new(),
        }
    }

    /// Move selection up/down within current category
    pub fn move_selection(&mut self, delta: i32) {
        if self.mode == DashboardMode::Main {
            if self.categories_focused {
                // Move within categories list
                let new_index = (self.selected_category_index as i32 + delta).max(0);
                self.selected_category_index = new_index as usize;
                self.selected_action_index = 0; // Reset action selection
            } else {
                // Move within actions list
                let new_index = (self.selected_action_index as i32 + delta).max(0);
                self.selected_action_index = new_index as usize;
            }
        }
    }

    /// Move between categories (left/right) with wrapping
    pub fn move_category(&mut self, delta: i32, category_count: usize) {
        if self.mode == DashboardMode::Main {
            if category_count == 0 {
                self.selected_category_index = 0;
            } else {
                let current = self.selected_category_index as i32;
                let new_index = if delta > 0 {
                    // Moving forward: wrap to 0 after last
                    (current + delta) % category_count as i32
                } else {
                    // Moving backward: wrap to last after first
                    let result = current + delta;
                    if result < 0 {
                        (category_count as i32 + result) % category_count as i32
                    } else {
                        result % category_count as i32
                    }
                };
                self.selected_category_index = new_index as usize;
                self.selected_action_index = 0; // Reset action selection
            }
        }
    }

    /// Go to next category (requires category count for wrapping)
    pub fn next_category(&mut self, category_count: usize) {
        self.move_category(1, category_count);
    }

    /// Go to previous category (requires category count for wrapping)
    pub fn prev_category(&mut self, category_count: usize) {
        self.move_category(-1, category_count);
    }

    /// Get currently selected category
    pub fn get_current_category<'a>(
        &self,
        config: &'a DashboardConfig,
    ) -> Option<&'a MenuCategory> {
        config
            .categories_with_actions
            .get(self.selected_category_index)
    }

    /// Get currently selected action
    pub fn get_selected_action<'a>(&self, config: &'a DashboardConfig) -> Option<&'a MenuAction> {
        let category = self.get_current_category(config)?;
        category.actions.get(self.selected_action_index)
    }

    /// Validate and adjust selection indices
    pub fn validate_selection(&mut self, config: &DashboardConfig) {
        // Ensure category index is valid
        if self.selected_category_index >= config.category_count() {
            self.selected_category_index = config.category_count().saturating_sub(1);
        }

        // Ensure action index is valid for current category
        if let Some(category) = self.get_current_category(config) {
            if self.selected_action_index >= category.actions.len() {
                self.selected_action_index = category.actions.len().saturating_sub(1);
            }
        }
    }

    /// Set status message
    pub fn set_status(&mut self, message: String) {
        self.status_message = Some(message);
        self.error_message = None;
    }

    /// Set error message
    pub fn set_error(&mut self, message: String) {
        self.error_message = Some(message);
        self.status_message = None;
    }

    /// Set action result
    pub fn set_action_result(&mut self, result: String) {
        self.action_result = Some(result);
        self.mode = DashboardMode::ActionResult;
    }

    /// Clear all messages
    pub fn clear_messages(&mut self) {
        self.status_message = None;
        self.error_message = None;
        self.action_result = None;
    }

    /// Toggle shortcuts display
    pub fn toggle_shortcuts(&mut self) {
        self.show_shortcuts = !self.show_shortcuts;
    }

    /// Toggle descriptions display
    pub fn toggle_descriptions(&mut self) {
        self.show_descriptions = !self.show_descriptions;
    }

    /// Get current mode name for display
    pub fn mode_name(&self) -> &'static str {
        match self.mode {
            DashboardMode::Main => "Main",
            DashboardMode::ActionResult => "Action Result",
            DashboardMode::Help => "Help",
            DashboardMode::Settings => "Settings",
            DashboardMode::PageGenerator => "Page Generator",
            DashboardMode::PageEditor => "Page Editor",
            DashboardMode::PageSelector => "Page Selector",
        }
    }

    /// Toggle chat input focus
    pub fn toggle_chat_focus(&mut self) {
        self.chat_focused = !self.chat_focused;
    }

    /// Add character to chat input
    pub fn chat_input_char(&mut self, c: char) {
        if self.chat_focused {
            self.chat_input.push(c);
        }
    }

    /// Remove last character from chat input
    pub fn chat_backspace(&mut self) {
        if self.chat_focused {
            self.chat_input.pop();
        }
    }

    /// Submit chat input and add to history
    pub fn submit_chat(&mut self) -> String {
        let input = self.chat_input.clone();
        if !input.trim().is_empty() {
            self.chat_history.push(input.clone());
            self.chat_input.clear();
        }
        input
    }

    /// Toggle between categories and actions panel focus
    pub fn toggle_panel_focus(&mut self) {
        if self.mode == DashboardMode::Main && !self.chat_focused {
            self.categories_focused = !self.categories_focused;
        }
    }

    /// Switch to next available language
    pub fn next_language(&mut self) -> bool {
        if self.available_languages.is_empty() {
            return false;
        }

        if let Some(current_index) = self
            .available_languages
            .iter()
            .position(|lang| lang == &self.current_language)
        {
            let next_index = (current_index + 1) % self.available_languages.len();
            self.current_language = self.available_languages[next_index].clone();
            true
        } else {
            // Current language not in available list, set to first available
            self.current_language = self.available_languages[0].clone();
            true
        }
    }

    /// Enter page generator mode
    pub fn enter_page_generator(
        &mut self,
        project_root: &std::path::Path,
        translations: &std::collections::HashMap<String, String>,
    ) -> anyhow::Result<()> {
        let mut app = App::new(project_root.to_path_buf(), translations.clone())?;
        // Force the app to be in CreatePage mode, not PageManager mode
        app.switch_to_create_page();
        self.page_app = Some(app);
        self.mode = DashboardMode::PageGenerator;
        self.page_editing_name = None;
        Ok(())
    }

    /// Enter page editor mode
    pub fn enter_page_editor(
        &mut self,
        _project_root: &std::path::Path,
        _translations: &std::collections::HashMap<String, String>,
        page_name: Option<String>,
    ) -> anyhow::Result<()> {
        // Don't create App for now - just switch to editor mode
        // let app = App::new(project_root.to_path_buf(), translations.clone())?;
        // self.page_app = Some(app);
        self.page_app = None; // Simplified for now
        self.mode = DashboardMode::PageEditor;
        self.page_editing_name = page_name;
        self.set_status("Page editor opened successfully".to_string());
        Ok(())
    }

    /// Exit page generator/editor mode back to dashboard
    pub fn exit_page_mode(&mut self) {
        self.page_app = None;
        self.page_editing_name = None;
        self.mode = DashboardMode::Main;
        self.clear_messages();
        self.set_status("Returned to dashboard".to_string());
    }

    /// Enter page selector mode to choose a page to edit
    pub fn enter_page_selector(&mut self, project_root: &std::path::Path) -> anyhow::Result<()> {
        // Discover available pages
        self.available_pages = self.discover_available_pages(project_root)?;
        self.selected_page_index = 0;
        self.mode = DashboardMode::PageSelector;
        Ok(())
    }

    /// Discover available pages in the project
    fn discover_available_pages(
        &self,
        project_root: &std::path::Path,
    ) -> anyhow::Result<Vec<String>> {
        use std::collections::HashSet;
        let mut pages = Vec::new();
        let mut seen_components = HashSet::new();

        // First, try to discover pages from ALL route configuration files
        let routes_dir = project_root.join("site").join("config").join("routes");
        if routes_dir.exists() {
            // Read ALL TOML files in the routes directory
            if let Ok(entries) = std::fs::read_dir(&routes_dir) {
                // Process en.toml first if it exists, then all others
                let mut route_files = Vec::new();
                let mut en_file = None;

                // Collect all TOML files
                for entry in entries.flatten() {
                    if entry.path().is_file()
                        && entry.path().extension() == Some(std::ffi::OsStr::new("toml"))
                    {
                        if entry.file_name() == "en.toml" {
                            en_file = Some(entry.path());
                        } else {
                            route_files.push(entry.path());
                        }
                    }
                }

                // Process en.toml first, then others
                if let Some(en_path) = en_file {
                    route_files.insert(0, en_path);
                }

                // Process all route files
                for route_file in route_files {
                    if let Ok(content) = std::fs::read_to_string(&route_file) {
                        // Parse TOML and extract route information
                        if let Ok(parsed) = content.parse::<toml::Table>() {
                            if let Some(routes_array) =
                                parsed.get("routes").and_then(|r| r.as_array())
                            {
                                let file_name = route_file
                                    .file_name()
                                    .and_then(|n| n.to_str())
                                    .unwrap_or("unknown");
                                let lang_code =
                                    file_name.strip_suffix(".toml").unwrap_or("unknown");

                                for route in routes_array {
                                    if let Some(route_table) = route.as_table() {
                                        // Get canonical_path or path for display
                                        let display_name = route_table
                                            .get("canonical_path")
                                            .or_else(|| route_table.get("path"))
                                            .and_then(|p| p.as_str())
                                            .unwrap_or("unknown");

                                        // Get component name for internal reference
                                        let component = route_table
                                            .get("page_component")
                                            .or_else(|| route_table.get("component"))
                                            .and_then(|c| c.as_str())
                                            .unwrap_or("unknown");

                                        // Create unique key with path and component to avoid real
                                        // duplicates
                                        let unique_key = format!("{}|{}", display_name, component);
                                        if !seen_components.contains(&unique_key) {
                                            seen_components.insert(unique_key);
                                            pages.push(format!(
                                                "{} → {} [{}]",
                                                display_name, component, lang_code
                                            ));
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        // Only add file-based pages if no routes were found
        if pages.is_empty() {
            let pages_dir = project_root.join("crates").join("pages").join("src");
            if pages_dir.exists() {
                if let Ok(entries) = std::fs::read_dir(&pages_dir) {
                    for entry in entries.flatten() {
                        if entry.path().is_dir() {
                            if let Some(dir_name) = entry.file_name().to_str() {
                                if dir_name != "common"
                                    && dir_name != "helpers"
                                    && dir_name != "content"
                                {
                                    pages.push(format!("📄 {}", dir_name));
                                }
                            }
                        }
                    }
                }
            }
        }

        pages.sort();
        Ok(pages)
    }

    /// Find a page by canonical_path or component name
    pub fn find_page_by_path(
        &self,
        project_root: &std::path::Path,
        search_term: &str,
    ) -> anyhow::Result<Option<(String, String)>> {
        // Search in route configuration files
        let routes_dir = project_root.join("site").join("config").join("routes");
        if routes_dir.exists() {
            if let Ok(entries) = std::fs::read_dir(&routes_dir) {
                for entry in entries.flatten() {
                    if entry.path().is_file()
                        && entry.path().extension() == Some(std::ffi::OsStr::new("toml"))
                    {
                        if let Ok(content) = std::fs::read_to_string(entry.path()) {
                            // Parse TOML and search for matching routes
                            if let Ok(parsed) = content.parse::<toml::Table>() {
                                if let Some(routes_array) =
                                    parsed.get("routes").and_then(|r| r.as_array())
                                {
                                    for route in routes_array {
                                        if let Some(route_table) = route.as_table() {
                                            // Check canonical_path, path, or component matches
                                            let canonical_path = route_table
                                                .get("canonical_path")
                                                .and_then(|p| p.as_str());
                                            let path =
                                                route_table.get("path").and_then(|p| p.as_str());
                                            let component = route_table
                                                .get("page_component")
                                                .or_else(|| route_table.get("component"))
                                                .and_then(|c| c.as_str());

                                            // Check if search term matches (case-insensitive)
                                            let search_lower = search_term.to_lowercase();
                                            let matches = canonical_path.is_some_and(|p| {
                                                p.to_lowercase() == search_lower
                                                    || p.to_lowercase()
                                                        == format!("/{}", search_lower)
                                                    || p.trim_start_matches('/').to_lowercase()
                                                        == search_lower
                                            }) || path.is_some_and(|p| {
                                                p.to_lowercase() == search_lower
                                                    || p.to_lowercase()
                                                        == format!("/{}", search_lower)
                                                    || p.trim_start_matches('/').to_lowercase()
                                                        == search_lower
                                            }) || component.is_some_and(|c| {
                                                c.to_lowercase().contains(&search_lower)
                                            });

                                            if matches {
                                                let display_path =
                                                    canonical_path.or(path).unwrap_or("unknown");
                                                let page_component = component.unwrap_or("unknown");
                                                return Ok(Some((
                                                    display_path.to_string(),
                                                    page_component.to_string(),
                                                )));
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        Ok(None)
    }

    /// Discover files related to a specific page
    pub fn discover_page_files(
        &self,
        project_root: &std::path::Path,
        page_component: &str,
    ) -> Vec<(String, String)> {
        let mut files = Vec::new();

        // Convert component name to lowercase for directory matching
        let component_lower = page_component.to_lowercase();
        let page_name = component_lower
            .strip_suffix("page")
            .unwrap_or(&component_lower);

        // 1. Route configuration files
        let routes_dir = project_root.join("site").join("config").join("routes");
        for lang_file in [
            "en.toml",
            "es.toml",
            "admin.toml",
            "content_dynamic.toml",
            "external.toml",
        ] {
            let route_file = routes_dir.join(lang_file);
            if route_file.exists() {
                files.push((
                    format!("📋 Route Config: {}", lang_file),
                    route_file.display().to_string(),
                ));
            }
        }

        // 2. Page source files
        let pages_dir = project_root
            .join("crates")
            .join("pages")
            .join("src")
            .join(page_name);
        if pages_dir.exists() {
            // Look for common page files
            for file_name in ["mod.rs", "unified.rs", "client.rs", "ssr.rs"] {
                let page_file = pages_dir.join(file_name);
                if page_file.exists() {
                    files.push((
                        format!("🦀 Page Source: {}", file_name),
                        page_file.display().to_string(),
                    ));
                }
            }
        }

        // 3. FTL translation files (content directory)
        let content_dir = project_root.join("site").join("content");
        for lang in ["en", "es"] {
            let ftl_file = content_dir.join(format!("{}.ftl", lang));
            if ftl_file.exists() {
                files.push((
                    format!("🌐 Translation: {}.ftl", lang),
                    ftl_file.display().to_string(),
                ));
            }
        }

        // 4. Content files (if any)
        let content_pages_dir = content_dir.join("pages").join(page_name);
        if content_pages_dir.exists() {
            if let Ok(entries) = std::fs::read_dir(&content_pages_dir) {
                for entry in entries.flatten() {
                    if entry.path().is_file() {
                        if let Some(file_name) = entry.file_name().to_str() {
                            files.push((
                                format!("📄 Content: {}", file_name),
                                entry.path().display().to_string(),
                            ));
                        }
                    }
                }
            }
        }

        files
    }

    /// Move selection in page selector
    pub fn move_page_selection(&mut self, delta: i32) {
        if self.available_pages.is_empty() {
            return;
        }

        let new_index = if delta > 0 {
            (self.selected_page_index + 1) % self.available_pages.len()
        } else if self.selected_page_index == 0 {
            self.available_pages.len() - 1
        } else {
            self.selected_page_index - 1
        };

        self.selected_page_index = new_index;
    }

    /// Move selection in file list (for page editor)
    pub fn move_file_selection(&mut self, delta: i32) {
        if self.page_files.is_empty() {
            return;
        }

        let new_index = if delta > 0 {
            (self.selected_file_index + 1) % self.page_files.len()
        } else if self.selected_file_index == 0 {
            self.page_files.len() - 1
        } else {
            self.selected_file_index - 1
        };

        self.selected_file_index = new_index;
    }

    /// Get currently selected file
    pub fn get_selected_file(&self) -> Option<&(String, String)> {
        self.page_files.get(self.selected_file_index)
    }

    /// Get currently selected page
    pub fn get_selected_page(&self) -> Option<&String> {
        self.available_pages.get(self.selected_page_index)
    }

    /// Select page and switch to editor
    pub fn select_page_for_editing(
        &mut self,
        project_root: &std::path::Path,
        translations: &std::collections::HashMap<String, String>,
    ) -> anyhow::Result<()> {
        if let Some(selected_page) = self.get_selected_page().cloned() {
            // Extract component name from the selected page format: "path → Component
            // [lang]"
            let component_name = if let Some((_, after_arrow)) = selected_page.split_once(" → ") {
                // Split on the bracket to get just the component name
                if let Some((component, _)) = after_arrow.split_once(" [") {
                    component.to_string()
                } else {
                    after_arrow.to_string()
                }
            } else {
                // Fallback for other formats
                selected_page.clone()
            };

            // Store the component name for file discovery
            log::debug!("Extracted component name: '{}'", component_name);
            self.page_editing_component = Some(component_name.clone());

            // Discover related files (legacy format - kept for compatibility)
            self.page_files = self.discover_page_files(project_root, &component_name);
            self.selected_file_index = 0;

            // Load multi-panel data
            self.load_route_config_from_json(project_root, &component_name)?;
            self.discover_i18n_files(project_root, &component_name);
            self.discover_source_files(project_root, &component_name);

            // Reset panel state
            self.page_editor_panel = PageEditorPanel::RouteConfig;
            self.selected_panel_item_index = 0;

            self.enter_page_editor(project_root, translations, Some(selected_page))?;
        } else {
            anyhow::bail!("No page selected or available pages list is empty");
        }
        Ok(())
    }

    /// Switch between page editor panels (Space bar)
    pub fn next_page_editor_panel(&mut self) {
        use PageEditorPanel::*;
        self.page_editor_panel = match self.page_editor_panel {
            RouteConfig => I18nFiles,
            I18nFiles => SourceFiles,
            SourceFiles => EditorSelector,
            EditorSelector => RouteConfig,
        };
        self.selected_panel_item_index = 0; // Reset selection when changing
                                            // panels
    }

    /// Switch to previous page editor panel (Shift+Tab)
    pub fn prev_page_editor_panel(&mut self) {
        use PageEditorPanel::*;
        self.page_editor_panel = match self.page_editor_panel {
            RouteConfig => EditorSelector,
            I18nFiles => RouteConfig,
            SourceFiles => I18nFiles,
            EditorSelector => SourceFiles,
        };
        self.selected_panel_item_index = 0; // Reset selection when changing
                                            // panels
    }

    /// Move selection within current panel
    pub fn move_panel_item_selection(&mut self, delta: i32) {
        let max_items = match self.page_editor_panel {
            PageEditorPanel::RouteConfig => {
                // For route config, we need to navigate through all fields
                // This will be handled by the UI rendering logic
                if self.route_config_data.is_some() {
                    // Estimate based on typical fields - this will be properly counted in UI
                    10 // Allow navigation even if config exists
                } else {
                    0
                }
            }
            PageEditorPanel::I18nFiles => self.i18n_files.len(),
            PageEditorPanel::SourceFiles => self.source_files.len(),
            PageEditorPanel::EditorSelector => 3, // VS Code, Cursor, System Default
        };

        if max_items > 0 {
            if delta > 0 {
                self.selected_panel_item_index = (self.selected_panel_item_index + 1) % max_items;
            } else if delta < 0 {
                self.selected_panel_item_index = if self.selected_panel_item_index == 0 {
                    max_items - 1
                } else {
                    self.selected_panel_item_index - 1
                };
            }
        }
    }

    /// Load route configuration from JSON files (preferred method)
    pub fn load_route_config_from_json(
        &mut self,
        project_root: &std::path::Path,
        component_name: &str,
    ) -> anyhow::Result<()> {
        log::debug!("Loading route config for component: {}", component_name);

        // Use SITE_INFO_PATH with fallback to SITE_ROOT/data
        let data_path = if let Ok(info_path) = std::env::var("SITE_INFO_PATH") {
            std::path::PathBuf::from(info_path)
        } else if let Ok(site_root) = std::env::var("SITE_ROOT_PATH") {
            std::path::Path::new(&site_root).join("data")
        } else {
            let info_path = std::env::var("SITE_INFO_PATH")
                .unwrap_or_else(|_| "target/site_build/info".to_string());
            std::path::PathBuf::from(info_path)
        };

        let routes_json = project_root
            .join(data_path)
            .join("pages")
            .join("routes")
            .join("data.json");

        log::debug!("Attempting to load routes from: {}", routes_json.display());

        // Early return if file doesn't exist
        if !routes_json.exists() {
            log::debug!("Routes JSON file does not exist, falling back to TOML");
            self.load_route_config_from_toml(project_root, component_name)?;
            // Return early since we handled the config loading via TOML
            return Ok(());
        }

        // Load and parse JSON with proper error handling
        let routes_document = std::fs::read_to_string(&routes_json)
            .and_then(|content| {
                serde_json::from_str::<RoutesDataDocument>(&content)
                    .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))
            })
            .map_err(|e| {
                log::warn!("Failed to load/parse JSON routes: {}", e);
                e
            })
            .or_else(|_| -> anyhow::Result<RoutesDataDocument> {
                log::debug!("JSON loading failed, falling back to TOML");
                self.load_route_config_from_toml(project_root, component_name)?;
                // Return a minimal RoutesDataDocument since TOML loading succeeded
                Ok(RoutesDataDocument {
                    generated_at: std::time::SystemTime::now()
                        .duration_since(std::time::UNIX_EPOCH)
                        .unwrap_or_default()
                        .as_secs()
                        .to_string(),
                    total_routes: self.route_configs.len(),
                    routes: Vec::new(), // Will be populated later
                    metadata: RoutesMetadata {
                        languages: vec!["en".to_string()],
                        components: vec!["page".to_string()],
                        menu_groups: Vec::new(),
                    },
                })
            })?;

        log::debug!(
            "Successfully loaded {} routes from JSON",
            routes_document.total_routes
        );

        // Filter and convert matching routes
        let matching_routes: Vec<RouteConfigToml> = routes_document
            .routes
            .iter()
            .filter(|route| {
                route.page_component == component_name
                    || route.unified_component == component_name
                    || route.component == component_name
            })
            .map(|route| self.convert_page_route_to_config(route))
            .collect();

        // Add routes to state
        self.route_configs.extend(matching_routes);

        log::debug!(
            "Added {} route configs for component: {}",
            self.route_configs.len(),
            component_name
        );

        Ok(())
    }

    /// Convert PageRouteInfo to RouteConfigToml
    fn convert_page_route_to_config(&self, route: &PageRouteInfo) -> RouteConfigToml {
        use std::collections::HashMap;

        let mut metadata = HashMap::new();
        metadata.insert("language".to_string(), route.language.clone());
        metadata.insert(
            "title_key".to_string(),
            route.title_key.clone().unwrap_or_default(),
        );
        metadata.insert("enabled".to_string(), route.enabled.to_string());
        metadata.insert("priority".to_string(), route.priority.to_string());

        if let Some(description_key) = &route.description_key {
            metadata.insert("description_key".to_string(), description_key.clone());
        }
        if let Some(menu_group) = &route.menu_group {
            metadata.insert("menu_group".to_string(), menu_group.clone());
        }
        if let Some(menu_order) = route.menu_order {
            metadata.insert("menu_order".to_string(), menu_order.to_string());
        }
        if let Some(menu_icon) = &route.menu_icon {
            metadata.insert("menu_icon".to_string(), menu_icon.clone());
        }
        if let Some(requires_auth) = route.requires_auth {
            metadata.insert("requires_auth".to_string(), requires_auth.to_string());
        }
        metadata.insert(
            "unified_component".to_string(),
            route.unified_component.clone(),
        );

        RouteConfigToml {
            path: route.path.clone(),
            component: route.component.clone(),
            title_key: route.title_key.clone().unwrap_or_default(),
            language: route.language.clone(),
            enabled: route.enabled,
            description_key: route.description_key.clone(),
            keywords: if route.keywords.is_empty() {
                None
            } else {
                Some(route.keywords.clone())
            },
            priority: Some(route.priority as f32),
            menu_group: route.menu_group.clone(),
            menu_order: route.menu_order,
            menu_icon: route.menu_icon.clone(),
            is_external: None,
            requires_auth: route.requires_auth,
            show_in_sitemap: None,
            alternate_paths: None,
            canonical_path: None,
            content_type: None,
            rendering_profile: None,
            template: None,
            props: Some(
                metadata
                    .into_iter()
                    .map(|(k, v)| (k, toml::Value::String(v)))
                    .collect(),
            ),
            unified_component: Some(route.unified_component.clone()),
            lang_prefixes: None,
            params_component: None,
        }
    }

    /// Load route configuration from TOML files (fallback method)
    pub fn load_route_config_from_toml(
        &mut self,
        project_root: &std::path::Path,
        component_name: &str,
    ) -> anyhow::Result<()> {
        log::debug!("Loading route config for component: {}", component_name);

        // Look in the build output directory for embedded_routes.toml
        let build_dir = project_root.join("target").join("debug").join("build");
        log::debug!("Searching in build directory: {}", build_dir.display());

        if let Ok(entries) = std::fs::read_dir(&build_dir) {
            let mut shared_dirs: Vec<_> = entries
                .filter_map(|entry| entry.ok())
                .filter(|entry| {
                    entry.file_type().map(|ft| ft.is_dir()).unwrap_or(false)
                        && entry
                            .file_name()
                            .to_str()
                            .map(|name| name.starts_with("shared-"))
                            .unwrap_or(false)
                })
                .collect();

            // Sort by modification time (most recent first)
            shared_dirs.sort_by_key(|entry| {
                entry
                    .metadata()
                    .and_then(|m| m.modified())
                    .unwrap_or(std::time::SystemTime::UNIX_EPOCH)
            });
            shared_dirs.reverse();

            log::debug!("Found {} shared build directories", shared_dirs.len());

            for build_entry in shared_dirs {
                let embedded_routes = build_entry.path().join("out").join("embedded_routes.toml");
                log::debug!("Checking: {}", embedded_routes.display());

                if embedded_routes.exists() {
                    match std::fs::read_to_string(&embedded_routes) {
                        Ok(toml_content) => {
                            log::debug!(
                                "Read {} bytes from embedded_routes.toml",
                                toml_content.len()
                            );

                            // Parse individual route entries from the concatenated TOML content
                            let routes_array = self.parse_routes_from_toml(&toml_content);
                            log::debug!(
                                "Successfully extracted {} route entries from embedded_routes.toml",
                                routes_array.len()
                            );

                            for (route_index, route_value) in routes_array.iter().enumerate() {
                                if let Some(route_table) = route_value.as_table() {
                                    // Check for page_component, unified_component, or component
                                    let page_component = route_table
                                        .get("page_component")
                                        .or_else(|| route_table.get("unified_component"))
                                        .or_else(|| route_table.get("component"))
                                        .and_then(|v| v.as_str());

                                    if let Some(component_str) = page_component {
                                        log::debug!(
                                            "Route {}: Checking component '{}' vs '{}'",
                                            route_index,
                                            component_str,
                                            component_name
                                        );

                                        if component_str == component_name {
                                            // Found matching route
                                            // TODO: Fix this RouteConfigToml construction to use
                                            // proper metadata approach
                                            let mut metadata = HashMap::new();
                                            metadata
                                                .insert("language".to_string(), "en".to_string());
                                            let config = RouteConfigToml {
                                                path: route_table
                                                    .get("canonical_path")
                                                    .or_else(|| route_table.get("path"))
                                                    .and_then(|v| v.as_str())
                                                    .unwrap_or("unknown")
                                                    .to_string(),
                                                component: component_name.to_string(),
                                                title_key: component_name.to_string(),
                                                language: "en".to_string(),
                                                enabled: true,
                                                description_key: None,
                                                keywords: None,
                                                priority: None,
                                                menu_group: None,
                                                menu_order: None,
                                                menu_icon: None,
                                                is_external: None,
                                                requires_auth: None,
                                                show_in_sitemap: None,
                                                alternate_paths: None,
                                                canonical_path: None,
                                                content_type: None,
                                                rendering_profile: None,
                                                template: None,
                                                props: Some(
                                                    metadata
                                                        .into_iter()
                                                        .map(|(k, v)| (k, toml::Value::String(v)))
                                                        .collect(),
                                                ),
                                                unified_component: None,
                                                lang_prefixes: None,
                                                params_component: None,
                                            };

                                            self.route_config_data = Some(config);
                                            log::info!(
                                                "Found route config for '{}' at index {}",
                                                component_name,
                                                route_index
                                            );
                                            return Ok(());
                                        }
                                    }
                                }
                            }

                            if routes_array.is_empty() {
                                log::warn!("No route entries found in embedded_routes.toml");
                            } else {
                                log::debug!(
                                    "No matching component found in {} route entries",
                                    routes_array.len()
                                );
                            }
                        }
                        Err(e) => {
                            log::error!("Failed to read embedded_routes.toml: {}", e);
                        }
                    }
                }
            }
        } else {
            log::error!("Failed to read build directory: {}", build_dir.display());
        }

        log::warn!("No route config found for component: {}", component_name);
        self.route_config_data = None;
        Ok(())
    }

    /// Extract and parse individual route entries from concatenated TOML
    /// content
    fn parse_routes_from_toml(&self, toml_content: &str) -> Vec<toml::Value> {
        let mut routes = Vec::new();
        let mut current_route_lines = Vec::new();
        let mut in_route = false;
        let mut in_nested_section = false;

        for line in toml_content.lines() {
            let trimmed = line.trim();

            // Skip empty lines and comments outside of routes
            if !in_route && (trimmed.is_empty() || trimmed.starts_with('#')) {
                continue;
            }

            // Skip problematic lines
            if trimmed == "routes = []" {
                log::debug!("Skipping problematic 'routes = []' line");
                continue;
            }

            // Start of a new route section
            if trimmed.starts_with("[[routes]]") {
                // If we have a previous route, try to parse it
                if in_route && !current_route_lines.is_empty() {
                    self.try_parse_route(&current_route_lines, &mut routes);
                }

                // Start collecting lines for new route
                current_route_lines.clear();
                in_route = true;
                in_nested_section = false;
                continue; // Skip the [[routes]] line itself
            }

            // Handle nested sections like [routes.props] or [routes.parameter_extraction]
            if in_route && trimmed.starts_with("[routes.") {
                in_nested_section = true;
                current_route_lines.push(line);
                continue;
            }

            // End of current route (start of new section or config)
            if in_route
                && !in_nested_section
                && (trimmed.starts_with("[[")
                    || (trimmed.starts_with("# ") && trimmed.contains("Configuration")))
            {
                // Parse the accumulated route
                if !current_route_lines.is_empty() {
                    self.try_parse_route(&current_route_lines, &mut routes);
                }
                current_route_lines.clear();
                in_route = false;
                in_nested_section = false;
                continue;
            }

            // End of nested section
            if in_route && in_nested_section && trimmed.is_empty() {
                in_nested_section = false;
            }

            // Collect lines for current route
            if in_route {
                current_route_lines.push(line);
            }
        }

        // Parse any remaining route
        if in_route && !current_route_lines.is_empty() {
            self.try_parse_route(&current_route_lines, &mut routes);
        }

        log::debug!("Successfully parsed {} route entries", routes.len());
        routes
    }

    /// Try to parse a route from accumulated lines, handling malformed TOML
    /// gracefully
    fn try_parse_route(&self, route_lines: &[&str], routes: &mut Vec<toml::Value>) {
        let route_toml = route_lines.join("\n");

        // Try parsing as-is first
        if let Ok(parsed_route) = route_toml.parse::<toml::Value>() {
            routes.push(parsed_route);
        } else {
            // If parsing failed, try to extract basic key-value pairs manually
            log::debug!("Standard TOML parsing failed, trying manual extraction");
            if let Some(manual_route) = self.manual_parse_route(&route_toml) {
                routes.push(manual_route);
            } else {
                log::debug!("Failed to parse route: {}", route_toml);
            }
        }
    }

    /// Manually parse route TOML when standard parsing fails
    fn manual_parse_route(&self, route_toml: &str) -> Option<toml::Value> {
        use toml::{map::Map, Value};

        let mut route_map = Map::new();

        for line in route_toml.lines() {
            let trimmed = line.trim();

            // Skip empty lines, comments, and nested sections for now
            if trimmed.is_empty() || trimmed.starts_with('#') || trimmed.starts_with('[') {
                continue;
            }

            // Parse key = value pairs
            if let Some((key, value)) = trimmed.split_once('=') {
                let key = key.trim().to_string();
                let value_str = value.trim();

                // Try to parse the value as appropriate TOML type
                let parsed_value = if value_str.starts_with('"') && value_str.ends_with('"') {
                    // String value
                    Value::String(value_str.trim_matches('"').to_string())
                } else if value_str == "true" {
                    Value::Boolean(true)
                } else if value_str == "false" {
                    Value::Boolean(false)
                } else if let Ok(int_val) = value_str.parse::<i64>() {
                    Value::Integer(int_val)
                } else if let Ok(float_val) = value_str.parse::<f64>() {
                    Value::Float(float_val)
                } else if value_str.starts_with('[') && value_str.ends_with(']') {
                    // Try to parse as array
                    let array_content = value_str.trim_matches(['[', ']']);
                    let items: Vec<Value> = array_content
                        .split(',')
                        .map(|item| {
                            let item = item.trim().trim_matches('"');
                            Value::String(item.to_string())
                        })
                        .collect();
                    Value::Array(items)
                } else {
                    // Default to string
                    Value::String(value_str.to_string())
                };

                route_map.insert(key, parsed_value);
            }
        }

        if route_map.is_empty() {
            None
        } else {
            Some(Value::Table(route_map))
        }
    }

    /// Clean TOML content to handle mixed [[routes]] and routes = [] syntax
    fn clean_routes_toml(&self, toml_content: &str) -> String {
        // For backwards compatibility, but we'll use parse_routes_from_toml instead
        toml_content.to_string()
    }

    /// Discover I18n files for the current page
    pub fn discover_i18n_files(&mut self, project_root: &std::path::Path, component_name: &str) {
        let mut files = Vec::new();
        let component_lower = component_name.to_lowercase();
        let page_name = component_lower
            .strip_suffix("page")
            .unwrap_or(&component_lower);

        // Look in site/i18n/locales for FTL files
        let i18n_locales_dir = project_root.join("site").join("i18n").join("locales");

        for lang in ["en", "es"] {
            let lang_dir = i18n_locales_dir.join(lang);
            if lang_dir.exists() {
                // Look for page-specific FTL files
                for ftl_file in [
                    format!("{}.ftl", page_name),
                    format!("pages/{}.ftl", page_name),
                    format!("content/{}.ftl", page_name),
                ] {
                    let ftl_path = lang_dir.join(&ftl_file);
                    if ftl_path.exists() {
                        files.push((
                            format!("🌐 {} - {}", lang.to_uppercase(), ftl_file),
                            ftl_path.display().to_string(),
                        ));
                    }
                }
            }
        }

        self.i18n_files = files;
        log::debug!(
            "Found {} I18n files for {}",
            self.i18n_files.len(),
            component_name
        );
    }

    /// Discover source files for the current page
    pub fn discover_source_files(&mut self, project_root: &std::path::Path, component_name: &str) {
        let mut files = Vec::new();
        let component_lower = component_name.to_lowercase();
        let page_name = component_lower
            .strip_suffix("page")
            .unwrap_or(&component_lower);

        // Look in crates/pages/src for the page directory
        let pages_src_dir = project_root
            .join("crates")
            .join("pages")
            .join("src")
            .join(page_name);
        if pages_src_dir.exists() {
            // Common source files
            for file_name in ["mod.rs", "unified.rs", "client.rs", "ssr.rs"] {
                let source_file = pages_src_dir.join(file_name);
                if source_file.exists() {
                    files.push((
                        format!("🦀 {}", file_name),
                        source_file.display().to_string(),
                    ));
                }
            }

            // Check for subdirectories
            if let Ok(entries) = std::fs::read_dir(&pages_src_dir) {
                for entry in entries.flatten() {
                    if entry.file_type().map(|ft| ft.is_dir()).unwrap_or(false) {
                        let subdir_name = entry.file_name().to_string_lossy().to_string();
                        let subdir_mod = entry.path().join("mod.rs");
                        if subdir_mod.exists() {
                            files.push((
                                format!("📁 {}/mod.rs", subdir_name),
                                subdir_mod.display().to_string(),
                            ));
                        }
                        let subdir_unified = entry.path().join("unified.rs");
                        if subdir_unified.exists() {
                            files.push((
                                format!("📁 {}/unified.rs", subdir_name),
                                subdir_unified.display().to_string(),
                            ));
                        }
                    }
                }
            }
        }

        self.source_files = files;
        log::debug!(
            "Found {} source files for {}",
            self.source_files.len(),
            component_name
        );
    }
}
