//! i18n Extractor
//!
//! Extracts multi-language documentation from Nickel schemas and generates
//! Fluent translation (.ftl) files for form localization.
//!
//! Supports extracting translations from doc comments in format:
//! - `doc "English text"` (default locale: en)
//! - Additional locales parsed from schema metadata

use super::schema_ir::NickelSchemaIR;
use crate::error::ErrorWrapper;
use crate::Result;
use std::collections::HashMap;
use std::path::Path;

/// Extractor for multi-language documentation from Nickel schemas
pub struct I18nExtractor;

impl I18nExtractor {
    /// Extract multi-language documentation and generate .ftl files
    ///
    /// Parses doc comments from all fields in the schema and generates
    /// Fluent translation files for each detected locale.
    ///
    /// # Arguments
    ///
    /// * `schema` - The Nickel schema with documented fields
    /// * `output_dir` - Directory to write .ftl files
    ///
    /// # Returns
    ///
    /// HashMap mapping field_name -> i18n_key (e.g., "app_name" -> "app-name-prompt")
    pub fn extract_and_generate(
        schema: &NickelSchemaIR,
        output_dir: &Path,
    ) -> Result<HashMap<String, String>> {
        let mut translations: HashMap<String, HashMap<String, String>> = HashMap::new();

        // Extract translations from all fields
        for field in &schema.fields {
            if let Some(doc) = &field.doc {
                // Parse multi-language doc comments
                let lang_docs = Self::parse_multi_lang_doc(doc);

                // Add to translations by locale
                for (locale, text) in lang_docs {
                    translations
                        .entry(locale)
                        .or_default()
                        .insert(field.flat_name.clone(), text);
                }
            }
        }

        // Generate .ftl files for each locale
        for (locale, messages) in &translations {
            let ftl_dir = output_dir.join(locale);
            std::fs::create_dir_all(&ftl_dir)
                .map_err(|e| ErrorWrapper::new(format!("Failed to create locale dir: {}", e)))?;

            let ftl_path = ftl_dir.join("forms.ftl");
            let ftl_content = Self::generate_ftl_content(messages);

            std::fs::write(&ftl_path, ftl_content)
                .map_err(|e| ErrorWrapper::new(format!("Failed to write .ftl file: {}", e)))?;
        }

        // Return mapping of field_name -> i18n_key
        let mut key_mapping = HashMap::new();
        for field in &schema.fields {
            let i18n_key = Self::field_name_to_i18n_key(&field.flat_name);
            key_mapping.insert(field.flat_name.clone(), i18n_key);
        }

        Ok(key_mapping)
    }

    /// Parse multi-language documentation from a field doc comment
    ///
    /// Handles format: "English text" (default to "en" locale)
    /// Future: Support "doc.es: Spanish text", "doc.fr: French text" format
    fn parse_multi_lang_doc(doc: &str) -> HashMap<String, String> {
        let mut result = HashMap::new();

        // For now, treat all doc as English (en)
        // In the future, parse format like: "en: English | es: Spanish | fr: French"
        if !doc.is_empty() {
            result.insert("en".to_string(), doc.to_string());
        }

        result
    }

    /// Generate Fluent (.ftl) content from messages
    fn generate_ftl_content(messages: &HashMap<String, String>) -> String {
        let mut content = String::new();
        content.push_str("# Form translations\n\n");

        // Sort for consistent output
        let mut sorted_keys: Vec<_> = messages.keys().collect();
        sorted_keys.sort();

        for key in sorted_keys {
            if let Some(text) = messages.get(key.as_str()) {
                let ftl_key = Self::field_name_to_i18n_key(key);
                // Escape quotes in text
                let escaped_text = text.replace('"', "\\\"");
                content.push_str(&format!("{}-prompt = {}\n", ftl_key, escaped_text));
                content.push_str(&format!("{}-help = {}\n\n", ftl_key, escaped_text));
            }
        }

        content
    }

    /// Convert field name to i18n key format
    ///
    /// "app_name" -> "app-name"
    /// "tls_cert_path" -> "tls-cert-path"
    fn field_name_to_i18n_key(field_name: &str) -> String {
        field_name.replace('_', "-")
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_field_name_to_i18n_key() {
        assert_eq!(
            I18nExtractor::field_name_to_i18n_key("app_name"),
            "app-name"
        );
        assert_eq!(
            I18nExtractor::field_name_to_i18n_key("tls_cert_path"),
            "tls-cert-path"
        );
        assert_eq!(
            I18nExtractor::field_name_to_i18n_key("database_url"),
            "database-url"
        );
    }

    #[test]
    fn test_parse_multi_lang_doc() {
        let doc = "Application name";
        let result = I18nExtractor::parse_multi_lang_doc(doc);

        assert_eq!(result.get("en"), Some(&"Application name".to_string()));
    }

    #[test]
    fn test_generate_ftl_content() {
        let mut messages = HashMap::new();
        messages.insert("app_name".to_string(), "Application name".to_string());
        messages.insert("app_version".to_string(), "Application version".to_string());

        let content = I18nExtractor::generate_ftl_content(&messages);

        assert!(content.contains("app-name-prompt"));
        assert!(content.contains("Application name"));
        assert!(content.contains("app-version-prompt"));
        assert!(content.contains("Application version"));
    }
}
