#!/usr/bin/env nu

# Rustelo Prerequisites Installer
# Installs Rust, Node.js/pnpm, Nushell, and Just for Rustelo development

def main [
    --skip-rust          # Skip Rust installation
    --skip-node          # Skip Node.js/pnpm installation
    --skip-nushell       # Skip Nushell installation
    --skip-just          # Skip Just installation
    --verbose (-v)       # Verbose output
] {
    print "🚀 Installing Rustelo Prerequisites..."
    print ""

    let os_info = get_os_info

    if $verbose {
        print $"Detected OS: ($os_info.os) on ($os_info.arch)"
        print ""
    }

    # Install Rust
    if not $skip_rust {
        install_rust $os_info $verbose
    }

    # Install Node.js and pnpm
    if not $skip_node {
        install_node $os_info $verbose
    }

    # Install Nushell
    if not $skip_nushell {
        install_nushell $os_info $verbose
    }

    # Install Just
    if not $skip_just {
        install_just $os_info $verbose
    }

    print ""
    print "✅ Prerequisites installation complete!"
    print ""
    print "🎯 Next steps:"
    print "  1. Restart your terminal or run: source ~/.bashrc (or ~/.zshrc)"
    print "  2. Verify installations: nu scripts/verify-prerequisites.nu"
    print "  3. Create your first project: rustelo new my-website"
    print ""
}

def get_os_info [] {
    let os = (sys | get host.name)
    let arch = (sys | get host.cpu | first | get brand | str replace ".*" "unknown")

    if ($env.OS? | default "" | str contains "Windows") {
        { os: "windows", arch: "x86_64" }
    } else if (which uname | is-not-empty) {
        let uname_os = (uname -s)
        let uname_arch = (uname -m)

        match [$uname_os, $uname_arch] {
            ["Darwin", "x86_64"] => { os: "macos", arch: "x86_64" }
            ["Darwin", "arm64"] => { os: "macos", arch: "aarch64" }
            ["Linux", "x86_64"] => { os: "linux", arch: "x86_64" }
            ["Linux", "aarch64"] => { os: "linux", arch: "aarch64" }
            _ => { os: "linux", arch: "x86_64" }
        }
    } else {
        { os: "linux", arch: "x86_64" }
    }
}

def install_rust [os_info: record, verbose: bool] {
    print "📦 Installing Rust..."

    if (which rustc | is-not-empty) {
        let version = (rustc --version | str trim)
        print $"  ✅ Rust already installed: ($version)"
        return
    }

    match $os_info.os {
        "windows" => {
            print "  🔽 Downloading Rust installer for Windows..."
            print "  ⚠️  Please run the installer manually from: https://rustup.rs/"
        }
        _ => {
            print "  🔽 Installing Rust via rustup..."
            if $verbose {
                bash -c "curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y"
            } else {
                bash -c "curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y" | ignore
            }

            # Source the cargo env
            $env.PATH = ($env.PATH | split row ":" | append $"($env.HOME)/.cargo/bin" | uniq)
        }
    }

    print "  ✅ Rust installation complete"
}

def install_node [os_info: record, verbose: bool] {
    print "📦 Installing Node.js and pnpm..."

    # Check if Node.js is already installed
    if (which node | is-not-empty) {
        let node_version = (node --version | str trim)
        print $"  ✅ Node.js already installed: ($node_version)"

        # Check pnpm
        if (which pnpm | is-not-empty) {
            let pnpm_version = (pnpm --version | str trim)
            print $"  ✅ pnpm already installed: ($pnpm_version)"
            return
        }
    }

    match $os_info.os {
        "macos" => {
            if (which brew | is-not-empty) {
                print "  🔽 Installing via Homebrew..."
                if $verbose {
                    brew install node pnpm
                } else {
                    brew install node pnpm | ignore
                }
            } else {
                print "  ⚠️  Homebrew not found. Please install Node.js manually from: https://nodejs.org/"
                print "  Then run: npm install -g pnpm"
            }
        }
        "linux" => {
            # Try different package managers
            if (which apt | is-not-empty) {
                print "  🔽 Installing via apt..."
                if $verbose {
                    sudo apt update
                    sudo apt install -y nodejs npm
                    sudo npm install -g pnpm
                } else {
                    sudo apt update | ignore
                    sudo apt install -y nodejs npm | ignore
                    sudo npm install -g pnpm | ignore
                }
            } else if (which dnf | is-not-empty) {
                print "  🔽 Installing via dnf..."
                if $verbose {
                    sudo dnf install -y nodejs npm
                    sudo npm install -g pnpm
                } else {
                    sudo dnf install -y nodejs npm | ignore
                    sudo npm install -g pnpm | ignore
                }
            } else if (which pacman | is-not-empty) {
                print "  🔽 Installing via pacman..."
                if $verbose {
                    sudo pacman -S nodejs npm
                    sudo npm install -g pnpm
                } else {
                    sudo pacman -S nodejs npm | ignore
                    sudo npm install -g pnpm | ignore
                }
            } else {
                print "  ⚠️  Package manager not found. Please install Node.js manually from: https://nodejs.org/"
                print "  Then run: npm install -g pnpm"
            }
        }
        "windows" => {
            if (which winget | is-not-empty) {
                print "  🔽 Installing via winget..."
                if $verbose {
                    winget install OpenJS.NodeJS
                    npm install -g pnpm
                } else {
                    winget install OpenJS.NodeJS | ignore
                    npm install -g pnpm | ignore
                }
            } else {
                print "  ⚠️  winget not found. Please install Node.js manually from: https://nodejs.org/"
                print "  Then run: npm install -g pnpm"
            }
        }
    }

    print "  ✅ Node.js and pnpm installation complete"
}

def install_nushell [os_info: record, verbose: bool] {
    print "📦 Installing Nushell..."

    if (which nu | is-not-empty) {
        let version = (nu --version | str trim)
        print $"  ✅ Nushell already installed: ($version)"
        return
    }

    match $os_info.os {
        "macos" => {
            if (which brew | is-not-empty) {
                print "  🔽 Installing via Homebrew..."
                if $verbose {
                    brew install nushell
                } else {
                    brew install nushell | ignore
                }
            } else {
                install_nushell_from_github $os_info $verbose
            }
        }
        "linux" => {
            # Try package managers first
            if (which cargo | is-not-empty) and (which apt | is-not-empty) {
                print "  🔽 Installing via cargo (recommended)..."
                if $verbose {
                    cargo install nu --features=extra
                } else {
                    cargo install nu --features=extra | ignore
                }
            } else {
                install_nushell_from_github $os_info $verbose
            }
        }
        "windows" => {
            if (which winget | is-not-empty) {
                print "  🔽 Installing via winget..."
                if $verbose {
                    winget install nushell.nushell
                } else {
                    winget install nushell.nushell | ignore
                }
            } else if (which cargo | is-not-empty) {
                print "  🔽 Installing via cargo..."
                if $verbose {
                    cargo install nu --features=extra
                } else {
                    cargo install nu --features=extra | ignore
                }
            } else {
                print "  ⚠️  Please install Nushell manually from: https://github.com/nushell/nushell/releases"
            }
        }
    }

    print "  ✅ Nushell installation complete"
}

def install_nushell_from_github [os_info: record, verbose: bool] {
    print "  🔽 Installing from GitHub releases..."

    let arch_map = {
        "x86_64": "x86_64",
        "aarch64": "aarch64",
        "arm64": "aarch64"
    }

    let os_map = {
        "linux": "unknown-linux-gnu",
        "macos": "apple-darwin",
        "windows": "pc-windows-msvc"
    }

    let arch = ($arch_map | get ($os_info.arch | default "x86_64"))
    let os_suffix = ($os_map | get ($os_info.os | default "linux"))
    let extension = if ($os_info.os == "windows") { "zip" } else { "tar.gz" }

    let filename = $"nu-0.88.1-($arch)-($os_suffix).($extension)"
    let url = $"https://github.com/nushell/nushell/releases/download/0.88.1/($filename)"

    print $"  📥 Downloading: ($filename)"

    try {
        if ($os_info.os == "windows") {
            # Windows ZIP extraction
            curl -fsSL $url -o $"/tmp/($filename)"
            # Manual extraction needed on Windows
            print "  ⚠️  Please extract the downloaded file and add nu.exe to your PATH"
        } else {
            # Unix tar.gz extraction
            let extract_cmd = $"curl -fsSL ($url) | tar -xz && sudo mv nu* /usr/local/bin/"
            if $verbose {
                bash -c $extract_cmd
            } else {
                bash -c $extract_cmd | ignore
            }
        }
    } catch {
        print "  ❌ Failed to download Nushell. Please install manually from:"
        print "     https://github.com/nushell/nushell/releases"
    }
}

def install_just [os_info: record, verbose: bool] {
    print "📦 Installing Just..."

    if (which just | is-not-empty) {
        let version = (just --version | str trim)
        print $"  ✅ Just already installed: ($version)"
        return
    }

    match $os_info.os {
        "macos" => {
            if (which brew | is-not-empty) {
                print "  🔽 Installing via Homebrew..."
                if $verbose {
                    brew install just
                } else {
                    brew install just | ignore
                }
            } else if (which cargo | is-not-empty) {
                print "  🔽 Installing via cargo..."
                if $verbose {
                    cargo install just
                } else {
                    cargo install just | ignore
                }
            }
        }
        "linux" => {
            if (which cargo | is-not-empty) {
                print "  🔽 Installing via cargo..."
                if $verbose {
                    cargo install just
                } else {
                    cargo install just | ignore
                }
            } else {
                install_just_from_github $os_info $verbose
            }
        }
        "windows" => {
            if (which cargo | is-not-empty) {
                print "  🔽 Installing via cargo..."
                if $verbose {
                    cargo install just
                } else {
                    cargo install just | ignore
                }
            } else {
                print "  ⚠️  Please install Just manually: cargo install just"
                print "     Or download from: https://github.com/casey/just/releases"
            }
        }
    }

    print "  ✅ Just installation complete"
}

def install_just_from_github [os_info: record, verbose: bool] {
    print "  🔽 Installing from GitHub releases..."

    let arch = match $os_info.arch {
        "aarch64" => "aarch64",
        "arm64" => "aarch64",
        _ => "x86_64"
    }

    let os_suffix = match $os_info.os {
        "linux" => "unknown-linux-musl",
        "macos" => "apple-darwin",
        _ => "unknown-linux-musl"
    }

    let filename = $"just-1.16.0-($arch)-($os_suffix).tar.gz"
    let url = $"https://github.com/casey/just/releases/download/1.16.0/($filename)"

    try {
        let extract_cmd = $"curl -fsSL ($url) | tar -xz && sudo mv just /usr/local/bin/"
        if $verbose {
            bash -c $extract_cmd
        } else {
            bash -c $extract_cmd | ignore
        }
    } catch {
        print "  ❌ Failed to download Just. Please install via cargo: cargo install just"
    }
}

# Run the installer
main
