//! Locales generator: creates Fluent translation files for i18n support.

use crate::error::Result;
use crate::models::ProjectSpec;
use std::path::Path;

/// Generates Fluent translation files for internationalization.
pub struct LocalesGenerator;

impl LocalesGenerator {
    /// Generate locale files for all configured languages.
    pub fn generate(spec: &ProjectSpec, output_dir: impl AsRef<Path>) -> Result<()> {
        let output_dir = output_dir.as_ref();
        tracing::info!("Generating locale files for project: {}", spec.name);

        // Ensure locales directory exists
        let locales_dir = output_dir.join("locales");
        std::fs::create_dir_all(&locales_dir).map_err(|e| {
            crate::error::ProvisioningGenError::Other(format!(
                "Failed to create locales directory: {}",
                e
            ))
        })?;

        // Generate English locale (default)
        Self::generate_locale(spec, &locales_dir, "en-US")?;

        // Generate additional configured locales
        for locale_spec in &spec.locales {
            Self::generate_locale(spec, &locales_dir, &locale_spec.language_code)?;
        }

        // Generate README
        Self::generate_locales_readme(spec, &locales_dir)?;

        tracing::info!("Successfully generated locale files");
        Ok(())
    }

    /// Generate Fluent translation file for a specific locale.
    fn generate_locale(spec: &ProjectSpec, locales_dir: &Path, locale_code: &str) -> Result<()> {
        let mut fluent_content = String::new();

        fluent_content.push_str(&format!(
            "# Fluent translations for {} ({})\n",
            spec.name, locale_code
        ));
        fluent_content.push_str("# https://projectfluent.org/\n\n");

        // App-level strings
        fluent_content.push_str("## Application\n\n");
        fluent_content.push_str(&format!("app-name = {}\n", spec.name));
        fluent_content.push_str(&format!("app-title = {} Configuration\n", spec.name));
        fluent_content.push_str("app-description = Interactive configuration wizard\n\n");

        // Feature-specific strings
        for feature in &spec.domain_features {
            fluent_content.push_str(&format!("## {} Feature\n\n", feature.name));

            // Feature metadata
            fluent_content.push_str(&format!("{}-title = ", feature.name));
            if let Some(desc) = &feature.description {
                fluent_content.push_str(&format!("{}\n", desc));
            } else {
                fluent_content.push_str(&format!(
                    "{} Configuration\n",
                    Self::capitalize_first(&feature.name)
                ));
            }

            // Field labels and help text
            for field in &feature.fields {
                // Field prompt
                fluent_content.push_str(&format!(
                    "{}-{}-prompt = {}\n",
                    feature.name, field.name, field.prompt
                ));

                // Field help text
                if let Some(help) = &field.help {
                    fluent_content.push_str(&format!(
                        "{}-{}-help = {}\n",
                        feature.name, field.name, help
                    ));
                }

                // Placeholder
                if let Some(placeholder) = &field.placeholder {
                    fluent_content.push_str(&format!(
                        "{}-{}-placeholder = {}\n",
                        feature.name, field.name, placeholder
                    ));
                }
            }

            fluent_content.push('\n');
        }

        // Common UI strings
        fluent_content.push_str("## Common UI Strings\n\n");
        fluent_content.push_str("common-continue = Continue\n");
        fluent_content.push_str("common-back = Back\n");
        fluent_content.push_str("common-cancel = Cancel\n");
        fluent_content.push_str("common-finish = Finish\n");
        fluent_content.push_str("common-save = Save\n");
        fluent_content.push_str("common-required = Required\n");
        fluent_content.push_str("common-optional = Optional\n\n");

        // Validation messages
        fluent_content.push_str("## Validation Messages\n\n");
        fluent_content.push_str("validation-required = This field is required\n");
        fluent_content.push_str("validation-invalid = Invalid value\n");
        fluent_content.push_str("validation-too-short = Value is too short\n");
        fluent_content.push_str("validation-too-long = Value is too long\n");
        fluent_content.push_str("validation-out-of-range = Value out of range\n\n");

        // Success/error messages
        fluent_content.push_str("## Messages\n\n");
        fluent_content.push_str("success-saved = Configuration saved successfully\n");
        fluent_content.push_str("error-load-failed = Failed to load configuration\n");
        fluent_content.push_str("error-save-failed = Failed to save configuration\n");

        // Write locale file
        let locale_file = locales_dir.join(format!("{}.ftl", locale_code));
        std::fs::write(&locale_file, fluent_content).map_err(|e| {
            crate::error::ProvisioningGenError::Other(format!(
                "Failed to write {} locale file: {}",
                locale_code, e
            ))
        })?;

        tracing::debug!("Generated {} locale file", locale_code);
        Ok(())
    }

    /// Generate README.md for locales directory.
    fn generate_locales_readme(spec: &ProjectSpec, locales_dir: &Path) -> Result<()> {
        let mut content = String::new();

        content.push_str(&format!("# Localization - {}\n\n", spec.name));

        content.push_str(
            "This directory contains Fluent translation files for internationalization (i18n).\n\n\
             ## Overview\n\n\
             Fluent is a modern localization system designed for natural-sounding translations. \
             See https://projectfluent.org/ for more information.\n\n\
             ## Files\n\n\
             - `en-US.ftl` - English (United States) translations (default)\n",
        );

        for locale_spec in &spec.locales {
            content.push_str(&format!(
                "- `{}.ftl` - Translations for {}\n",
                locale_spec.language_code, locale_spec.language_code
            ));
        }

        content.push_str(
            "\n\
             ## Adding New Locales\n\n\
             1. Copy `en-US.ftl` to `<locale-code>.ftl` (e.g., `es-ES.ftl` for Spanish)\n\
             2. Translate all strings while preserving the message IDs\n\
             3. Update the form configuration to detect and use the new locale\n\n\
             ## Message Structure\n\n\
             Fluent messages follow this pattern:\n\n\
             ```fluent\n\
             # Comments\n\
             message-id = Translation text\n\
             message-with-variable = Hello, {{ $name }}!\n\
             ```\n\n\
             ## Usage in TypeDialog\n\n\
             Enable i18n support in forms:\n\n\
             ```toml\n\
             [form]\n\
             name = \"config\"\n\
             locale = \"en-US\"  # Default locale\n\
             locale_dir = \"locales\"  # Path to .ftl files\n\
             \n\
             [[fields]]\n\
             name = \"server_port\"\n\
             prompt_i18n = \"server-port-prompt\"  # References locale key\n\
             ```\n\n\
             TypeDialog will load the appropriate translation file based on the user's locale.\n\n",
        );

        let readme_file = locales_dir.join("README.md");
        std::fs::write(&readme_file, content).map_err(|e| {
            crate::error::ProvisioningGenError::Other(format!(
                "Failed to write locales README: {}",
                e
            ))
        })?;

        Ok(())
    }

    /// Capitalize first letter of a string.
    fn capitalize_first(s: &str) -> String {
        let mut chars = s.chars();
        match chars.next() {
            None => String::new(),
            Some(first) => first.to_uppercase().collect::<String>() + chars.as_str(),
        }
    }
}
