#!/usr/bin/env bash
set -u

# =============================
# COLORS & LOGGING
# =============================
GREEN="\033[0;32m"
RED="\033[0;31m"
YELLOW="\033[1;33m"
BLUE="\033[0;34m"
NC="\033[0m"

log()  { echo -e "${GREEN}▶ $*${NC}"; }
warn() { echo -e "${YELLOW}⚠ $*${NC}"; }
err()  { echo -e "${RED}✖ $*${NC}"; }
info() { echo -e "${BLUE}ℹ $*${NC}"; }

# =============================
# HELPERS & SYSTEM DETECTION
# =============================
require_cmd() { command -v "$1" >/dev/null 2>&1; }

add_to_path_config() {
    local label=$1
    local path_line=$2
    local target_file="${3:-$HOME/.pathrc}"
    
    if [[ -f "$target_file" ]]; then
        if ! grep -q "$label" "$target_file"; then
            echo -e "\n# $label\n$path_line" >> "$target_file"
            log "Added $label to $target_file"
        fi
    else
        echo -e "\n# $label\n$path_line" >> "$HOME/.bashrc"
        [[ -f "$HOME/.zshrc" ]] && echo -e "\n# $label\n$path_line" >> "$HOME/.zshrc"
        log "Added $label to shell profiles."
    fi
}

detect_os_arch() {
    ARCH=$(uname -m)
    case "$ARCH" in
        x86_64|amd64) SYS_ARCH="amd64"; MAC_ARCH="x86_64"; AWS_ARCH="x86_64" ;;
        aarch64|arm64) SYS_ARCH="arm64"; MAC_ARCH="arm64"; AWS_ARCH="aarch64" ;;
        *) err "Unsupported architecture: $ARCH"; exit 1 ;;
    esac

    if [[ "$OSTYPE" == "darwin"* ]]; then
        OS="macOS"
        OS_LOWER="darwin"
    elif grep -qi microsoft /proc/version 2>/dev/null; then
        OS="WSL"
        OS_LOWER="linux"
    elif [[ -f /etc/os-release ]]; then
        . /etc/os-release
        [[ "$ID" == "ubuntu" || "$ID_LIKE" == *"ubuntu"* ]] && OS="Ubuntu" || OS="Linux"
        OS_LOWER="linux"
    else
        OS="Unknown"
        OS_LOWER="unknown"
    fi
    log "Detected: $OS ($ARCH)"
}

detect_os_arch

# =============================
# CORE RUNTIMES & MANAGERS
# =============================

install_build_tools() {
    log "Installing Build Essentials & Core Dependencies..."
    case "$OS" in
        Ubuntu|WSL) sudo apt-get update && sudo apt-get install -y build-essential curl wget git jq unzip libssl-dev zlib1g-dev libffi-dev libsqlite3-dev ;;
        macOS) xcode-select --install || warn "Xcode tools already installed" ;;
        *) warn "Manual installation required for $OS." ;;
    esac
}

install_brew() {
    if require_cmd brew; then warn "Homebrew already installed"; return; fi
    log "Installing Homebrew from Official Source..."
    /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
    
    if [[ "$OS_LOWER" == "linux" ]]; then
        add_to_path_config "HOMEBREW" 'eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"'
    elif [[ "$MAC_ARCH" == "arm64" ]]; then
        add_to_path_config "HOMEBREW" 'eval "$(/opt/homebrew/bin/brew shellenv)"'
    else
        add_to_path_config "HOMEBREW" 'eval "$(/usr/local/bin/brew shellenv)"'
    fi
}

install_nvm() {
    export NVM_DIR="$HOME/.nvm"
    
    if [ -d "$NVM_DIR" ]; then 
        warn "NVM is already installed."
    else
        log "Installing NVM..."
        curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
    fi
    
    # Load NVM for the current session to ensure the 'nvm' command is available immediately
    [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
    
    echo -e "\n${YELLOW}Which version of Node.js would you like to install?${NC}"
    echo "  1) LTS (Long Term Support - Recommended for stability)"
    echo "  2) Latest (Current features - Recommended for testing new APIs)"
    echo "  3) Skip installing Node.js right now"
    read -p "Select (1/2/3): " node_choice

    case "$node_choice" in
        2)
            log "Installing Latest Node.js..."
            nvm install node
            nvm alias default node
            nvm use node
            ;;
        3)
            log "Skipping Node.js installation."
            ;;
        *)
            log "Installing Latest LTS Node.js..."
            nvm install --lts
            nvm alias default 'lts/*'
            nvm use --lts
            ;;
    esac
}

install_python() {
    log "Fetching latest Python 3 version from official API..."
    LATEST_PY=$(curl -s https://api.github.com/repos/python/cpython/releases/latest | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/')
    [[ -z "$LATEST_PY" ]] && LATEST_PY="3.12.3"
    
    log "Installing Python $LATEST_PY directly from Python.org..."
    if [[ "$OS" == "macOS" ]]; then
        PKG_URL="https://www.python.org/ftp/python/${LATEST_PY}/python-${LATEST_PY}-macos11.pkg"
        curl -fsSL -o /tmp/python.pkg "$PKG_URL"
        sudo installer -pkg /tmp/python.pkg -target /
        rm /tmp/python.pkg
    else
        SRC_URL="https://www.python.org/ftp/python/${LATEST_PY}/Python-${LATEST_PY}.tgz"
        curl -fsSL -o /tmp/Python.tgz "$SRC_URL"
        cd /tmp && tar -xzf Python.tgz && cd "Python-${LATEST_PY}"
        ./configure --enable-optimizations
        sudo make altinstall
        
        PY_MINOR=$(echo "$LATEST_PY" | cut -d. -f1,2)
        log "Symlinking python${PY_MINOR} to python3..."
        sudo ln -sf /usr/local/bin/python${PY_MINOR} /usr/local/bin/python3
        sudo ln -sf /usr/local/bin/pip${PY_MINOR} /usr/local/bin/pip3
        
        cd ~ && sudo rm -rf /tmp/Python*
    fi
}

install_go() {
    log "Fetching latest Go version from official source..."
    LATEST_GO=$(curl -sL https://go.dev/VERSION?m=text | head -n 1)
    TAR_FILE="${LATEST_GO}.${OS_LOWER}-${SYS_ARCH}.tar.gz"
    
    log "Downloading $TAR_FILE..."
    curl -fsSL -o /tmp/go.tar.gz "https://go.dev/dl/$TAR_FILE"
    
    log "Installing to /usr/local/go..."
    sudo rm -rf /usr/local/go
    sudo tar -C /usr/local -xzf /tmp/go.tar.gz
    rm /tmp/go.tar.gz
    add_to_path_config "GO_BIN" 'export PATH="$PATH:/usr/local/go/bin"'
}

install_sdkman() {
    if [ -d "$HOME/.sdkman" ]; then warn "SDKMAN already exists"; return; fi
    log "Installing SDKMAN..."
    curl -s "https://get.sdkman.io" | bash
}

install_dotnet() {
    log "Installing .NET from official script..."
    curl -fsSL https://dot.net/v1/dotnet-install.sh | bash
    add_to_path_config "DOTNET_TOOLS" 'export PATH="$PATH:$HOME/.dotnet/tools"'
}

# =============================
# CLOUD & INFRASTRUCTURE
# =============================

install_docker() {
    if require_cmd docker; then log "Docker exists"; else
        log "Installing Docker from official source..."

        if [[ "$OS" == "macOS" ]]; then
            [[ "$SYS_ARCH" == "arm64" ]] && DOCKER_MAC_ARCH="arm64" || DOCKER_MAC_ARCH="amd64"
            DMG_URL="https://desktop.docker.com/mac/main/${DOCKER_MAC_ARCH}/Docker.dmg"
            curl -fsSL -o /tmp/Docker.dmg "$DMG_URL"
            hdiutil attach /tmp/Docker.dmg -nobrowse -mountpoint /Volumes/Docker
            sudo cp -a /Volumes/Docker/Docker.app /Applications/
            hdiutil detach /Volumes/Docker
            rm /tmp/Docker.dmg
            
            log "Starting Docker Desktop..."
            open /Applications/Docker.app
            log "Please complete the setup in the Docker Desktop UI."
        else
            # Linux install
            curl -fsSL https://get.docker.com | sudo sh
        fi
    fi

    # Post-install logic for Linux (Ubuntu/WSL)
    if [[ "$OS" != "macOS" ]]; then
        log "Applying Linux post-install actions..."
        
        # 1. Create docker group and add user
        sudo groupadd -f docker
        sudo usermod -aG docker "$USER"
        
        # 2. Enable and start Docker services
        if command -v systemctl >/dev/null 2>&1; then
            sudo systemctl enable --now docker.service
            sudo systemctl enable --now containerd.service
        elif [[ "$OS" == "WSL" ]]; then
            sudo service docker start
        fi

        # 3. Immediate Socket Fix
        if [[ -S /var/run/docker.sock ]]; then
            log "Fixing ownership of /var/run/docker.sock..."
            sudo chown root:docker /var/run/docker.sock
            sudo chmod 660 /var/run/docker.sock
        fi

        log "Added $USER to the docker group."
        log "CRITICAL: To apply group changes immediately, run: newgrp docker"
    fi
}

install_aws() {
    if require_cmd aws; then warn "AWS CLI exists"; return; fi
    log "Installing AWS CLI directly from Amazon..."

    if [[ "$OS" == "macOS" ]]; then
        curl -fsSL -o /tmp/AWSCLIV2.pkg "https://awscli.amazonaws.com/AWSCLIV2.pkg"
        sudo installer -pkg /tmp/AWSCLIV2.pkg -target /
        rm /tmp/AWSCLIV2.pkg
    else
        if ! require_cmd unzip; then 
            err "unzip is required. Please install 'Build Tools' (Option 1) first."
            return 1
        fi
        curl -fsSL -o /tmp/awscliv2.zip "https://awscli.amazonaws.com/awscli-exe-linux-${AWS_ARCH}.zip"
        cd /tmp && unzip -q awscliv2.zip && sudo ./aws/install
        rm -rf /tmp/awscliv2.zip /tmp/aws
    fi
}

install_gcloud() {
    if require_cmd gcloud; then warn "Google Cloud CLI exists"; return; fi
    log "Installing Google Cloud CLI..."
    curl -fsSL https://sdk.cloud.google.com | bash -s -- --disable-prompts
    
    add_to_path_config "GCLOUD" '[ -f "$HOME/google-cloud-sdk/path.bash.inc" ] && . "$HOME/google-cloud-sdk/path.bash.inc"'
}

install_firebase() {
    if require_cmd firebase; then warn "Firebase CLI exists"; return; fi
    log "Installing Firebase CLI via NPM to ensure ARM64 compatibility..."
    
    if ! require_cmd npm; then
        err "NPM not found. Please install NVM (Option 3) first."
        return 1
    fi
    
    npm install -g firebase-tools
}

# =============================
# DEV TOOLS & SECURITY
# =============================

install_gh() {
    if require_cmd gh; then warn "GitHub CLI exists"; return; fi
    log "Fetching latest GitHub CLI version..."
    LATEST_GH=$(curl -s https://api.github.com/repos/cli/cli/releases/latest | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/')
    TAR_NAME="gh_${LATEST_GH}_${OS_LOWER}_${SYS_ARCH}"
    
    curl -fsSL -o /tmp/gh.tar.gz "https://github.com/cli/cli/releases/download/v${LATEST_GH}/${TAR_NAME}.tar.gz"
    tar -xzf /tmp/gh.tar.gz -C /tmp
    sudo mv "/tmp/${TAR_NAME}/bin/gh" /usr/local/bin/
    sudo rm -rf "/tmp/${TAR_NAME}" /tmp/gh.tar.gz
}

install_infisical() {
    if require_cmd infisical; then warn "Infisical CLI exists"; return; fi
    log "Installing Infisical CLI via NPM..."
    
    if ! require_cmd npm; then 
        err "NPM not found. Please install NVM (Option 3) first."
        return 1
    fi
    
    npm install -g @infisical/cli
}

# =============================
# AI & AGENTIC TOOLS
# =============================

install_claude() { log "Installing Claude Code..."; curl -fsSL https://claude.ai/install.sh | bash; }
install_opencode() { log "Installing OpenCode..."; curl -fsSL https://opencode.ai/install | bash; }

install_codex() {
    log "Installing @openai/codex..."
    if ! require_cmd npm; then err "Node.js/NPM is required. Install NVM (3) first."; return 1; fi
    npm i -g @openai/codex
}

# =============================
# MENU LOGIC
# =============================
show_menu() {
    clear
    echo -e "${BLUE}==================================================${NC}"
    echo -e "${GREEN}    DEVELOPER ENVIRONMENT INSTALLER (Strict)      ${NC}"
    echo -e "${BLUE}==================================================${NC}"
    echo -e "${YELLOW}--- Core Runtimes & Managers ---${NC}"
    echo "  1) Build Tools (GCC/Make)"
    echo "  2) Homebrew (Optional)"
    echo "  3) NVM (Node.js)"
    echo "  4) Python 3 (Official API)"
    echo "  5) Go (Official -> /usr/local)"
    echo "  6) SDKMAN (Java/Kotlin)"
    echo "  7) .NET (Official Script)"
    echo -e "${YELLOW}--- Cloud & Infrastructure ---${NC}"
    echo "  8) Docker (Official DMG/sh)"
    echo "  9) AWS CLI (Official Bin)"
    echo " 10) Google Cloud CLI (gcloud)"
    echo " 11) Firebase CLI (NPM/ARM64 Safe)"
    echo -e "${YELLOW}--- Dev Tools & Security ---${NC}"
    echo " 12) GitHub CLI (Official Bin)"
    echo " 13) Infisical (Official Bin)"
    echo -e "${YELLOW}--- AI & Agentic Tools ---${NC}"
    echo " 14) Claude Code CLI"
    echo " 15) OpenCode (opencode.ai)"
    echo " 16) OpenAI Codex CLI"
    echo -e "${BLUE}==================================================${NC}"
    echo " 99) Quit"
    echo -e "${BLUE}==================================================${NC}"
}

while true; do
    show_menu
    read -p "Select options (space-separated): " input
    for choice in $input; do
        case "$choice" in
            1) install_build_tools ;;
            2) install_brew ;;
            3) install_nvm ;;
            4) install_python ;;
            5) install_go ;;
            6) install_sdkman ;;
            7) install_dotnet ;;
            8) install_docker ;;
            9) install_aws ;;
           10) install_gcloud ;;
           11) install_firebase ;;
           12) install_gh ;;
           13) install_infisical ;;
           14) install_claude ;;
           15) install_opencode ;;
           16) install_codex ;;
           99) log "Exiting..."; exit 0 ;;
            *) warn "Option $choice not valid." ;;
        esac
    done
    read -p "Press Enter to continue..." 
done