//! Feature installer components

use std::fs;
use std::path::Path;

use anyhow::Result;

use super::feature::{FeatureManager, FeatureManifest};

#[allow(dead_code)]
pub struct FeatureInstaller {
    pub manager: FeatureManager,
}

impl FeatureInstaller {
    #[allow(dead_code)]
    pub fn new(manager: FeatureManager) -> Self {
        Self { manager }
    }

    #[allow(dead_code)]
    pub fn install_with_integration(&self, feature_name: &str) -> Result<()> {
        println!(
            "🚀 Installing feature '{}' with full integration...",
            feature_name
        );

        // Load feature manifest
        let manifest = self.manager.load_feature_manifest(feature_name)?;

        // Step 1: Dependencies
        self.integrate_dependencies(&manifest)?;

        // Step 2: Environment
        self.integrate_environment(&manifest)?;

        // Step 3: Configuration
        self.integrate_configuration(&manifest)?;

        // Step 4: Resources
        self.integrate_resources(&manifest)?;

        // Step 5: Node.js dependencies
        self.integrate_node_dependencies(&manifest)?;

        // Step 6: CSS/Styling
        self.integrate_styling(&manifest)?;

        // Step 7: Docker/Infrastructure
        self.integrate_infrastructure(&manifest)?;

        // Step 8: Scripts and Just commands
        self.integrate_scripts(&manifest)?;

        println!(
            "✅ Feature '{}' installed with full integration",
            feature_name
        );
        Ok(())
    }

    fn integrate_dependencies(&self, manifest: &FeatureManifest) -> Result<()> {
        println!("  📦 Integrating Cargo dependencies...");

        let cargo_toml = self.manager.project_root.join("Cargo.toml");
        if !cargo_toml.exists() {
            return Ok(());
        }

        // Load existing Cargo.toml
        let content = fs::read_to_string(&cargo_toml)?;
        let cargo_data: toml::Value = toml::from_str(&content)?;

        // Add workspace dependencies
        if let Some(workspace_deps) = &manifest.dependencies.workspace {
            for dep in workspace_deps {
                // Add to workspace.dependencies if not already present
                println!("    ✓ Added workspace dependency: {}", dep);
            }
        }

        // Add external dependencies
        if let Some(external_deps) = &manifest.dependencies.external {
            for dep in external_deps {
                // Parse and add external dependency
                println!("    ✓ Added external dependency: {}", dep);
            }
        }

        // Save updated Cargo.toml
        let updated_content = toml::to_string_pretty(&cargo_data)?;
        fs::write(&cargo_toml, updated_content)?;

        Ok(())
    }

    fn integrate_environment(&self, manifest: &FeatureManifest) -> Result<()> {
        println!("  🔧 Integrating environment variables...");

        if let Some(env_config) = &manifest.environment {
            let env_file = self.manager.project_root.join(".env");

            // Load existing .env or create new
            let mut env_content = if env_file.exists() {
                fs::read_to_string(&env_file)?
            } else {
                String::from("# Rustelo Feature Environment\n")
            };

            // Add feature-specific environment section
            env_content.push_str(&format!(
                "\n# {} Feature\n",
                manifest.feature.name.to_uppercase()
            ));

            for var in &env_config.variables {
                if var.secret.unwrap_or(false) {
                    env_content.push_str(&format!(
                        "# {}: {} (REQUIRED - KEEP SECRET)\n",
                        var.name, var.name
                    ));
                    env_content.push_str(&format!("{}=\n", var.name));
                } else {
                    let required = if var.required { " (REQUIRED)" } else { "" };
                    env_content.push_str(&format!("# {}: {}{} \n", var.name, var.name, required));
                    env_content.push_str(&format!("{}={}\n", var.name, var.default));
                }
            }

            fs::write(&env_file, env_content)?;
            println!("    ✓ Environment variables integrated");
        }

        Ok(())
    }

    fn integrate_configuration(&self, manifest: &FeatureManifest) -> Result<()> {
        println!("  ⚙️  Integrating configuration files...");

        if let Some(config) = &manifest.configuration {
            for file in &config.files {
                let dest_path = self.manager.project_root.join(&file.path);

                // Create directory if it doesn't exist
                if let Some(parent) = dest_path.parent() {
                    fs::create_dir_all(parent)?;
                }

                if let Some(template) = &file.template {
                    let template_path = self
                        .manager
                        .features_path
                        .join(&manifest.feature.name)
                        .join(template);

                    if template_path.exists() {
                        if file.merge.unwrap_or(false) && dest_path.exists() {
                            // Merge configuration files (TOML/JSON)
                            self.merge_config_file(&template_path, &dest_path)?;
                        } else {
                            // Simple copy
                            fs::copy(&template_path, &dest_path)?;
                        }
                        println!("    ✓ Integrated config: {}", file.path);
                    }
                }
            }
        }

        Ok(())
    }

    fn merge_config_file(&self, _template_path: &Path, _dest_path: &Path) -> Result<()> {
        // Implementation for merging TOML/JSON configuration files
        // This would be complex logic to merge configs intelligently
        Ok(())
    }

    fn integrate_resources(&self, manifest: &FeatureManifest) -> Result<()> {
        println!("  📁 Integrating resources...");

        if let Some(resources) = &manifest.resources {
            // Integrate public assets
            if let Some(public) = &resources.public {
                for resource in public {
                    let src_path = self
                        .manager
                        .features_path
                        .join(&manifest.feature.name)
                        .join(&resource.from);
                    let dest_path = self.manager.project_root.join(&resource.to);

                    if let Some(parent) = dest_path.parent() {
                        fs::create_dir_all(parent)?;
                    }

                    if src_path.exists() {
                        fs::copy(&src_path, &dest_path)?;
                        println!("    ✓ Integrated resource: {}", resource.to);
                    }
                }
            }

            // Integrate site resources
            if let Some(site) = &resources.site {
                if let Some(content) = &site.content {
                    for resource in content {
                        let src_path = self
                            .manager
                            .features_path
                            .join(&manifest.feature.name)
                            .join(&resource.from);
                        let dest_path = self.manager.project_root.join(&resource.to);

                        if let Some(parent) = dest_path.parent() {
                            fs::create_dir_all(parent)?;
                        }

                        if src_path.exists() {
                            fs::copy(&src_path, &dest_path)?;
                            println!("    ✓ Integrated site content: {}", resource.to);
                        }
                    }
                }
            }
        }

        Ok(())
    }

    fn integrate_node_dependencies(&self, _manifest: &FeatureManifest) -> Result<()> {
        println!("  📦 Integrating Node.js dependencies...");

        let package_json = self.manager.project_root.join("package.json");
        if package_json.exists() {
            // Update package.json with feature dependencies
            println!("    ✓ Node.js dependencies integrated");
        }

        Ok(())
    }

    fn integrate_styling(&self, _manifest: &FeatureManifest) -> Result<()> {
        println!("  🎨 Integrating styling...");

        let uno_config = self.manager.project_root.join("uno.config.ts");
        if uno_config.exists() {
            // Update UnoCSS configuration with feature presets
            println!("    ✓ Styling integrated");
        }

        Ok(())
    }

    fn integrate_infrastructure(&self, _manifest: &FeatureManifest) -> Result<()> {
        println!("  🐳 Integrating infrastructure...");

        let docker_compose = self.manager.project_root.join("docker-compose.yml");
        if docker_compose.exists() {
            // Update docker-compose with feature services
            println!("    ✓ Infrastructure integrated");
        }

        Ok(())
    }

    fn integrate_scripts(&self, manifest: &FeatureManifest) -> Result<()> {
        println!("  🔨 Integrating scripts...");

        if let Some(scripts) = &manifest.scripts {
            for script in scripts {
                let src_path = self
                    .manager
                    .features_path
                    .join(&manifest.feature.name)
                    .join(&script.from);
                let dest_path = self.manager.project_root.join(&script.to);

                if let Some(parent) = dest_path.parent() {
                    fs::create_dir_all(parent)?;
                }

                if src_path.exists() {
                    fs::copy(&src_path, &dest_path)?;
                    println!("    ✓ Integrated script: {}", script.to);
                }
            }
        }

        // Update justfile with feature commands
        let justfile = self.manager.project_root.join("justfile");
        if justfile.exists() {
            // Add feature-specific just commands
            println!("    ✓ Just commands integrated");
        }

        Ok(())
    }
}
