//! RouteMetadataAccess trait for accessing route metadata following PAP
//! principles
//!
//! This module provides helper functions to access route metadata from the
//! RouteConfigToml fields, following Project Architecture Principles (PAP).

use std::collections::HashMap;

use rustelo_core_types::RouteConfigToml;

/// Helper trait to access metadata from RouteConfigToml following PAP
/// principles
pub trait RouteMetadataAccess {
    /// Get language from metadata
    fn get_language(&self) -> Option<String>;

    /// Get title key from metadata
    fn get_title_key(&self) -> Option<String>;

    /// Get description key from metadata
    fn get_description_key(&self) -> Option<String>;

    /// Get enabled status from metadata
    fn get_enabled(&self) -> bool;

    /// Get priority from metadata
    fn get_priority(&self) -> f32;

    /// Get keywords from metadata
    fn get_keywords(&self) -> Option<String>;

    /// Get menu group from metadata
    fn get_menu_group(&self) -> Option<String>;

    /// Get menu order from metadata
    fn get_menu_order(&self) -> Option<i32>;

    /// Get menu icon from metadata
    fn get_menu_icon(&self) -> Option<String>;

    /// Get external link status from metadata
    fn get_is_external(&self) -> bool;

    /// Get auth requirement from metadata
    fn get_requires_auth(&self) -> bool;

    /// Get sitemap visibility from metadata
    fn get_show_in_sitemap(&self) -> bool;

    /// Get canonical path from metadata
    fn get_canonical_path(&self) -> Option<String>;

    /// Get unified component from metadata
    fn get_unified_component(&self) -> Option<String>;

    /// Get template from metadata
    fn get_template(&self) -> Option<String>;

    /// Get content type from metadata
    fn get_content_type(&self) -> Option<String>;

    /// Set metadata value
    fn set_metadata(&mut self, key: &str, value: &str);

    /// Get metadata value by key
    fn get_metadata(&self, key: &str) -> Option<String>;

    /// Get all metadata keys
    fn get_metadata_keys(&self) -> Vec<String>;

    /// Get all metadata as HashMap
    fn get_all_metadata(&self) -> HashMap<String, String>;

    /// Check if metadata contains key
    fn has_metadata(&self, key: &str) -> bool;

    /// Get auto generate status from metadata
    fn get_auto_generate(&self) -> bool;

    /// Get i18n patterns from metadata
    fn get_i18n_patterns(&self) -> Vec<String>;

    /// Get template params from metadata as TOML value
    fn get_template_params(&self) -> toml::Value;
}

impl RouteMetadataAccess for RouteConfigToml {
    fn get_language(&self) -> Option<String> {
        Some(self.language.clone())
    }

    fn get_title_key(&self) -> Option<String> {
        if self.title_key.is_empty() {
            None
        } else {
            Some(self.title_key.clone())
        }
    }

    fn get_description_key(&self) -> Option<String> {
        self.description_key.clone()
    }

    fn get_enabled(&self) -> bool {
        self.enabled
    }

    fn get_priority(&self) -> f32 {
        self.priority.unwrap_or(0.5)
    }

    fn get_keywords(&self) -> Option<String> {
        self.keywords.as_ref().map(|k| k.join(", "))
    }

    fn get_menu_group(&self) -> Option<String> {
        self.menu_group.clone()
    }

    fn get_menu_order(&self) -> Option<i32> {
        self.menu_order
    }

    fn get_menu_icon(&self) -> Option<String> {
        self.menu_icon.clone()
    }

    fn get_is_external(&self) -> bool {
        self.is_external.unwrap_or(false)
    }

    fn get_requires_auth(&self) -> bool {
        self.requires_auth.unwrap_or(false)
    }

    fn get_show_in_sitemap(&self) -> bool {
        self.show_in_sitemap.unwrap_or(true)
    }

    fn get_canonical_path(&self) -> Option<String> {
        self.canonical_path.clone()
    }

    fn get_unified_component(&self) -> Option<String> {
        self.unified_component.clone()
    }

    fn get_template(&self) -> Option<String> {
        // Template not directly available, return None
        None
    }

    fn get_content_type(&self) -> Option<String> {
        self.content_type.clone()
    }

    fn set_metadata(&mut self, _key: &str, _value: &str) {
        // No generic metadata system in new structure, this is a no-op
        // In the future, could extend props field
    }

    fn get_metadata(&self, key: &str) -> Option<String> {
        // Try to map common metadata keys to actual fields
        match key {
            "language" => Some(self.language.clone()),
            "title_key" => self.get_title_key(),
            "description_key" => self.get_description_key(),
            "canonical_path" => self.get_canonical_path(),
            "unified_component" => RouteMetadataAccess::get_unified_component(self),
            "content_type" => self.get_content_type(),
            "component" => Some(self.component.clone()),
            "enabled" => Some(self.enabled.to_string()),
            "priority" => Some(self.get_priority().to_string()),
            "menu_group" => self.get_menu_group(),
            "menu_order" => RouteMetadataAccess::get_menu_order(self).map(|o| o.to_string()),
            "menu_icon" => self.get_menu_icon(),
            "is_external" => Some(self.get_is_external().to_string()),
            "requires_auth" => Some(self.get_requires_auth().to_string()),
            "show_in_sitemap" => Some(self.get_show_in_sitemap().to_string()),
            _ => {
                // Check props field if it exists
                if let Some(ref props) = self.props {
                    props
                        .get(key)
                        .and_then(|v| v.as_str())
                        .map(|s| s.to_string())
                } else {
                    None
                }
            }
        }
    }

    fn get_metadata_keys(&self) -> Vec<String> {
        let mut keys = vec![
            "language".to_string(),
            "component".to_string(),
            "enabled".to_string(),
        ];

        if !self.title_key.is_empty() {
            keys.push("title_key".to_string());
        }
        if self.description_key.is_some() {
            keys.push("description_key".to_string());
        }
        if self.canonical_path.is_some() {
            keys.push("canonical_path".to_string());
        }
        if self.unified_component.is_some() {
            keys.push("unified_component".to_string());
        }
        if self.content_type.is_some() {
            keys.push("content_type".to_string());
        }

        // Add props keys if they exist
        if let Some(ref props) = self.props {
            keys.extend(props.keys().cloned());
        }

        keys
    }

    fn get_all_metadata(&self) -> HashMap<String, String> {
        let mut metadata = HashMap::new();

        metadata.insert("language".to_string(), self.language.clone());
        metadata.insert("component".to_string(), self.component.clone());
        metadata.insert("enabled".to_string(), self.enabled.to_string());
        metadata.insert("priority".to_string(), self.get_priority().to_string());

        if let Some(title_key) = self.get_title_key() {
            metadata.insert("title_key".to_string(), title_key);
        }
        if let Some(desc_key) = self.get_description_key() {
            metadata.insert("description_key".to_string(), desc_key);
        }
        if let Some(canonical) = self.get_canonical_path() {
            metadata.insert("canonical_path".to_string(), canonical);
        }
        if let Some(unified) = RouteMetadataAccess::get_unified_component(self) {
            metadata.insert("unified_component".to_string(), unified);
        }
        if let Some(content_type) = self.get_content_type() {
            metadata.insert("content_type".to_string(), content_type);
        }

        // Add props if they exist
        if let Some(ref props) = self.props {
            for (key, value) in props {
                if let Some(str_value) = value.as_str() {
                    metadata.insert(key.clone(), str_value.to_string());
                }
            }
        }

        metadata
    }

    fn has_metadata(&self, key: &str) -> bool {
        self.get_metadata(key).is_some()
    }

    fn get_auto_generate(&self) -> bool {
        self.get_metadata("auto_generate")
            .map(|s| s.parse().unwrap_or(false))
            .unwrap_or(false)
    }

    fn get_i18n_patterns(&self) -> Vec<String> {
        if let Some(patterns_str) = self.get_metadata("i18n_patterns") {
            patterns_str
                .split(',')
                .map(|p| p.trim().to_string())
                .collect()
        } else {
            // Default pattern based on component name
            vec![format!("{}-", self.component.to_lowercase())]
        }
    }

    fn get_template_params(&self) -> toml::Value {
        if let Some(ref props) = self.props {
            if let Some(template_params) = props.get("template_params") {
                return template_params.clone();
            }
        }
        toml::Value::Table(toml::map::Map::new())
    }
}
