#!/bin/bash

# ============================================================
# OpenVPN client one-shot installer for Ubuntu
# Supported OS: Ubuntu 20.04 / 22.04 / 24.04 LTS
# Published by: helper.sh
# Script note: generated with Claude and curated by helper.sh
# ============================================================

set -euo pipefail

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'

CONFIG_DIR="/etc/openvpn/client"
CONFIG_NAME="client"
SOURCE_CONF="./client.conf"
SOURCE_LOGIN="./login.txt"
SOURCE_DNS_HELPER="./update-resolv-conf"
DNS_HELPER_PATH="/etc/openvpn/update-resolv-conf"
DNS_HELPER_INSTALLED=0

info()    { echo -e "${BLUE}[INFO]${NC}  $1"; }
success() { echo -e "${GREEN}[OK]${NC}    $1"; }
warning() { echo -e "${YELLOW}[WARN]${NC}  $1"; }
error()   { echo -e "${RED}[ERROR]${NC} $1"; exit 1; }

usage() {
  cat <<'EOF'
Usage: install_openvpn_client_ubuntu.sh [options]

Options:
  --config-dir PATH       Install destination (default: /etc/openvpn/client)
  --config-name NAME      Systemd instance name (default: client)
  --source-conf PATH      Source client.conf path (default: ./client.conf)
  --source-login PATH     Source login.txt path (default: ./login.txt)
  --source-dns-helper     Optional local update-resolv-conf path (default: ./update-resolv-conf)
  -h, --help              Show this help message

Required local files in the current directory by default:
  ./client.conf
  ./login.txt
EOF
}

while [ $# -gt 0 ]; do
  case "$1" in
    --config-dir)
      CONFIG_DIR="$2"
      shift 2
      ;;
    --config-name)
      CONFIG_NAME="$2"
      shift 2
      ;;
    --source-conf)
      SOURCE_CONF="$2"
      shift 2
      ;;
    --source-login)
      SOURCE_LOGIN="$2"
      shift 2
      ;;
    --source-dns-helper)
      SOURCE_DNS_HELPER="$2"
      shift 2
      ;;
    -h|--help)
      usage
      exit 0
      ;;
    *)
      error "Unknown argument: $1"
      ;;
  esac
done

if [ "${EUID}" -ne 0 ]; then
  error "Run this script with root privileges: sudo bash $0"
fi

if [ ! -f "${SOURCE_CONF}" ]; then
  error "Missing ${SOURCE_CONF}. Put client.conf in the current directory before running this script."
fi

if [ ! -f "${SOURCE_LOGIN}" ]; then
  error "Missing ${SOURCE_LOGIN}. Put login.txt in the current directory before running this script."
fi

info "Checking operating system..."
. /etc/os-release
if [ "${ID:-}" != "ubuntu" ]; then
  error "This script only supports Ubuntu. Detected: ${ID:-unknown}"
fi

case "${VERSION_ID:-}" in
  20.04|22.04|24.04)
    success "Detected system: ${PRETTY_NAME:-Ubuntu}"
    ;;
  *)
    warning "This script was tested for Ubuntu 20.04 / 22.04 / 24.04. Continuing on ${PRETTY_NAME:-Ubuntu}."
    ;;
esac

info "Installing OpenVPN..."
apt-get update -qq
apt-get install -y -qq openvpn
success "OpenVPN installed"

info "Preparing ${CONFIG_DIR} ..."
mkdir -p "${CONFIG_DIR}"

TARGET_CONF="${CONFIG_DIR}/${CONFIG_NAME}.conf"
TARGET_LOGIN="${CONFIG_DIR}/login.txt"
BACKUP_SUFFIX="$(date +%Y%m%d%H%M%S)"

ensure_line() {
  local file="$1"
  local line="$2"
  if ! grep -Fxq "$line" "$file"; then
    printf '\n%s\n' "$line" >> "$file"
  fi
}

if [ -f "${TARGET_CONF}" ]; then
  cp -f "${TARGET_CONF}" "${TARGET_CONF}.bak.${BACKUP_SUFFIX}"
  warning "Backed up existing config to ${TARGET_CONF}.bak.${BACKUP_SUFFIX}"
fi

if [ -f "${TARGET_LOGIN}" ]; then
  cp -f "${TARGET_LOGIN}" "${TARGET_LOGIN}.bak.${BACKUP_SUFFIX}"
  warning "Backed up existing login file to ${TARGET_LOGIN}.bak.${BACKUP_SUFFIX}"
fi

cp -f "${SOURCE_CONF}" "${TARGET_CONF}"
cp -f "${SOURCE_LOGIN}" "${TARGET_LOGIN}"

# Normalize common Windows line endings so OpenVPN and shell scripts run cleanly on Linux.
sed -i 's/\r$//' "${TARGET_CONF}"
sed -i 's/\r$//' "${TARGET_LOGIN}"

chmod 600 "${TARGET_LOGIN}"
chmod 600 "${TARGET_CONF}"

if ! grep -q "auth-user-pass" "${TARGET_CONF}"; then
  warning "client.conf does not contain auth-user-pass. Username/password login may not be enabled."
fi

if grep -q "auth-user-pass login.txt" "${TARGET_CONF}"; then
  success "client.conf references login.txt in the target directory"
else
  warning "client.conf does not reference 'login.txt' exactly. Confirm the auth-user-pass path manually."
fi

if [ -f "${SOURCE_DNS_HELPER}" ]; then
  info "Using local DNS helper from ${SOURCE_DNS_HELPER} ..."
  cp -f "${SOURCE_DNS_HELPER}" "${DNS_HELPER_PATH}"
  sed -i 's/\r$//' "${DNS_HELPER_PATH}"
  chmod +x "${DNS_HELPER_PATH}"
  DNS_HELPER_INSTALLED=1
  success "DNS helper installed"

  info "Ensuring DNS helper hooks exist in ${TARGET_CONF} ..."
  ensure_line "${TARGET_CONF}" "script-security 2"
  ensure_line "${TARGET_CONF}" "up ${DNS_HELPER_PATH}"
  ensure_line "${TARGET_CONF}" "down ${DNS_HELPER_PATH}"
  success "OpenVPN DNS helper hooks updated"
else
  warning "No local update-resolv-conf found. Skipping DNS helper installation."
fi

SERVICE_NAME="openvpn-client@${CONFIG_NAME}"

info "Enabling ${SERVICE_NAME} ..."
systemctl enable "${SERVICE_NAME}" >/dev/null

info "Restarting ${SERVICE_NAME} ..."
systemctl restart "${SERVICE_NAME}"
sleep 3

if systemctl is-active --quiet "${SERVICE_NAME}"; then
  success "${SERVICE_NAME} is active"
else
  warning "${SERVICE_NAME} is not active yet. Review: journalctl -u ${SERVICE_NAME} -n 100 --no-pager"
fi

echo ""
echo -e "${GREEN}============================================================${NC}"
echo -e "${GREEN} OpenVPN client installation completed                       ${NC}"
echo -e "${GREEN}============================================================${NC}"
echo ""
echo -e "  ${BLUE}Installed config:${NC} ${TARGET_CONF}"
echo -e "  ${BLUE}Credentials file:${NC} ${TARGET_LOGIN}"
echo -e "  ${BLUE}Service name:${NC}     ${SERVICE_NAME}"
if [ "${DNS_HELPER_INSTALLED}" -eq 1 ]; then
  echo -e "  ${BLUE}DNS helper:${NC}       ${DNS_HELPER_PATH}"
  echo -e "  ${BLUE}Note:${NC}             DNS values are defined by the copied update-resolv-conf script"
fi
echo ""
echo -e "  ${YELLOW}Useful commands:${NC}"
echo -e "    systemctl status ${SERVICE_NAME}"
echo -e "    journalctl -u ${SERVICE_NAME} -n 100 --no-pager"
echo -e "    systemctl restart ${SERVICE_NAME}"
echo -e "    ip addr show tun0"
if [ "${DNS_HELPER_INSTALLED}" -eq 1 ]; then
  echo -e "    cat /etc/resolv.conf"
  echo -e "    tail -n 50 /var/log/openvpn-dns-update.log"
fi
echo ""
