//! Deployment functionality for documentation and applications

use std::path::Path;

use anyhow::Result;

/// Deploy documentation to specified target
pub fn deploy_docs(target: &str) -> Result<()> {
    match target {
        "github-pages" => deploy_to_github_pages(),
        "netlify" => deploy_to_netlify(),
        "vercel" => deploy_to_vercel(),
        "s3" => deploy_to_s3(),
        "local" => deploy_to_local(),
        _ => {
            println!("⚠️ Unknown deployment target: {}", target);
            println!("📋 Available targets: github-pages, netlify, vercel, s3, local");
            Ok(())
        }
    }
}

/// Deploy documentation or applications (legacy)
pub fn deploy_project(target: &str, config: &str) -> Result<()> {
    println!("🚀 Deploying to {}...", target);
    println!("   Using config: {}", config);
    deploy_docs(target)
}

/// Deploy to GitHub Pages
fn deploy_to_github_pages() -> Result<()> {
    println!("  🐙 Deploying to GitHub Pages...");

    // Check if documentation exists
    if !Path::new("target/doc").exists() {
        println!("  ⚠️ No documentation found. Generating first...");
        generate_documentation()?;
    }

    // Simple approach: create a deployment script
    create_gh_pages_script()?;

    println!("  ✅ GitHub Pages deployment script created!");
    println!("  📝 Run: ./deploy-gh-pages.sh to deploy");

    Ok(())
}

/// Deploy to Netlify
fn deploy_to_netlify() -> Result<()> {
    println!("  🌐 Deploying to Netlify...");

    // Check if netlify CLI is available
    let output = std::process::Command::new("netlify")
        .args(["--version"])
        .output();

    match output {
        Ok(_) => {
            println!("  🔧 Using Netlify CLI...");

            if !Path::new("target/doc").exists() {
                generate_documentation()?;
            }

            let deploy_output = std::process::Command::new("netlify")
                .args(["deploy", "--prod", "--dir", "target/doc"])
                .output()?;

            if deploy_output.status.success() {
                println!("  ✅ Documentation deployed to Netlify!");
                println!("{}", String::from_utf8_lossy(&deploy_output.stdout));
            } else {
                println!("  ❌ Netlify deployment failed:");
                println!("{}", String::from_utf8_lossy(&deploy_output.stderr));
            }
        }
        Err(_) => {
            println!("  ⚠️ Netlify CLI not found. Install with:");
            println!("     npm install -g netlify-cli");
            println!("  📖 Manual deployment:");
            println!("     1. Build documentation: cargo doc");
            println!("     2. Upload target/doc/ to Netlify");
        }
    }

    Ok(())
}

/// Deploy to Vercel
fn deploy_to_vercel() -> Result<()> {
    println!("  ▲ Deploying to Vercel...");

    // Check if vercel CLI is available
    let output = std::process::Command::new("vercel")
        .args(["--version"])
        .output();

    match output {
        Ok(_) => {
            println!("  🔧 Using Vercel CLI...");

            if !Path::new("target/doc").exists() {
                generate_documentation()?;
            }

            // Create vercel.json if it doesn't exist
            create_vercel_config()?;

            let deploy_output = std::process::Command::new("vercel")
                .args(["--prod", "target/doc"])
                .output()?;

            if deploy_output.status.success() {
                println!("  ✅ Documentation deployed to Vercel!");
                println!("{}", String::from_utf8_lossy(&deploy_output.stdout));
            } else {
                println!("  ❌ Vercel deployment failed:");
                println!("{}", String::from_utf8_lossy(&deploy_output.stderr));
            }
        }
        Err(_) => {
            println!("  ⚠️ Vercel CLI not found. Install with:");
            println!("     npm install -g vercel");
            println!("  📖 Manual deployment:");
            println!("     1. Build documentation: cargo doc");
            println!("     2. Upload target/doc/ to Vercel");
        }
    }

    Ok(())
}

/// Deploy to S3
fn deploy_to_s3() -> Result<()> {
    println!("  🪣 Deploying to AWS S3...");

    // Check if AWS CLI is available
    let output = std::process::Command::new("aws")
        .args(["--version"])
        .output();

    match output {
        Ok(_) => {
            println!("  🔧 Using AWS CLI...");

            if !Path::new("target/doc").exists() {
                generate_documentation()?;
            }

            // Get S3 bucket from environment
            let bucket =
                std::env::var("DOCS_S3_BUCKET").unwrap_or_else(|_| "rustelo-docs".to_string());

            println!("  📤 Uploading to S3 bucket: {}", bucket);

            let sync_output = std::process::Command::new("aws")
                .args([
                    "s3",
                    "sync",
                    "target/doc/",
                    &format!("s3://{}/", bucket),
                    "--delete",
                    "--cache-control",
                    "max-age=86400",
                ])
                .output()?;

            if sync_output.status.success() {
                println!("  ✅ Documentation deployed to S3!");
                println!(
                    "  🔗 Available at: https://{}.s3.amazonaws.com/index.html",
                    bucket
                );
            } else {
                println!("  ❌ S3 deployment failed:");
                println!("{}", String::from_utf8_lossy(&sync_output.stderr));
            }
        }
        Err(_) => {
            println!("  ⚠️ AWS CLI not found. Install and configure AWS CLI first.");
        }
    }

    Ok(())
}

/// Deploy to local directory
fn deploy_to_local() -> Result<()> {
    println!("  📁 Deploying to local directory...");

    let deploy_dir = std::env::var("DOCS_DEPLOY_DIR").unwrap_or_else(|_| "deploy/docs".to_string());

    if !Path::new("target/doc").exists() {
        generate_documentation()?;
    }

    // Create deployment directory
    std::fs::create_dir_all(&deploy_dir)?;

    // Copy documentation
    copy_dir_recursive("target/doc", &deploy_dir)?;

    println!("  ✅ Documentation deployed to: {}", deploy_dir);
    println!("  🔗 Open: {}/index.html", deploy_dir);

    Ok(())
}

/// Generate documentation if needed
fn generate_documentation() -> Result<()> {
    println!("  📚 Generating documentation...");

    let output = std::process::Command::new("cargo")
        .args(["doc", "--no-deps"])
        .output()?;

    if output.status.success() {
        println!("  ✅ Documentation generated!");
    } else {
        println!("  ❌ Documentation generation failed:");
        println!("{}", String::from_utf8_lossy(&output.stderr));
    }

    Ok(())
}

/// Create GitHub Pages deployment script
fn create_gh_pages_script() -> Result<()> {
    let script_content = r#"#!/bin/bash

# GitHub Pages Deployment Script
# Generated by Rustelo Tools

set -e

echo "📚 Generating documentation..."
cargo doc --no-deps

echo "🌳 Setting up gh-pages worktree..."
if [ ! -d "gh-pages" ]; then
    git worktree add gh-pages gh-pages || {
        echo "🌱 Creating gh-pages branch..."
        git checkout --orphan gh-pages
        git rm -rf .
        git commit --allow-empty -m "Initial gh-pages commit"
        git push origin gh-pages
        git checkout main
        git worktree add gh-pages gh-pages
    }
fi

echo "📦 Copying documentation..."
rm -rf gh-pages/*
cp -r target/doc/* gh-pages/

echo "🚀 Deploying to GitHub Pages..."
cd gh-pages
git add .
if git diff --staged --quiet; then
    echo "✅ No changes to deploy"
else
    git commit -m "Deploy documentation $(date)"
    git push origin gh-pages
    echo "✅ Documentation deployed!"
fi

cd ..
echo "🌐 Documentation available at: https://$(git config --get remote.origin.url | sed 's/.*:\/\/github.com\///; s/\.git$//' | sed 's/\//\.github\.io\//').github.io/$(basename $(pwd))"
"#;

    std::fs::write("deploy-gh-pages.sh", script_content)?;

    // Make script executable
    #[cfg(unix)]
    {
        use std::os::unix::fs::PermissionsExt;
        let mut perms = std::fs::metadata("deploy-gh-pages.sh")?.permissions();
        perms.set_mode(0o755);
        std::fs::set_permissions("deploy-gh-pages.sh", perms)?;
    }

    println!("  📝 Created deployment script: deploy-gh-pages.sh");

    Ok(())
}

/// Create Vercel configuration
fn create_vercel_config() -> Result<()> {
    let vercel_config = r#"{
  "version": 2,
  "name": "rustelo-docs",
  "builds": [
    {
      "src": "**/*",
      "use": "@vercel/static"
    }
  ],
  "routes": [
    {
      "src": "/(.*)",
      "dest": "/$1"
    }
  ]
}"#;

    if !Path::new("vercel.json").exists() {
        std::fs::write("vercel.json", vercel_config)?;
        println!("  📄 Created vercel.json configuration");
    }

    Ok(())
}

/// Copy directory recursively
fn copy_dir_recursive<P1: AsRef<Path>, P2: AsRef<Path>>(src: P1, dst: P2) -> Result<()> {
    let src = src.as_ref();
    let dst = dst.as_ref();

    std::fs::create_dir_all(dst)?;

    for entry in std::fs::read_dir(src)? {
        let entry = entry?;
        let src_path = entry.path();
        let dst_path = dst.join(entry.file_name());

        if src_path.is_dir() {
            copy_dir_recursive(&src_path, &dst_path)?;
        } else {
            std::fs::copy(&src_path, &dst_path)?;
        }
    }

    Ok(())
}
