#!/bin/bash

# Ensure script is run using bash
if [ -z "$BASH_VERSION" ]; then
    echo "This script must be run with bash. Please use: bash vitalpbx ..."
    exit 1
fi

# ANSI Color Codes
GREEN="\033[00;32m"
RED="\033[00;31m"
BLUE="\033[00;36m"
NC="\033[00;0m"

# VitalPBX Utilities
usage() {
    print "
VitalPBX Command Line Utilities
===============================

USAGE:
  vitalpbx <command> [options]

To view detailed help for a specific command:
  vitalpbx help <command>

Available Commands:
-------------------
  reset-pwd <username>              Reset the web GUI password for a user
  build-db                          Rebuild the internal VitalPBX database
  gen-conf                          Generate configuration files for selected modules
  fully-gen-conf                    Fully regenerate all system configuration files
  check-integrity                   Verify installation and configuration integrity
  apply-firewall                    Apply the current firewall rules
  restore-backup <file_path>        Restore a backup file from the command line
  make-backup <uuid>                Create a backup using a defined backup group ID
  list-backups                      Display available backup groups and their UUIDs
  reset-web-server                  Restart NGINX and PHP services
  optimize-mariadb                  Apply recommended MariaDB tuning
  optimize-web-server               Tune PHP/NGINX for best performance
  optimize-cache-server             Optimize Redis or other caching services
  optimize-server                   Apply system-wide optimizations
  disable-2FA <username>            Disable 2FA for a specific user
  update                            Perform a full system update
  clean-logs                        Rotate and clean archived log files
  check-geo-block <ip1> [ip2 ...]   Check if one or more IPs are blocked by GEO IP firewall sets
  check-ports <port1> [port2 ...]   Table check of ports in iptables (TCP & UDP)
  track-db-usage                    Live table of MariaDB SLEEP vs ACTIVE connections

Notes:
------
  • Most commands require root privileges.
  • Double-dash versions (e.g., --make-backup) are supported as aliases.
"
} # => usage()

print() { printf "%s\n" "$*"; }

die() {
	print "
VitalPBX - Command Line Error:

$1" 1>&2
	exit ${2:-1}
} # => die()

cmd_help() {
	local text
	case "$1" in
	reset-pwd) text="
  reset-pwd [username]
      Reset password for any user. if not user is specified, it resets the password for admin user (Main Tenant Only)";;
     build-db) text="
  build-db
      Execute a series of scripts to build VitalPBX database (apply_migrations)
     ";;
     gen-conf) text="
  gen-conf
      It generate the Asterisk cnfigurations and re-build Asterisk DB for the main tenant only";;
      fully-gen-conf) text="
  fully-gen-conf
      It generates the Asteirsk configurations and re-build Asterisk DB for all the tenants";;
		 check-integrity) text="
	check-integrity
	 		Check for issues on folders/files regarding permissions and owners";;
	    apply-firewall) text="
	apply-firewall
	 		Applies all the firewall settings defined in the firewall module";;
	 	restore-backup) text="
	restore-backup
	 		Restore a backup from the given path";;
	 	make-backup) text="
  make-backup <backup-identifier>
      Creates a backup using the specified Backup Identifier.
      The identifier corresponds to a defined backup profile (UUID),
      which controls what data is included (e.g., CDRs, recordings).
      Example: vitalpbx make-backup 520f2ff4-111-4444-8888-f153e69f1594";;
	 reset-web-server) text="
	reset-web-server
	    It resets the SSL certificate to the default one and disable the forced HTTPS option";;
   optimize-mariadb) text="
  optimize-mariadb
      It configures MariaDB/MySQL for better performance. Keep in mind that this command restarts MariaDB";;
    disable-2FA) text="
  disable-2FA
      It disables the 2FA feature for a specific user. You can either use the username or the email address.";;
  optimize-web-server) text="
    optimize-web-server
        It configures Web Server for better performance. Keep in mind that this command restarts the Web Server";;
  clean-logs) text="
    clean-logs
        It clean up the PBX logs to free up the hard drive space";;
  optimize-server) text="
      optimize-server
          It applies all the optimizations(Web, DB, System) in once. Keep in mind that this command restarts the Web and DB services";;
  optimize-cache-server) text="
      optimize-cache-server
          It configures the Cache Server for better performance. Keep in mind that this command restarts the Cache Server";;
  check-geo-block) text="
      check-geo-block <ip1> [ip2 ...]
          Checks whether one or more IP addresses are currently blocked by
          the system's GEO IP firewall rules (based on ipset sets).

          This is useful for diagnosing why Let's Encrypt or remote users
          may not be able to access the system due to country-based blocks.

          Example:
              vitalpbx check-geo-block 23.178.112.104 18.191.207.54";;
  check-ports) text="
      check-ports <port1> [port2 ... portN]
         Checks whether each given port is open in iptables for both TCP and UDP.
         Output is shown in a table format.

         Example:
             vitalpbx check-ports 80 443 5060
  ";;
  track-db-usage) text="
      track-db-usage
         Continuously monitors and displays MariaDB connection usage,
         showing the number of active (running) and SLEEP (idle) threads.

         Output is refreshed live in a color-coded table for easy analysis.

         Example:
             vitalpbx track-db-usage
  ";;
  "") usage ;;
	 *) text="
  Unknown command: '$1' (try without commands for a list of commands)" ;;
	esac

	# display the help text
	print "$text"
} # => cmd_help()

reset_pwd() {
	local username="$1"
	/usr/share/vitalpbx/scripts/reset_pwd $username
} # => reset_pwd()

build_db() {
	/usr/share/vitalpbx/scripts/apply_migrations
	/usr/share/vitalpbx/scripts/apply_addons_migrations
	print "Done"
} # => build_db()

fully_gen_conf() {
	/usr/share/vitalpbx/scripts/configure_tenants
	asterisk -rx"core reload"
	print "Done"
} # => gen_conf()

gen_conf() {
	/usr/share/vitalpbx/scripts/dump_asterisk_conf
	asterisk -rx"core reload"
	print "Done"
} # => gen_conf()

check_integrity(){
	/usr/share/vitalpbx/scripts/troubleshoot_env
} # => check_integrity()

apply_firewall(){
	/usr/share/vitalpbx/scripts/build_firewall
	firewall-cmd --list-all
	print "Done"
} # => apply_firewall()

restore_backup(){
	local backup="$1"
	# 1,1,1,1 are the flags for enabling restore cdr,recordings,voicemail and faxes
	/usr/share/vitalpbx/scripts/backup_manager "console_restore" "$backup" "1,1,1,1"
	print "Done"
} # => restore_backup()

make_backup(){
	local backup_id="$1"
	[ -z "$backup_id" ] && die "Missing backup identifier. Usage: make-backup <backup-identifier>"
	/usr/share/vitalpbx/scripts/backup_manager "backup" "$backup_id" "--debug"
} # => make_backup()

reset_web_server(){
  /usr/share/vitalpbx/scripts/vitalpbx "resetWebServer"
  print "Configurations has been reset"
  systemctl reload-or-restart nginx.service
  systemctl status nginx.service
}

optimize_mariadb(){
  /usr/share/vitalpbx/scripts/vitalpbx "optimizeMariaDB"
  print "Restarting MariaDB..."
  systemctl restart mariadb.service
  print "Reloading Asterisk ODBC driver..."
  asterisk -rx"module reload res_odbc.so"
  print "Done"
  systemctl status mariadb.service
}

optimize_web_server(){
  PHP_VER=$(php -r 'echo phpversion();' | awk -F '.' '{print $1}')
  PHP_SUB_VER=$(php -r 'echo phpversion();' | awk -F '.' '{print $2}')
  PHP_SERVICE="php${PHP_VER}.${PHP_SUB_VER}-fpm.service"

  print "Optimizing Nginx..."
  /usr/share/vitalpbx/scripts/vitalpbx "optimizeNginxSettings"

  print "Optimizing PHP FPM..."
  /usr/share/vitalpbx/scripts/vitalpbx "optimizePHPFPM"

  systemctl restart "$PHP_SERVICE"
  systemctl restart nginx.service
  print "Done"
  systemctl status nginx.service
  systemctl status "$PHP_SERVICE"
}

disable_2FA(){
  local username="$1"

  if [ -z "$username" ]
  then
        print "Please provide the username"
  else
        /usr/share/vitalpbx/scripts/vitalpbx "disable2FA" $username
  fi
}

update_pbx(){
  apt clean all
  apt update
  apt upgrade -y
  apt autoremove -y
}

optimize_server(){
  PHP_VER=$(php -r 'echo phpversion();' | awk -F '.' '{print $1}')
  PHP_SUB_VER=$(php -r 'echo phpversion();' | awk -F '.' '{print $2}')
  PHP_SERVICE="php${PHP_VER}.${PHP_SUB_VER}-fpm.service"

  print "Optimizing Nginx..."
  /usr/share/vitalpbx/scripts/vitalpbx "optimizeNginxSettings"

  print "Optimizing PHP FPM..."
  /usr/share/vitalpbx/scripts/vitalpbx "optimizePHPFPM"

  print "Optimizing MariaDB..."
  /usr/share/vitalpbx/scripts/vitalpbx "optimizeMariaDB"

  print "Optimizing Redis..."
  /usr/share/vitalpbx/scripts/vitalpbx "optimizeCacheSettings"

  print "Optimizing Server..."
  /usr/share/vitalpbx/scripts/vitalpbx "optimizeServerSettings"

  systemctl restart "$PHP_SERVICE"
  systemctl restart nginx.service
  systemctl restart mariadb.service
  systemctl restart redis.service
  asterisk -rx"module reload res_odbc.so"
  print "Done"
  systemctl status nginx.service
  systemctl status "$PHP_SERVICE"
  systemctl status mariadb.service
  systemctl status redis.service
}

optimize_cache_server(){
  /usr/share/vitalpbx/scripts/vitalpbx "optimizeCacheSettings"
  print "Restarting Redis..."
  systemctl restart redis.service
  print "Done"
  systemctl status redis.service
}

clean_logs(){
  /usr/share/vitalpbx/scripts/clean_server
}

check_ipset_membership() {
    if [ "$#" -lt 1 ]; then
        print "Usage: vitalpbx check-geo-block <ip1> [ip2 ... ipN]"
        return 1
    fi

    IPSETS=$(ipset list -name)

    print "Checking IPs against all available ipsets..."
    print "---------------------------------------------"

    for IP in "$@"; do
      MATCH_FOUND=false
      for SET in $IPSETS; do
          if ipset test "$SET" "$IP" &>/dev/null; then
              print "$IP is in IP set: $SET"
              MATCH_FOUND=true
          fi
      done
      if [ "$MATCH_FOUND" = false ]; then
          print "$IP is NOT in any IP set"
      fi
    done
}

colorize_status() {
    [[ "$1" == "Open" ]] && echo -e "\e[32mOpen\e[0m" || echo -e "\e[31mClosed\e[0m"
}

check_ports_table() {
    if [ "$#" -lt 1 ]; then
        print "Usage: vitalpbx check-ports <port1> [port2 ... portN]"
        return 1
    fi

    printf "\n%-6s | %-6s | %-6s\n" "Port" "UDP" "TCP"
    printf "%s\n" "--------------------------"

    for port in "$@"; do
        for proto in udp tcp; do
            if iptables-save | grep -qE "\-p $proto .* --dport $port(\b|:)"; then
                eval "${proto}_status=Open"
            else
                eval "${proto}_status=Closed"
            fi
        done
        printf "%-6s | %-6s | %-6s\n" "$port" "$(colorize_status "$udp_status")" "$(colorize_status "$tcp_status")"
    done
    echo
}

track_db_usage(){
    mysql -u"root" -h"localhost" -e"
       SELECT
           COUNT(*) AS total,
           SUM(CASE WHEN COMMAND = 'Sleep' THEN 1 ELSE 0 END) AS sleep,
           SUM(CASE WHEN COMMAND != 'Sleep' THEN 1 ELSE 0 END) AS active
       FROM information_schema.PROCESSLIST;
       " 2>/dev/null | awk -v green="$GREEN" -v red="$RED" -v blue="$BLUE" -v nc="$NC" '
           NR == 1 {
               print blue "Timestamp           | Total | Sleep | Active" nc
           }
           NR == 2 {
               cmd = "date \"+%Y-%m-%d %H:%M:%S\""
               cmd | getline ts
               close(cmd)
               printf "%s%s%s | %s%5s%s | %s%5s%s | %s%6s%s\n", blue, ts, nc, green, $1, nc, green, $2, nc, red, $3, nc
           }
       '
}

cmd="$1"
[ -n "$1" ] && shift # scrape off command

case "$cmd" in
  clean-logs|--clean-logs)
    clean_logs
  ;;
  update|--update)
    update_pbx
  ;;
	restore-backup|--restore-backup)
		restore_backup "$@"
	;;
  make-backup|--make-backup)
		make_backup "$@"
	;;
	apply-firewall|--apply-firewall)
		apply_firewall "$@"
	;;
	check-integrity|--check-integrity)
		check_integrity "$@"
	;;
	gen-conf|--gen-conf)
		gen_conf "$@"
	;;
	fully-gen-conf|--fully-gen-conf)
		fully_gen_conf "$@"
	;;
	build-db|--build-db)
		build_db "$@"
	;;
	reset-pwd|--reset-pwd)
		reset_pwd "$@"
	;;
  reset-web-server|--reset-web-server)
    reset_web_server "$@"
  ;;
  optimize-mariadb|--optimize-mariadb)
    optimize_mariadb "$@"
  ;;
  disable-2FA|--disable-2FA|disable-2fa|--disable-2fa)
    disable_2FA "$@"
  ;;
  optimize-web-server|--optimize-web-server)
    optimize_web_server "$@"
  ;;
  optimize-server|--optimize-server)
    optimize_server "$@"
  ;;
  optimize-cache-server|--optimize-cache-server)
    optimize_cache_server "$@"
  ;;
  check-geo-block|--check-geo-block)
    check_ipset_membership "$@"
  ;;
  check-ports|--check-ports)
    check_ports_table "$@"
  ;;
  track-db-usage|--track-db-usage)
    while true; do
      clear
      track_db_usage
      sleep 2
    done
  ;;
	""|help|-h|--help|--usage)
		cmd_help "$1"
		exit 0
		;;
	*)
		die "Unknown command '$cmd'. Run without commands for usage help."
		;;
esac
