//! Documentation generator: creates comprehensive project documentation.

use crate::error::Result;
use crate::models::ProjectSpec;
use crate::template::TemplateLoader;
use std::path::Path;
use tera::Context;

/// Generates project documentation using templates.
pub struct DocumentationGenerator;

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

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

        // Prepare template context
        let mut context = Context::new();
        context.insert("project_name", &spec.name);
        context.insert("project_type", &format!("{:?}", spec.project_type));
        context.insert("features", &spec.domain_features);
        context.insert("infrastructure", &spec.infrastructure);

        // Generate main README
        Self::generate_readme(spec, output_dir, template_loader, &context)?;

        // Generate quickstart guide
        Self::generate_quickstart(spec, &docs_dir, template_loader, &context)?;

        // Generate nickel-roundtrip workflow documentation
        Self::generate_nickel_roundtrip_guide(spec, &docs_dir, template_loader, &context)?;

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

    /// Generate main project README.md.
    fn generate_readme(
        _spec: &ProjectSpec,
        output_dir: &Path,
        template_loader: &TemplateLoader,
        context: &Context,
    ) -> Result<()> {
        let readme = template_loader.render("docs/readme.md.tera", context)?;
        let readme_file = output_dir.join("README.md");
        std::fs::write(&readme_file, readme).map_err(|e| {
            crate::error::ProvisioningGenError::Other(format!("Failed to write README.md: {}", e))
        })?;

        tracing::debug!("Generated README.md");
        Ok(())
    }

    /// Generate quickstart guide.
    fn generate_quickstart(
        _spec: &ProjectSpec,
        docs_dir: &Path,
        template_loader: &TemplateLoader,
        context: &Context,
    ) -> Result<()> {
        let quickstart = template_loader.render("docs/quickstart.md.tera", context)?;
        let quickstart_file = docs_dir.join("quickstart.md");
        std::fs::write(&quickstart_file, quickstart).map_err(|e| {
            crate::error::ProvisioningGenError::Other(format!(
                "Failed to write quickstart.md: {}",
                e
            ))
        })?;

        tracing::debug!("Generated quickstart.md");
        Ok(())
    }

    /// Generate nickel-roundtrip workflow documentation.
    fn generate_nickel_roundtrip_guide(
        _spec: &ProjectSpec,
        docs_dir: &Path,
        template_loader: &TemplateLoader,
        context: &Context,
    ) -> Result<()> {
        let roundtrip = template_loader.render("docs/nickel-roundtrip.md.tera", context)?;
        let roundtrip_file = docs_dir.join("nickel-roundtrip.md");
        std::fs::write(&roundtrip_file, roundtrip).map_err(|e| {
            crate::error::ProvisioningGenError::Other(format!(
                "Failed to write nickel-roundtrip.md: {}",
                e
            ))
        })?;

        tracing::debug!("Generated nickel-roundtrip.md");
        Ok(())
    }
}
