//! Configuration structures for page generation

use anyhow::Result;
use chrono::Utc;
use serde::{Deserialize, Serialize};
use std::path::Path;

use crate::PageConfig;

/// Route configuration entry as it appears in TOML files
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RouteEntry {
    pub component: String,
    pub page_component: String,
    pub unified_component: String,
    pub path: String,
    pub language: String,
    pub enabled: bool,
    pub priority: f64,
    pub auto_scaffold: bool,
    pub generate_boilerplate_only: bool,
    pub replace_existing_boilerplate: bool,
    pub scaffold_template: String,
    pub i18n_patterns: Vec<String>,
    pub title_key: String,
}

impl RouteEntry {
    /// Create a new route entry from page config
    pub fn from_page_config(config: &PageConfig, language: &str) -> Self {
        let title_key = format!("{}-page-title", config.module_name.replace('_', "-"));

        Self {
            component: config.name.clone(),
            page_component: format!("{}Page", config.name),
            unified_component: format!("Unified{}Page", config.name),
            path: config.route_path.clone(),
            language: language.to_string(),
            enabled: true,
            priority: config.priority,
            auto_scaffold: config.auto_scaffold,
            generate_boilerplate_only: false,
            replace_existing_boilerplate: config.replace_existing,
            scaffold_template: config.template.as_str().to_string(),
            i18n_patterns: config.i18n_patterns.clone(),
            title_key,
        }
    }
}

/// Route configuration file structure
#[derive(Debug, Serialize, Deserialize)]
pub struct RouteConfig {
    /// Auto-generated comment
    #[serde(skip)]
    pub comment: String,
    /// Array of route entries
    pub routes: Vec<RouteEntry>,
}

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

        let routes = config
            .languages
            .iter()
            .map(|lang| RouteEntry::from_page_config(config, lang))
            .collect();

        Self { comment, routes }
    }

    /// 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)?;
        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('#') {
                comment_lines.push(line);
            } else if 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::{PageConfig, PageTemplate};

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

        let entry = RouteEntry::from_page_config(&config, "en");

        assert_eq!(entry.component, "TestPage");
        assert_eq!(entry.page_component, "TestPagePage");
        assert_eq!(entry.unified_component, "UnifiedTestPagePage");
        assert_eq!(entry.scaffold_template, "hero_page");
        assert_eq!(entry.language, "en");
        assert_eq!(entry.title_key, "test-page-page-title");
    }

    #[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 rustelo-page"));
        assert!(toml.contains("component = \"TestPage\""));
        assert!(toml.contains("scaffold_template = \"basic_page\""));
    }
}
