#!/bin/bash
# =============================================================================
# FORGEJO RUNNER - FULL SYSTEM DEPLOYMENT WITH SYSTEMD
# Supports both DIRECT and DOCKER modes
# =============================================================================

# --- CONFIGURATION VARIABLES ---
FORGEJO_URL="http://192.168.2.76:3006"           # CHANGE THIS
REGISTRATION_TOKEN="your-registration-token"      # CHANGE THIS
RUNNER_NAME="selfhosted-runner-01"
RUNNER_VERSION="latest"                           # Can be "latest" or specific like "v12.13.2"
RUNNER_MODE="direct"                              # "direct" or "docker"

# Direct mode variables - using current user
RUNNER_HOME="/opt/forgejo-runner"

# Docker mode variables
COMPOSE_DIR="$HOME/forgejo-runner"
DIND_IMAGE="docker:dind"
RUNNER_IMAGE="data.forgejo.org/forgejo/runner"
# =============================================================================

set -e

echo "============================================================"
echo "FORGEJO RUNNER DEPLOYMENT"
echo "============================================================"
echo "Mode: $RUNNER_MODE"
echo "Version: $RUNNER_VERSION"
echo "Instance: $FORGEJO_URL"
echo ""

# --- STEP 1: Detect system architecture ---
ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/;s/armv7l/armv7/')
echo "Detected architecture: $ARCH"

# --- STEP 2: Get actual version if "latest" ---
if [ "$RUNNER_VERSION" = "latest" ]; then
    echo "Fetching latest Forgejo Runner version..."
    
    # Check if jq is installed
    if ! command -v jq &> /dev/null; then
        echo "jq not found. Installing jq..."
        apt-get update && apt-get install -y jq
    fi
    
    # Get version using jq (your method)
    RUNNER_VERSION=$(curl -s https://code.forgejo.org/api/v1/repos/forgejo/runner/releases/latest | jq -r .tag_name)
    
    # Verify we got a valid version
    if [ -z "$RUNNER_VERSION" ] || [ "$RUNNER_VERSION" = "null" ]; then
        echo "Failed to get version from API, trying fallback..."
        RUNNER_VERSION=$(curl -s https://code.forgejo.org/forgejo/runner/releases | \
            grep -o 'v[0-9]\+\.[0-9]\+\.[0-9]\+' | head -1)
    fi
    
    if [ -z "$RUNNER_VERSION" ]; then
        echo "ERROR: Failed to fetch latest version"
        echo "Using fallback version v12.13.2"
        RUNNER_VERSION="v12.13.2"
    fi
    
    echo "Latest version: $RUNNER_VERSION"
fi

# Remove 'v' prefix for version number
VERSION_NUM=${RUNNER_VERSION#v}
echo "Using version: $RUNNER_VERSION (number: $VERSION_NUM)"
echo ""

# --- STEP 3: Download runner binary (direct mode) ---
if [ "$RUNNER_MODE" = "direct" ]; then
    echo "=== DIRECT MODE INSTALLATION ==="
    echo "Installing runner directly on the system (no Docker required)"
    echo "Using current user: $USER"
    echo ""

    # --- Create directory ---
    echo "Creating runner directory..."
    sudo mkdir -p "$RUNNER_HOME/bin"
    sudo chown -R "$USER":"$USER" "$RUNNER_HOME"

    # --- Download runner binary ---
    echo "Downloading Forgejo runner binary..."
    DOWNLOAD_URL="https://code.forgejo.org/forgejo/runner/releases/download/$RUNNER_VERSION/forgejo-runner-${VERSION_NUM}-linux-$ARCH"

    echo "Downloading from: $DOWNLOAD_URL"
    
    # Download with timeout and retry
    if ! curl -L -m 60 --retry 3 "$DOWNLOAD_URL" -o "$RUNNER_HOME/bin/forgejo-runner"; then
        echo "ERROR: Failed to download runner binary"
        echo "Try manual download:"
        echo "  wget $DOWNLOAD_URL"
        exit 1
    fi
    
    chmod +x "$RUNNER_HOME/bin/forgejo-runner"
    chown -R "$USER":"$USER" "$RUNNER_HOME"

    # Verify binary
    echo "Verifying binary..."
    "$RUNNER_HOME/bin/forgejo-runner" --version || echo "Warning: Version check failed"

    # --- Register runner ---
    echo "Registering runner with Forgejo..."
    "$RUNNER_HOME/bin/forgejo-runner" register \
        --token "$REGISTRATION_TOKEN" \
        --name "$RUNNER_NAME" \
        --instance "$FORGEJO_URL" \
        --labels "$RUNNER_NAME:host" \
        --no-interactive

    # --- Create config.yaml ---
    echo "Creating configuration..."
    cat > "$RUNNER_HOME/config.yaml" << EOF
instance: $FORGEJO_URL
token: "$REGISTRATION_TOKEN"

log:
  level: info

runner:
  file: .runner
  capacity: 1
  timeout: 30m
  shutdown_timeout: 30m
  insecure: true
  fetch_timeout: 30s
  fetch_interval: 60s
  report_interval: 10s
  labels:
    - "$RUNNER_NAME:host"

cache:
  enabled: true
  dir: ""

host:
  workdir_parent: ""
EOF

    # --- Create systemd service ---
    echo "Creating systemd service..."
    sudo tee /etc/systemd/system/forgejo-runner.service > /dev/null << EOF
[Unit]
Description=Forgejo Actions Runner
After=network.target

[Service]
Type=simple
User=$USER
Group=$USER
WorkingDirectory=$RUNNER_HOME
ExecStart=$RUNNER_HOME/bin/forgejo-runner daemon --config $RUNNER_HOME/config.yaml
Restart=always
RestartSec=10
StartLimitBurst=3
StartLimitInterval=60s
LimitNOFILE=65536
LimitNPROC=65536

[Install]
WantedBy=multi-user.target
EOF

    # --- Enable and start service ---
    echo "Starting service..."
    sudo systemctl daemon-reload
    sudo systemctl enable forgejo-runner.service
    sudo systemctl start forgejo-runner.service

    echo ""
    echo "=== DIRECT MODE DEPLOYMENT COMPLETE ==="
    echo ""
    echo "Service status:"
    sudo systemctl status forgejo-runner.service --no-pager
    echo ""
    echo "To view logs:"
    echo "  sudo journalctl -u forgejo-runner -f"
    echo ""
    echo "Runner location: $RUNNER_HOME"

# =============================================================================
# DOCKER MODE INSTALLATION
# =============================================================================
elif [ "$RUNNER_MODE" = "docker" ]; then
    echo "=== DOCKER MODE INSTALLATION ==="
    echo "Installing runner with Docker Compose"
    echo ""

    # --- Check and install Docker if needed ---
    echo "Checking Docker..."
    if ! command -v docker &> /dev/null; then
        echo "Docker not found. Installing Docker..."
        curl -fsSL https://get.docker.com -o get-docker.sh
        sudo sh get-docker.sh
        sudo usermod -aG docker $USER
        sudo systemctl enable docker --now
        rm get-docker.sh
        echo "Docker installed successfully"
    else
        echo "Docker is already installed"
    fi

    if ! systemctl is-active --quiet docker; then
        echo "Starting Docker service..."
        sudo systemctl start docker
    fi
    echo "Docker is running"

    # --- Check and install Docker Compose if needed ---
    echo "Checking Docker Compose..."
    if ! command -v docker compose &> /dev/null; then
        echo "Docker Compose not found. Installing..."
        apt-get update && apt-get install -y docker-compose-plugin
    else
        echo "Docker Compose is already installed"
    fi
    echo ""

    # --- Create working directory ---
    echo "Creating working directory..."
    mkdir -p "$COMPOSE_DIR"/{data,cache}
    cd "$COMPOSE_DIR"

    # --- Register runner using Docker ---
    echo "Registering runner with Forgejo..."
    docker run -it --rm \
        -v "$(pwd)/data:/data" \
        -w /data \
        --user root \
        "${RUNNER_IMAGE}:${RUNNER_VERSION#v}" \
        forgejo-runner register \
        --no-interactive \
        --token "$REGISTRATION_TOKEN" \
        --name "$RUNNER_NAME" \
        --instance "$FORGEJO_URL" \
        --labels "$RUNNER_NAME:host"

    # --- Generate config.yaml ---
    echo "Generating configuration..."
    cat > data/config.yaml << EOF
instance: $FORGEJO_URL
token: "$REGISTRATION_TOKEN"

log:
  level: info

runner:
  file: .runner
  capacity: 1
  timeout: 30m
  shutdown_timeout: 30m
  insecure: true
  fetch_timeout: 30s
  fetch_interval: 60s
  report_interval: 10s
  labels:
    - "$RUNNER_NAME:host"

cache:
  enabled: true
  dir: ""

container:
  privileged: false
  valid_volumes:
    - '**'
  docker_host: ""
  force_pull: false

host:
  workdir_parent: ""
EOF

    # --- Create docker-compose.yml ---
    echo "Creating docker-compose.yml..."
    cat > docker-compose.yml << EOF
version: '3.8'

services:
  docker-in-docker:
    image: $DIND_IMAGE
    container_name: ${RUNNER_NAME}_dind
    privileged: true
    command: ['dockerd', '-H', 'tcp://0.0.0.0:2375', '--tls=false']
    restart: unless-stopped
    volumes:
      - dind-storage:/var/lib/docker

  runner:
    image: ${RUNNER_IMAGE}:${RUNNER_VERSION#v}
    container_name: ${RUNNER_NAME}
    depends_on:
      docker-in-docker:
        condition: service_started
    environment:
      DOCKER_HOST: tcp://docker-in-docker:2375
    user: 0:0
    volumes:
      - ./data:/data
      - ./cache:/cache
    restart: unless-stopped
    command: /bin/sh -c "
      apk update && apk add --no-cache nodejs npm &&
      sleep 5 &&
      forgejo-runner daemon --config /data/config.yaml
      "

volumes:
  dind-storage:
EOF

    # --- Create systemd service for docker-compose ---
    echo "Creating systemd service..."
    sudo tee /etc/systemd/system/forgejo-runner-docker.service > /dev/null << EOF
[Unit]
Description=Forgejo Runner (Docker Compose)
After=docker.service
Requires=docker.service

[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=$COMPOSE_DIR
ExecStart=/usr/bin/docker compose up -d
ExecStop=/usr/bin/docker compose down
ExecReload=/usr/bin/docker compose restart
StandardOutput=journal
User=$USER
Group=$USER

[Install]
WantedBy=multi-user.target
EOF

    # --- Enable and start service ---
    echo "Starting service..."
    sudo systemctl daemon-reload
    sudo systemctl enable forgejo-runner-docker.service
    sudo systemctl start forgejo-runner-docker.service

    echo ""
    echo "=== DOCKER MODE DEPLOYMENT COMPLETE ==="
    echo ""
    echo "Service status:"
    sudo systemctl status forgejo-runner-docker.service --no-pager
    echo ""
    echo "To view logs:"
    echo "  docker compose -f $COMPOSE_DIR/docker-compose.yml logs -f runner"
    echo ""
    echo "To manage:"
    echo "  cd $COMPOSE_DIR"
    echo "  docker compose up -d    # start"
    echo "  docker compose down     # stop"
    echo "  docker compose restart  # restart"
    echo ""
    echo "Runner location: $COMPOSE_DIR"

# =============================================================================
# INVALID MODE
# =============================================================================
else
    echo "ERROR: Invalid RUNNER_MODE. Use 'direct' or 'docker'"
    exit 1
fi

echo ""
echo "============================================================"
echo "DEPLOYMENT COMPLETE"
echo "============================================================"
echo ""
echo "Runner should now appear online in Forgejo Admin -> Actions -> Runners"
echo "URL: $FORGEJO_URL/admin/actions/runners"
echo ""
if [ "$RUNNER_MODE" = "direct" ]; then
    echo "To check runner logs: sudo journalctl -u forgejo-runner -f"
else
    echo "To check runner logs: docker compose -f $COMPOSE_DIR/docker-compose.yml logs -f runner"
fi
echo "============================================================"