//! Configuration structures for page generation

use std::collections::HashMap;
use std::path::Path;

use anyhow::Result;
use chrono::Utc;
use rustelo_core_types::{RouteConfigToml, RoutesConfig};
use serde::{Deserialize, Serialize};

use crate::manager::{PageConfig, PageTemplate};

/// Create a new route configuration from page config following PAP principles
pub fn create_route_from_page_config(config: &PageConfig, language: &str) -> RouteConfigToml {
    let mut metadata = HashMap::new();

    // Calculate title key based on module name
    let title_key = format!("{}-page-title", config.module_name.replace('_', "-"));
    let description_key = format!("{}-page-description", config.module_name.replace('_', "-"));

    // Store all route metadata in the metadata HashMap following PAP principles
    metadata.insert("language".to_string(), language.to_string());
    metadata.insert("title_key".to_string(), title_key.clone());
    metadata.insert("description_key".to_string(), description_key.clone());
    metadata.insert("enabled".to_string(), "true".to_string());
    metadata.insert("priority".to_string(), config.priority.to_string());
    metadata.insert(
        "keywords".to_string(),
        format!("{},page", config.name.to_lowercase()),
    );
    metadata.insert("menu_group".to_string(), "main".to_string());
    metadata.insert("menu_order".to_string(), "999".to_string()); // Default to end of menu
    metadata.insert("is_external".to_string(), "false".to_string());
    metadata.insert("requires_auth".to_string(), "false".to_string());
    metadata.insert("show_in_sitemap".to_string(), "true".to_string());
    metadata.insert("canonical_path".to_string(), config.route_path.clone());
    metadata.insert(
        "unified_component".to_string(),
        format!("Unified{}Page", config.name),
    );

    // Store i18n patterns in metadata
    if !config.i18n_patterns.is_empty() {
        metadata.insert("lang_prefixes".to_string(), config.i18n_patterns.join(","));
    } else {
        metadata.insert(
            "lang_prefixes".to_string(),
            format!("{}-", config.module_name.replace('_', "-")),
        );
    }

    // Store template information in metadata
    let template_str = config.template.as_str().to_string();
    metadata.insert("scaffold_template".to_string(), template_str.clone());

    let unified_component_value = metadata.get("unified_component").cloned();
    let language_str = language.to_string();

    RouteConfigToml {
        path: config.route_path.clone(),
        component: config.name.clone(),
        title_key: title_key.clone(),
        language: language_str,
        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: unified_component_value,
        lang_prefixes: None,
        params_component: Some({
            let mut params = HashMap::new();
            params.insert("template".to_string(), config.template.as_str().to_string());
            params
        }),
    }
}

/// Manager-specific wrapper around shared RoutesConfig with additional metadata
#[derive(Debug, Serialize, Deserialize)]
pub struct RouteConfig {
    /// Auto-generated comment
    #[serde(skip)]
    pub comment: String,
    /// Array of route entries (using shared type)
    #[serde(flatten)]
    pub config: RoutesConfig,
}

impl RouteConfig {
    /// Create a new route config from page config
    pub fn from_page_config(config: &PageConfig) -> Self {
        let comment = format!(
            "# Auto-generated by manager at {}\n# Page: {} ({})",
            Utc::now().format("%Y-%m-%d %H:%M:%S UTC"),
            config.name,
            config.template.as_str()
        );

        let routes: HashMap<String, RouteConfigToml> = config
            .languages
            .iter()
            .map(|lang| {
                let route_config = create_route_from_page_config(config, lang);
                let route_key = format!("{}-{}", config.name.to_lowercase(), lang);
                (route_key, route_config)
            })
            .collect();

        Self {
            comment,
            config: RoutesConfig {
                routes: routes.into_values().collect(),
            },
        }
    }

    /// Convert to TOML string with custom comment
    pub fn to_toml(&self) -> Result<String> {
        let mut content = self.comment.clone();
        content.push('\n');
        content.push('\n');

        let toml_content = toml::to_string_pretty(&self.config)?;
        content.push_str(&toml_content);

        Ok(content)
    }

    /// Save to file
    pub fn save_to_file(&self, path: &Path) -> Result<()> {
        let content = self.to_toml()?;
        std::fs::write(path, content)?;
        Ok(())
    }

    /// Load from existing file
    pub fn load_from_file(path: &Path) -> Result<Self> {
        let content = std::fs::read_to_string(path)?;
        let mut config: Self = toml::from_str(&content)?;

        // Preserve any existing comment from the file
        let lines: Vec<&str> = content.lines().collect();
        let mut comment_lines = Vec::new();

        for line in lines {
            if line.starts_with('#') || (line.trim().is_empty() && !comment_lines.is_empty()) {
                comment_lines.push(line);
            } else {
                break;
            }
        }

        config.comment = comment_lines.join("\n");
        Ok(config)
    }
}

/// Check if a page component exists in the pages crate
pub fn page_exists(project_root: &Path, module_name: &str) -> bool {
    let pages_dir = project_root.join("crates/pages/src").join(module_name);
    pages_dir.exists() && pages_dir.join("mod.rs").exists()
}

/// Check if a route file already exists for the given name
pub fn route_file_exists(project_root: &Path, module_name: &str) -> bool {
    let routes_dir = project_root.join("content/routes");

    // Check common route file names
    let possible_files = [
        format!("{}.toml", module_name),
        format!("{}-routes.toml", module_name),
        format!("new-{}.toml", module_name),
    ];

    for filename in &possible_files {
        if routes_dir.join(filename).exists() {
            return true;
        }
    }

    false
}

/// Generate a unique route filename
pub fn generate_route_filename(project_root: &Path, module_name: &str) -> String {
    let routes_dir = project_root.join("content/routes");
    let mut counter = 0;

    loop {
        let filename = if counter == 0 {
            format!("{}.toml", module_name)
        } else {
            format!("{}-{}.toml", module_name, counter)
        };

        if !routes_dir.join(&filename).exists() {
            return filename;
        }

        counter += 1;
        if counter > 100 {
            // Fallback to timestamp-based name
            return format!("{}-{}.toml", module_name, Utc::now().timestamp());
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::manager::{PageConfig, PageTemplate};

    #[test]
    fn test_route_creation() {
        let mut config = PageConfig::new("TestPage".to_string()).unwrap();
        config.template = PageTemplate::HeroPage;

        let route = create_route_from_page_config(&config, "en");

        assert_eq!(route.component, "TestPage");
        assert_eq!(
            route.unified_component,
            Some("UnifiedTestPagePage".to_string())
        );
        assert_eq!(route.language, "en");
        assert_eq!(route.title_key, "test-page-page-title");
        assert_eq!(
            route
                .params_component
                .as_ref()
                .and_then(|p| p.get("template")),
            Some(&"hero_page".to_string())
        );
    }

    #[test]
    fn test_route_config_toml_generation() {
        let config = PageConfig::new("TestPage".to_string()).unwrap();
        let route_config = RouteConfig::from_page_config(&config);

        let toml = route_config.to_toml().unwrap();
        assert!(toml.contains("Auto-generated by manager"));
        assert!(toml.contains("component = \"TestPage\""));
        assert!(toml.contains("scaffold_template = \"basic_page\""));
    }
}
