#!/bin/bash
# Info: Script to install Coder
# Author: Provisioning System
# Release: 1.0
# Date: 2025-07-24

USAGE="install-coder.sh"
[ "$1" == "-h" ] && echo "$USAGE" && exit 1

[ -r "env-coder" ] && . ./env-coder

CODER_VERSION=${CODER_VERSION:-2.23.4}

# Determine architecture
ARCH="$(uname -m)"
case $ARCH in
    x86_64) ARCH="amd64" ;;
    aarch64) ARCH="arm64" ;;
    armv7*) ARCH="armv7" ;;
    *) echo "Unsupported architecture: $ARCH" && exit 1 ;;
esac

# Determine OS
OS="$(uname -s | tr '[:upper:]' '[:lower:]')"
case $OS in
    linux) OS="linux" ;;
    darwin) OS="darwin" ;;
    *) echo "Unsupported OS: $OS" && exit 1 ;;
esac

CODER_URL=https://github.com/coder/coder/releases/download
CODER_BINARY=v${CODER_VERSION}/coder_${CODER_VERSION}_${OS}_${ARCH}.tar.gz
CODER_ARCHIVE=coder_${CODER_VERSION}_${OS}_${ARCH}.tar.gz

CODER_RUN_PATH=${CODER_RUN_PATH:-/usr/local/bin/coder}
CODER_SYSTEMCTL_MODE=${CODER_SYSTEMCTL_MODE:-enabled}

CODER_CONFIG_PATH=${CODER_CONFIG_PATH:-/etc/coder}
CODER_WORK_PATH=${CODER_WORK_PATH:-/var/lib/coder}

CODER_RUN_USER=${CODER_RUN_USER:-coder}
CODER_RUN_GROUP=${CODER_RUN_GROUP:-coder}
CODER_RUN_USER_HOME=${CODER_RUN_USER_HOME:-/home/coder}

CODER_ACCESS_URL=${CODER_ACCESS_URL:-http://localhost:7080}
CODER_HTTP_ADDRESS=${CODER_HTTP_ADDRESS:-0.0.0.0:7080}

echo "Installing Coder ${CODER_VERSION}..."

# Install dependencies
echo "Installing dependencies..."
if command -v apt-get >/dev/null 2>&1; then
    apt-get update
    apt-get install -y curl ca-certificates git
elif command -v yum >/dev/null 2>&1; then
    yum update -y
    yum install -y curl ca-certificates git
elif command -v dnf >/dev/null 2>&1; then
    dnf update -y
    dnf install -y curl ca-certificates git
else
    echo "Package manager not found. Please install curl, ca-certificates, and git manually."
    exit 1
fi

# Create user and group
if ! id "$CODER_RUN_USER" &>/dev/null; then
    groupadd -r "$CODER_RUN_GROUP"
    useradd -r -g "$CODER_RUN_GROUP" -d "$CODER_RUN_USER_HOME" -s /bin/bash -c "Coder service user" "$CODER_RUN_USER"
fi

# Create directories
mkdir -p "$CODER_CONFIG_PATH"
mkdir -p "$CODER_WORK_PATH"
mkdir -p "$CODER_RUN_USER_HOME"

# Download and install Coder
cd /tmp
echo "Downloading Coder from ${CODER_URL}/${CODER_BINARY}..."
curl -L -o "$CODER_ARCHIVE" "${CODER_URL}/${CODER_BINARY}"

if [ ! -f "$CODER_ARCHIVE" ]; then
    echo "Failed to download Coder archive"
    exit 1
fi

# Extract and install binary
echo "Extracting Coder..."
tar -xzf "$CODER_ARCHIVE"

if [ ! -f "coder" ]; then
    echo "Failed to extract Coder binary"
    exit 1
fi

# Install binary
chmod +x coder
mv coder "$(dirname "$CODER_RUN_PATH")/"

# Create environment file
cat > "$CODER_CONFIG_PATH/coder.env" << EOF
CODER_ACCESS_URL=$CODER_ACCESS_URL
CODER_HTTP_ADDRESS=$CODER_HTTP_ADDRESS
CODER_CONFIG_DIR=$CODER_WORK_PATH
EOF

# Load additional environment variables from template if available
if [ -f "env-coder" ]; then
    cat env-coder >> "$CODER_CONFIG_PATH/coder.env"
fi

# Set ownership
chown -R "$CODER_RUN_USER:$CODER_RUN_GROUP" "$CODER_WORK_PATH"
chown -R "$CODER_RUN_USER:$CODER_RUN_GROUP" "$CODER_RUN_USER_HOME"
chown -R "$CODER_RUN_USER:$CODER_RUN_GROUP" "$CODER_CONFIG_PATH"

# Create systemd service file
cat > /etc/systemd/system/coder.service << EOF
[Unit]
Description=Coder Development Environment Platform
Documentation=https://coder.com/docs
After=network-online.target
Wants=network-online.target
$(if [ "${CODER_DATABASE_TYPE:-postgresql}" = "postgresql" ] && [ -z "$CODER_PG_CONNECTION_URL" ]; then echo "After=postgresql.service"; echo "Wants=postgresql.service"; fi)

[Service]
Type=simple
User=$CODER_RUN_USER
Group=$CODER_RUN_GROUP
EnvironmentFile=$CODER_CONFIG_PATH/coder.env
WorkingDirectory=$CODER_WORK_PATH
ExecStart=$CODER_RUN_PATH server
ExecReload=/bin/kill -HUP \$MAINPID
Restart=always
RestartSec=10

# Security settings
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=$CODER_WORK_PATH $CODER_CONFIG_PATH
CapabilityBoundingSet=CAP_NET_BIND_SERVICE

# Resource limits
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
EOF

# Initialize Coder database and first user if needed
echo "Initializing Coder server..."
sudo -u "$CODER_RUN_USER" bash -c "
    export CODER_CONFIG_DIR='$CODER_WORK_PATH'
    export CODER_ACCESS_URL='$CODER_ACCESS_URL'
    export CODER_HTTP_ADDRESS='$CODER_HTTP_ADDRESS'
    cd '$CODER_WORK_PATH'
    if [ ! -f '$CODER_WORK_PATH/.initialized' ]; then
        timeout 30 '$CODER_RUN_PATH' server --init-only 2>/dev/null || true
        touch '$CODER_WORK_PATH/.initialized'
    fi
"

# Enable and start service
systemctl daemon-reload
systemctl "$CODER_SYSTEMCTL_MODE" coder.service

if [ "$CODER_SYSTEMCTL_MODE" = "enabled" ]; then
    systemctl start coder.service
    
    # Wait a moment for service to start
    sleep 5
fi

# Cleanup
cd /
rm -rf /tmp/"$CODER_ARCHIVE" /tmp/coder

echo "Coder installation completed!"
echo "Service: coder.service"
echo "Coder Server available at: $CODER_ACCESS_URL"
echo "Configuration: $CODER_CONFIG_PATH/coder.env"
echo "Data directory: $CODER_WORK_PATH"

# Display service status
if systemctl is-active --quiet coder.service; then
    echo "✅ Coder service is running"
    echo ""
    echo "First time login:"
    echo "1. Open $CODER_ACCESS_URL in a browser"
    echo "2. Create your first admin user account"
    echo "3. Start creating workspaces and templates"
else
    echo "⚠️  Coder service status:"
    systemctl status coder.service --no-pager -l
fi