#!/usr/bin/env bash
set -Eeuo pipefail

# ============ Konfigurasi (silakan sesuaikan) ======================
XUI_DIR="/etc/x-ui"
XUI_SERVICE="x-ui"
XRAY_SERVICE="xray"                       # jika tidak ada, di-skip oleh health-check
CONF_FILE="/usr/local/sbin/3ling.conf"
BACKUP_DIR="/root/3xui-backups"
VERSION_FILE="/usr/local/sbin/.3ling_version"
UPDATE_BASE_URL="https://example.com/3ling"  # GANTI ke repo kamu

# Lokasi sertifikat yang dipakai x-ui/xray
TLS_CRT="/etc/x-ui/xray.crt"
TLS_KEY="/etc/x-ui/xray.key"

# Lokasi log default (edit jika custom)
XRAY_LOG_DIR="/var/log/xray"
XRAY_ACCESS_LOG="${XRAY_LOG_DIR}/access.log"
XRAY_ERROR_LOG="${XRAY_LOG_DIR}/error.log"
NGINX_ACCESS_LOG="/var/log/nginx/access.log"
NGINX_ERROR_LOG="/var/log/nginx/error.log"

# ============ Warna/UX ========================================================
C_RESET="\e[0m"; C_GREEN="\e[32m"; C_RED="\e[31m"; C_YELLOW="\e[33m"; C_BLUE="\e[34m"
pause(){ read -rp $'\nPress ENTER to continue… '; }
die(){ echo -e "${C_RED}ERROR:${C_RESET} $*" >&2; exit 1; }
need_root(){ [[ $EUID -eq 0 ]] || die "Run as root."; }

ask(){ local p="$1" def="${2:-}"; local a; read -rp "$(printf "%s%s " "$p" "${def:+ [$def]}")" a; echo "${a:-$def}"; }
confirm(){ local q="$1"; read -rp "$q [y/N]: " x; [[ "${x,,}" == "y" || "${x,,}" == "yes" ]]; }
hr(){ echo "------------------------------------------------------------"; }
exists(){ command -v "$1" >/dev/null 2>&1; }
ensure_dir(){ mkdir -p "$1"; }
timestamp(){ date +"%Y%m%d-%H%M%S"; }

load_conf(){ [[ -f "$CONF_FILE" ]] && source "$CONF_FILE" || true; }
save_conf_kv(){ local k="$1" v="$2"; touch "$CONF_FILE"
  grep -qE "^${k}=" "$CONF_FILE" && sed -i "s#^${k}=.*#${k}='${v//'/'/'\/'}'#" "$CONF_FILE" \
                                   || echo "${k}='${v}'" >>"$CONF_FILE"; }

# ============ 1) Launcher: 3ling Interactive =================================
menu_3ling(){
  if exists menu-3ling; then exec menu-3ling
  elif [[ -x /usr/local/sbin/menu-3ling ]]; then exec /usr/local/sbin/menu-3ling
  else echo -e "${C_YELLOW}menu-3ling tidak ditemukan.${C_RESET}"; pause; fi
}

# ============ 2) Backup ke Telegram / Restore ================================
tg_send_file(){ # <file>
  load_conf
  local f="$1"; [[ -s "$f" ]] || die "File tidak ada: $f"
  [[ -n "${TG_BOT_TOKEN:-}" && -n "${TG_CHAT_ID:-}" ]] || {
    TG_BOT_TOKEN="$(ask "Telegram BOT token" "${TG_BOT_TOKEN:-}")"
    TG_CHAT_ID="$(ask "Telegram Chat ID" "${TG_CHAT_ID:-}")"
    [[ -n "$TG_BOT_TOKEN" && -n "$TG_CHAT_ID" ]] || die "Wajib isi Token & Chat ID."
    save_conf_kv TG_BOT_TOKEN "$TG_BOT_TOKEN"
    save_conf_kv TG_CHAT_ID "$TG_CHAT_ID"
  }
  echo "Kirim ke Telegram…"
  curl -sS -F "chat_id=${TG_CHAT_ID}" -F "document=@${f}" \
       "https://api.telegram.org/bot${TG_BOT_TOKEN}/sendDocument" >/dev/null || true
  echo "OK."
}

xui_backup(){
  need_root; ensure_dir "$BACKUP_DIR"
  local out="${BACKUP_DIR}/3xui-$(hostname)-$(timestamp).tar.gz"
  echo "Membuat backup: $out"
  systemctl is-active --quiet "$XUI_SERVICE" && local was=1 || was=0
  [[ $was -eq 1 ]] && systemctl stop "$XUI_SERVICE"
  tar -C / -czf "$out" \
    "$XUI_DIR" \
    /etc/systemd/system/${XUI_SERVICE}.service 2>/dev/null || true
  [[ $was -eq 1 ]] && systemctl start "$XUI_SERVICE"
  systemctl daemon-reload || true
  echo -e "${C_GREEN}Backup selesai:${C_RESET} $out"

  # ping healthchecks jika diset
  load_conf
  if [[ -n "${HC_PING_URL:-}" ]]; then
    curl -fsS -m 10 --retry 2 -o /dev/null "$HC_PING_URL" || true
  fi

  if confirm "Kirim ke Telegram?"; then tg_send_file "$out"; fi
  if confirm "Sync ke rclone remote (jika diset)?"; then rclone_push_noninteractive "$out"; fi
  pause
}

xui_restore(){
  need_root
  local f; f="$(ask "Path file backup (.tar.gz):")"; [[ -s "$f" ]] || die "File tidak ditemukan/empty."
  echo -e "${C_YELLOW}PERINGATAN:${C_RESET} restore akan menimpa konfigurasi $XUI_DIR."
  confirm "Lanjut restore?" || return 0
  systemctl stop "$XUI_SERVICE" || true
  tar -C / -xzf "$f"
  systemctl daemon-reload || true
  systemctl start "$XUI_SERVICE" || true
  systemctl enable "$XUI_SERVICE" || true
  echo -e "${C_GREEN}Restore selesai.${C_RESET}"
  pause
}

backup_menu(){
  clear; echo "=== 3x-ui Backup/Restore ==="; hr
  echo "1) Backup 3x-ui (opsi Telegram & rclone sync)"
  echo "2) Restore dari file backup"
  echo "0) Kembali"
  read -rp "Pilih: " c
  case "$c" in
    1) xui_backup ;;
    2) xui_restore ;;
    *) return ;;
  esac
}

# ============ 3) Speedtest ====================================================
speedtest_menu(){
  clear; echo "=== Speedtest ==="; hr
  if exists speedtest; then
    echo; speedtest --accept-license --accept-gdpr || true
  else
    echo "Ookla Speedtest belum ada."
    if confirm "Install sekarang? (Debian/Ubuntu)"; then
      apt-get update -y && apt-get install -y gnupg curl jq || true
      curl -sS https://packagecloud.io/install/repositories/ookla/speedtest-cli/script.deb.sh | bash || true
      apt-get install -y speedtest || die "Install gagal."
      speedtest --accept-license --accept-gdpr || true
    else
      echo "Quick test (download 100MB Cloudflare)…"
      time curl -s -o /dev/null "https://speed.cloudflare.com/__down?bytes=100000000"
    fi
  fi
  pause
}

# ============ 4) Optimasi VM/VPS (aman) ======================================
vm_optimize(){
  need_root
  echo "Terapkan tuning sysctl & limits."
  confirm "Lanjut?" || return 0
  cat >/etc/sysctl.d/99-3ling-tune.conf <<'EOF'
# 3ling minimal safe tuning
net.core.somaxconn = 4096
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_tw_reuse = 1
net.core.rmem_max = 134217728
net.core.wmem_max = 134217728
net.ipv4.tcp_rmem = 4096 87380 134217728
net.ipv4.tcp_wmem = 4096 65536 134217728
net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr
fs.file-max = 1000000
EOF
  cat >/etc/security/limits.d/99-3ling.conf <<'EOF'
* soft nofile 1000000
* hard nofile 1000000
root soft nofile 1000000
root hard nofile 1000000
EOF
  sysctl --system || true
  echo -e "${C_GREEN}Optimasi diterapkan.${C_RESET}"
  pause
}

# ============ 5) Add Swap =====================================================
add_swap(){
  need_root
  local size; size="$(ask "Ukuran swap (GB)" "2")"; [[ "$size" =~ ^[0-9]+$ ]] || die "Harus angka."
  local path="/swapfile"; [[ -e "$path" ]] && die "Swapfile sudah ada: $path"
  fallocate -l "${size}G" "$path" 2>/dev/null || dd if=/dev/zero of="$path" bs=1G count="$size"
  chmod 600 "$path"; mkswap "$path"; swapon "$path"
  grep -q "^/swapfile" /etc/fstab || echo "/swapfile none swap sw 0 0" >>/etc/fstab
  echo -e "${C_GREEN}Swap ${size}G aktif.${C_RESET}"
  pause
}

# ============ 6) Auto Reboot ==================================================
auto_reboot(){
  need_root
  echo "Jadwalkan reboot via cron (/etc/cron.d/3ling-autoreboot)"
  echo "1) Harian  2) Mingguan  3) Matikan"
  read -rp "Pilih: " c
  case "$c" in
    1) local tm; tm="$(ask "Jam:Menit (24h)" "03:30")"; local hh="${tm%:*}" mm="${tm#*:}"
       echo "$mm $hh * * * root /sbin/reboot" >/etc/cron.d/3ling-autoreboot ;;
    2) local tm; tm="$(ask "Jam:Menit (24h)" "03:30")"; local wd; wd="$(ask "Hari (0=Min..6=Sab)" "1")"
       local hh="${tm%:*}" mm="${tm#*:}"
       echo "$mm $hh * * $wd root /sbin/reboot" >/etc/cron.d/3ling-autoreboot ;;
    3) rm -f /etc/cron.d/3ling-autoreboot ;;
    *) echo "Batal." ;;
  esac
  systemctl reload cron 2>/dev/null || systemctl restart crond 2>/dev/null || true
  echo -e "${C_GREEN}OK.${C_RESET}"; pause
}

# ============ 7) Update Script (berdasarkan versi) ============================
semver_lt(){ [ "$1" = "$2" ] && return 1; local IFS=.; local i a=($1) b=($2)
  for ((i=${#a[@]}; i<${#b[@]}; i++)); do a[i]=0; done
  for ((i=0;i<${#a[@]};i++)); do [[ -z "${b[i]:-}" ]] && b[i]=0
    ((10#${a[i]}<10#${b[i]})) && return 0
    ((10#${a[i]}>10#${b[i]})) && return 1
  done; return 1; }
update_script(){
  need_root
  local cur="0.0.0"; [[ -f "$VERSION_FILE" ]] && cur="$(cat "$VERSION_FILE" 2>/dev/null || echo 0.0.0)"
  echo "Versi saat ini: $cur"
  local latest; latest="$(curl -fsSL "${UPDATE_BASE_URL}/VERSION" || true)"; [[ -n "$latest" ]] || die "Gagal ambil versi."
  echo "Versi terbaru: $latest"
  if semver_lt "$cur" "$latest"; then
    echo "Download…"
    curl -fsSL -o /usr/local/sbin/menu-3ling "${UPDATE_BASE_URL}/pkg/menu-3ling" || die "Gagal unduh menu-3ling"
    curl -fsSL -o /usr/local/sbin/3ling       "${UPDATE_BASE_URL}/pkg/3ling"       || true
    chmod +x /usr/local/sbin/menu-3ling /usr/local/sbin/3ling 2>/dev/null || true
    echo "$latest" >"$VERSION_FILE"
    echo -e "${C_GREEN}Update ke ${latest}.${C_RESET}"
  else
    echo -e "${C_YELLOW}Sudah terbaru.${C_RESET}"
  fi
  pause
}

# ============ 8) Health-check x-ui ============================================
health_check(){
  clear
  echo "=== Health-check x-ui ==="; hr

  local svc="${XUI_SERVICE:-x-ui}"

  # Pastikan unit ada
  if ! systemctl list-unit-files --type=service --no-legend | awk '{print $1}' | grep -qx "${svc}.service"; then
    echo "Service ${svc} tidak ditemukan."; hr; pause; return 1
  fi

  echo -e "${C_BLUE}Service:${C_RESET} ${svc}"

  if systemctl is-active --quiet "$svc"; then
    echo -e "  Status : \e[32mOK (running)\e[0m"
  else
    echo -e "  Status : \e[31mNOT RUNNING\e[0m"
    echo "  Ringkasan status:"
    # Tampilkan ringkas tanpa pager untuk bantu debugging
    systemctl --no-pager --full status "$svc" 2>/dev/null | sed 's/^/    /' | head -n 40
  fi

  hr
  pause
}

# ============ 9) Auto-renew SSL (acme.sh / certbot) ==========================
ssl_menu(){
  clear; echo "=== SSL Auto-Renew ==="; hr
  echo "1) acme.sh (standalone :80)"
  echo "2) certbot (standalone :80)"
  echo "0) Kembali"
  read -rp "Pilih: " c
  case "$c" in
    1) ssl_acme ;;
    2) ssl_certbot ;;
    *) return ;;
  esac
}

ssl_acme(){
  need_root
  local domain email; domain="$(ask "Domain (FQDN)")"; email="$(ask "Email Let's Encrypt")"
  [[ -n "$domain" && -n "$email" ]] || die "Domain & email wajib."
  # install acme.sh
  if ! exists acme.sh; then
    curl -fsSL https://get.acme.sh | sh -s email="$email"
    source ~/.bashrc 2>/dev/null || true
    export PATH="$HOME/.acme.sh:$PATH"
  fi
  # issue standalone
  systemctl stop nginx 2>/dev/null || true
  ~/.acme.sh/acme.sh --set-default-ca --server letsencrypt || true
  ~/.acme.sh/acme.sh --issue -d "$domain" --standalone --force || die "Issue gagal."
  ~/.acme.sh/acme.sh --install-cert -d "$domain" \
    --key-file "$TLS_KEY" --fullchain-file "$TLS_CRT" \
    --reloadcmd "systemctl reload ${XUI_SERVICE} || systemctl restart ${XUI_SERVICE}"
  systemctl start nginx 2>/dev/null || true
  echo -e "${C_GREEN}Sertifikat terpasang ke ${TLS_CRT} / ${TLS_KEY}.${C_RESET}"
  pause
}

ssl_certbot(){
  need_root
  local domain email; domain="$(ask "Domain (FQDN)")"; email="$(ask "Email Let's Encrypt")"
  [[ -n "$domain" && -n "$email" ]] || die "Domain & email wajib."
  apt-get update -y && apt-get install -y certbot || die "Install certbot gagal."
  systemctl stop nginx 2>/dev/null || true
  certbot certonly --standalone -d "$domain" -m "$email" --agree-tos -n || die "Issue gagal."
  systemctl start nginx 2>/dev/null || true
  # symlink/backup lama
  install -d "$(dirname "$TLS_CRT")"
  ln -sf "/etc/letsencrypt/live/${domain}/fullchain.pem" "$TLS_CRT"
  ln -sf "/etc/letsencrypt/live/${domain}/privkey.pem"  "$TLS_KEY"
  systemctl reload "${XUI_SERVICE}" || systemctl restart "${XUI_SERVICE}" || true
  echo -e "${C_GREEN}Sertifikat terpasang & auto-renew oleh certbot.${C_RESET}"
  pause
}

# ============ 10) Fail2ban preset (ssh + nginx) ==============================
fail2ban_setup(){
  need_root
  apt-get update -y && apt-get install -y fail2ban || die "Install fail2ban gagal."
  cat >/etc/fail2ban/jail.d/3ling-sshd.local <<'EOF'
[sshd]
enabled = true
mode    = aggressive
port    = ssh
filter  = sshd
logpath = /var/log/auth.log
maxretry = 5
findtime = 10m
bantime  = 1h
EOF
  if [[ -d /etc/nginx ]]; then
    cat >/etc/fail2ban/jail.d/3ling-nginx.local <<'EOF'
[nginx-http-auth]
enabled = true
port    = http,https
logpath = /var/log/nginx/error.log
maxretry = 5
findtime = 10m
bantime  = 1h
EOF
  fi
  systemctl enable --now fail2ban || true
  systemctl restart fail2ban || true
  echo -e "${C_GREEN}Fail2ban aktif.${C_RESET}"
  pause
}

# ============ 11) Logrotate (xray + nginx) ===================================
logrotate_setup(){
  need_root
  install -d "$XRAY_LOG_DIR" || true
  cat >/etc/logrotate.d/3ling-xray <<EOF
${XRAY_ACCESS_LOG} ${XRAY_ERROR_LOG} {
  weekly
  rotate 8
  missingok
  notifempty
  compress
  delaycompress
  sharedscripts
  postrotate
    systemctl reload ${XRAY_SERVICE} 2>/dev/null || true
  endscript
}
EOF
  if [[ -d /etc/nginx ]]; then
    cat >/etc/logrotate.d/3ling-nginx <<'EOF'
/var/log/nginx/*.log {
  daily
  rotate 14
  missingok
  compress
  delaycompress
  notifempty
  sharedscripts
  postrotate
    [ -s /run/nginx.pid ] && kill -USR1 `cat /run/nginx.pid`
  endscript
}
EOF
  fi
  echo -e "${C_GREEN}Logrotate diset.${C_RESET}"
  pause
}

# ============ 12) Rclone backup to S3/B2 =====================================
rclone_config_check(){
  if ! exists rclone; then
    apt-get update -y && apt-get install -y rclone || die "Install rclone gagal."
  fi
}
rclone_setup(){
  need_root
  rclone_config_check
  echo -e "${C_YELLOW}Menjalankan rclone config (interactive).${C_RESET}"
  rclone config
}
rclone_push_noninteractive(){ # <file>
  load_conf
  local f="$1"
  [[ -n "${RCLONE_REMOTE_PATH:-}" ]] || return 0
  rclone copy "$f" "${RCLONE_REMOTE_PATH}/$(hostname)/" --create-empty-src-dirs --fast-list || true
}
rclone_menu(){
  clear; echo "=== Rclone Backup ==="; hr
  echo "1) Setup/Config rclone"
  echo "2) Set default remote path (contoh: b2:mybucket/3xui-backups)"
  echo "3) Sync BACKUP_DIR -> remote (full folder)"
  echo "0) Kembali"
  read -rp "Pilih: " c
  case "$c" in
    1) rclone_setup ;;
    2) local p; p="$(ask "Remote path" "$(load_conf; echo ${RCLONE_REMOTE_PATH:-})")"
       [[ -n "$p" ]] && save_conf_kv RCLONE_REMOTE_PATH "$p" && echo "Tersimpan." ;;
    3) load_conf; rclone_config_check
       [[ -n "${RCLONE_REMOTE_PATH:-}" ]] || die "Set remote path dulu."
       ensure_dir "$BACKUP_DIR"
       rclone copy "$BACKUP_DIR" "${RCLONE_REMOTE_PATH}/$(hostname)/" --create-empty-src-dirs --fast-list
       echo -e "${C_GREEN}Sync selesai.${C_RESET}" ; pause ;;
    *) return ;;
  esac
}

# ============ 13) Chrony time sync ===========================================
chrony_sync(){
  need_root
  apt-get update -y && apt-get install -y chrony || die "Install chrony gagal."
  systemctl enable --now chrony || systemctl enable --now chronyd || true
  timedatectl set-ntp true || true
  echo "Status:"
  chronyc tracking || true
  chronyc sources || true
  pause
}

# ============ 14) Healthchecks.io Webhook ====================================
healthchecks_menu(){
  load_conf
  clear; echo "=== Healthchecks.io ==="; hr
  echo "URL sekarang: ${HC_PING_URL:-<belum diset>}"
  echo "1) Set/ubah webhook URL"
  echo "2) Test ping sekarang"
  echo "3) Tambah cron ping tiap 6 jam"
  echo "4) Hapus cron ping"
  echo "0) Kembali"
  read -rp "Pilih: " c
  case "$c" in
    1) local url; url="$(ask "Masukkan HC ping URL" "${HC_PING_URL:-}")"
       [[ -n "$url" ]] || { echo "Batal."; return; }
       save_conf_kv HC_PING_URL "$url"; echo "Tersimpan." ;;
    2) [[ -n "${HC_PING_URL:-}" ]] || die "Set URL dulu."
       curl -fsS -m 10 --retry 2 -o /dev/null "$HC_PING_URL" && echo "OK terkirim." || echo "Gagal ping." ; pause ;;
    3) [[ -n "${HC_PING_URL:-}" ]] || die "Set URL dulu."
       cat >/etc/cron.d/3ling-hc <<EOF
# ping tiap 6 jam
0 */6 * * * root curl -fsS -m 10 --retry 2 -o /dev/null "${HC_PING_URL}"
EOF
       systemctl reload cron 2>/dev/null || systemctl restart crond 2>/dev/null || true
       echo "Cron dibuat." ; pause ;;
    4) rm -f /etc/cron.d/3ling-hc
       systemctl reload cron 2>/dev/null || systemctl restart crond 2>/dev/null || true
       echo "Cron dihapus." ; pause ;;
    *) return ;;
  esac
}

# ============ Menu Utama ======================================================
main_menu(){
  clear
  echo -e "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
  echo -e "             ${C_YELLOW}⇱ Server Menu ⇲${C_RESET}"
  echo -e "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
  echo "1) Xray 3XUI Interactive"
  echo "2) Backup/Restore 3x-ui (Telegram / rclone)"
  echo "3) Speedtest"
  echo "4) Optimasi VM/VPS"
  echo "5) Tambah Swap"
  echo "6) Setel Reboot Otomatis"
  echo "7) Update Script"
  echo "8) Health-check x-ui & xray"
  echo "9) SSL Auto-renew (acme.sh / certbot)"
  echo "10) Fail2ban preset (ssh + nginx)"
  echo "11) Logrotate (xray + nginx)"
  echo "12) Rclone backup (S3/B2)"
  echo "13) Sinkronisasi waktu (chrony)"
  echo "14) Healthchecks.io webhook"
  echo "0) Keluar"
  hr
  read -rp "Pilih: " c
  case "$c" in
    1) menu_3ling ;;
    2) backup_menu ;;
    3) speedtest_menu ;;
    4) vm_optimize ;;
    5) add_swap ;;
    6) auto_reboot ;;
    7) update_script ;;
    8) health_check ;;
    9) ssl_menu ;;
    10) fail2ban_setup ;;
    11) logrotate_setup ;;
    12) rclone_menu ;;
    13) chrony_sync ;;
    14) healthchecks_menu ;;
    0) exit 1 ;;
    *) echo "Pilihan tidak dikenal." ; pause ;;
  esac
}

need_root
while true; do main_menu; done