#!/bin/bash
set -e

# Zinit Installer Script
# Downloads and installs zinit binaries for your platform from Forgejo
# Usage: curl https://example.com/install.sh | bash

INSTALL_DIR="$HOME/hero/bin"
PACKAGE_URL="https://forge.ourworld.tf/api/packages/geomind_code/generic/zinit/dev"

# Detect shell type
detect_shell() {
    case "$SHELL" in
        */fish) echo "fish" ;;
        */zsh) echo "zsh" ;;
        */bash) echo "bash" ;;
        *) echo "unknown" ;;
    esac
}

# Configure PATH based on shell
configure_path() {
    local shell_type=$1
    local path_line="export PATH=\"\$HOME/hero/bin:\$PATH\""
    local fish_path_line="set -x PATH \$HOME/hero/bin \$PATH"

    case "$shell_type" in
        bash)
            local rc_file="$HOME/.bashrc"
            ;;
        zsh)
            local rc_file="$HOME/.zshrc"
            ;;
        fish)
            local config_dir="$HOME/.config/fish"
            mkdir -p "$config_dir"
            local rc_file="$config_dir/config.fish"
            path_line="$fish_path_line"
            ;;
        *)
            local rc_file="$HOME/.profile"
            ;;
    esac

    if [ -f "$rc_file" ]; then
        if grep -q "hero/bin" "$rc_file"; then
            echo "PATH already configured in $rc_file"
        else
            echo "" >> "$rc_file"
            echo "# Zinit binary path" >> "$rc_file"
            echo "$path_line" >> "$rc_file"
            echo "Added to PATH in $rc_file"
        fi
    else
        echo "# Zinit binary path" > "$rc_file"
        echo "$path_line" >> "$rc_file"
        echo "Created $rc_file with PATH configuration"
    fi
}

# Verify binary works
verify_binary() {
    local binary=$1
    local output

    # Try to run the binary with --version flag
    if output=$("${INSTALL_DIR}/${binary}" --version 2>&1); then
        # Check if output contains version info (e.g., "zinit 0.3.8" or "zinit-server 0.3.8")
        if echo "$output" | grep -qE "^[a-z-]+ [0-9]+\.[0-9]+\.[0-9]+"; then
            return 0
        fi
    fi

    # Fallback: check if binary exists and is executable
    if [ -x "${INSTALL_DIR}/${binary}" ]; then
        return 0
    fi

    echo "Warning: $binary did not verify properly"
    echo "Output: $output"
    return 1
}

# Start zinit-server in background (macOS/Windows)
start_server_background() {
    local os=$1

    # Determine socket and config paths based on OS
    local SOCKET="$HOME/hero/var/zinit.sock"
    local CONFIG_DIR="$HOME/hero/cfg/zinit"

    echo "Starting zinit-server in background..."

    # Kill any existing zinit-server
    pkill -f "zinit-server" 2>/dev/null || true
    sleep 0.5
    pkill -9 -f "zinit-server" 2>/dev/null || true

    # Clean up old socket
    if [ -e "$SOCKET" ]; then
        rm -f "$SOCKET"
    fi

    # Create directories
    mkdir -p "$(dirname "$SOCKET")"
    mkdir -p "$CONFIG_DIR"

    # Test that binary works
    if ! "${INSTALL_DIR}/zinit-server" --version > /dev/null 2>&1; then
        echo "Warning: zinit-server binary may be corrupted or incompatible"
        echo "         Try rebuilding from source: make build"
        echo "         Or check the binary: file ${INSTALL_DIR}/zinit-server"
        return 1
    fi

    # Start server in background
    ZINIT_SOCKET="$SOCKET" \
    ZINIT_CONFIG_DIR="$CONFIG_DIR" \
    ZINIT_LOG_LEVEL="info" \
    "${INSTALL_DIR}/zinit-server" \
        > /tmp/zinit-server.log 2>&1 &
    SERVER_PID=$!

    # Wait for socket to be ready
    for i in {1..50}; do
        if [ -S "$SOCKET" ]; then
            break
        fi
        sleep 0.1
    done

    # Check if process is still running
    if ! kill -0 $SERVER_PID 2>/dev/null; then
        echo "Warning: zinit-server exited unexpectedly"
        echo "Check /tmp/zinit-server.log for details:"
        cat /tmp/zinit-server.log 2>/dev/null || echo "(empty log)"
        return 1
    fi

    if [ ! -S "$SOCKET" ]; then
        echo "Warning: zinit-server did not create socket"
        echo "Check /tmp/zinit-server.log for details:"
        cat /tmp/zinit-server.log 2>/dev/null || echo "(empty log)"
        return 1
    fi

    echo "✓ zinit-server started (PID: $SERVER_PID)"
    echo "  Socket: $SOCKET"
    echo "  Config: $CONFIG_DIR"
    echo "  Log:    /tmp/zinit-server.log"

    return 0
}

# Detect OS
detect_os() {
    case "$(uname -s)" in
        Linux*)  echo "linux" ;;
        Darwin*) echo "darwin" ;;
        *)       echo "unsupported" ;;
    esac
}

# Detect architecture
detect_arch() {
    case "$(uname -m)" in
        x86_64)  echo "amd64" ;;
        aarch64) echo "arm64" ;;
        arm64)   echo "arm64" ;;
        *)       echo "unsupported" ;;
    esac
}

# Main installation
main() {
    echo "Zinit Installer"
    echo "==============="
    echo ""

    OS=$(detect_os)
    ARCH=$(detect_arch)

    if [ "$OS" = "unsupported" ]; then
        echo "Error: Unsupported operating system: $(uname -s)"
        echo "Zinit currently supports:"
        echo "  - macOS (darwin) arm64"
        echo "  - Linux (linux) amd64"
        exit 1
    fi

    if [ "$ARCH" = "unsupported" ]; then
        echo "Error: Unsupported architecture: $(uname -m)"
        echo "Zinit currently supports:"
        echo "  - macOS (darwin) arm64"
        echo "  - Linux (linux) amd64"
        exit 1
    fi

    echo "Detected platform: ${OS}-${ARCH}"
    echo ""

    # Create install directory
    echo "Creating install directory: ${INSTALL_DIR}"
    mkdir -p "${INSTALL_DIR}"

    # Download binaries
    BINARIES=("zinit" "zinit-server")

    # On Linux, also download zinit-pid1
    if [ "$OS" = "linux" ]; then
        BINARIES+=("zinit-pid1")
    fi

    for binary in "${BINARIES[@]}"; do
        BINARY_NAME="${binary}-${OS}-${ARCH}"
        DOWNLOAD_URL="${PACKAGE_URL}/${BINARY_NAME}"

        echo "Downloading $binary..."
        if command -v curl &> /dev/null; then
            if ! curl -L -f -o "${INSTALL_DIR}/${binary}" "${DOWNLOAD_URL}"; then
                echo "Error: Failed to download $binary from ${DOWNLOAD_URL}"
                exit 1
            fi
        elif command -v wget &> /dev/null; then
            if ! wget -O "${INSTALL_DIR}/${binary}" "${DOWNLOAD_URL}"; then
                echo "Error: Failed to download $binary from ${DOWNLOAD_URL}"
                exit 1
            fi
        else
            echo "Error: Neither curl nor wget found. Please install one of them."
            exit 1
        fi

        # Make executable
        chmod +x "${INSTALL_DIR}/${binary}"
        echo "✓ Installed $binary"
    done

    echo ""
    echo "Verifying installations..."

    all_ok=true
    for binary in "${BINARIES[@]}"; do
        if verify_binary "$binary"; then
            echo "✓ $binary verified"
        else
            echo "✗ $binary verification failed (but may still work)"
            all_ok=false
        fi
    done

    echo ""

    # Configure PATH
    SHELL_TYPE=$(detect_shell)
    if [ "$SHELL_TYPE" != "unknown" ]; then
        echo "Configuring PATH..."
        configure_path "$SHELL_TYPE"
    else
        echo "Could not detect shell type, skipping PATH configuration"
        echo "Please add manually: export PATH=\"\$HOME/hero/bin:\$PATH\""
    fi

    echo ""

    # On macOS/Windows, start the server
    if [ "$OS" != "linux" ]; then
        echo "macOS/Windows detected - starting zinit-server in background..."
        echo ""
        if start_server_background "$OS"; then
            echo ""
            echo "✓ Ready to use!"
            echo ""
            echo "Try:"
            echo "  $INSTALL_DIR/zinit list"
            echo "  $INSTALL_DIR/zinit status"
        else
            echo "Warning: Could not start zinit-server"
            echo "You can start it manually:"
            echo "  ZINIT_SOCKET=\$HOME/hero/var/zinit.sock \\"
            echo "  ZINIT_CONFIG_DIR=\$HOME/hero/cfg/zinit \\"
            echo "  $INSTALL_DIR/zinit-server"
        fi
    else
        echo "Linux detected - server runs in foreground"
        echo ""
        echo "To start zinit-server:"
        echo "  zinit-server"
        echo ""
        echo "In another terminal, try:"
        echo "  zinit list"
        echo "  zinit status"
    fi

    echo ""
    echo "Installation complete!"
    echo ""

    if [ "$all_ok" = false ]; then
        echo "⚠ Some verifications failed, but binaries may still work"
        echo "If you experience issues, rebuild from source:"
        echo "  git clone https://github.com/threefoldtech/zinit"
        echo "  cd zinit && make build"
    fi
}

main
