#!/bin/bash
# ===========================================================================
#  install-sbc.sh — Kalixor SBC Platform One-Touch Installer
#  Debian 13 (Trixie)
#
#  This script installs ALL prerequisites (Kamailio, RTPEngine, Node.js, 
#  PostgreSQL) and then deploys the softswitch-sbc package from the 
#  Ring2All APT repository.
#
#  Usage:
#    wget https://repo.softswitchone.com/apt/install-sbc.sh && chmod +x install-sbc.sh && ./install-sbc.sh
#
#  Flags:
#    --skip-sbc-kamailio   Kamailio already installed, skip its setup
#    --skip-rtpengine  RTPEngine already installed, skip its setup
#    --skip-repo       Ring2All repo already configured, skip setup
#    --skip-kamdb      Kamailio native DB already initialized
#    --help            Show this help
# ===========================================================================
set -e
set -o pipefail

# ── Flags ─────────────────────────────────────────────────────────────────────
SKIP_KAMAILIO=false
SKIP_RTPENGINE=false
SKIP_REPO=false
SKIP_KAMDB=false
for arg in "$@"; do
    case $arg in
        --skip-sbc-kamailio)  SKIP_KAMAILIO=true ;;
        --skip-rtpengine) SKIP_RTPENGINE=true ;;
        --skip-repo)      SKIP_REPO=true ;;
        --skip-kamdb)     SKIP_KAMDB=true ;;
        --help|-h)
            grep '^#' "$0" | head -30 | sed 's/^# \?//'
            exit 0 ;;
    esac
done

# ── Colors ────────────────────────────────────────────────────────────────────
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
WHITE='\033[1;37m'
BLUE='\033[0;34m'
NC='\033[0m'

ok()    { echo -e "  ${GREEN}✔${NC} $*"; }
step()  { echo -e "  ${CYAN}──>${NC} $*"; }
warn()  { echo -e "  ${YELLOW}[!]${NC} $*"; }
fail()  { echo -e "  ${RED}[✗]${NC} $*"; }
head_() { echo -e "\n${WHITE}=== $* ===${NC}"; }
svc()   { systemctl is-active --quiet "$1" && echo -e "  ${GREEN}✔${NC} $1 is running" \
          || echo -e "  ${YELLOW}!${NC} $1 is NOT running"; }

# ── Banner ────────────────────────────────────────────────────────────────────
echo ""
echo -e "${BLUE}================================================================${NC}"
echo -e "${BLUE}  Kalixor SBC Platform — One-Touch Installer                  ${NC}"
echo -e "${BLUE}  Debian 13 (Trixie)                                            ${NC}"
echo -e "${BLUE}================================================================${NC}"
echo ""

# ── Root check ────────────────────────────────────────────────────────────────
if [ "$EUID" -ne 0 ]; then
    fail "Please run as root: sudo $0 $*"
    exit 1
fi

# ── OS check ─────────────────────────────────────────────────────────────────
if [ -f /etc/debian_version ]; then
    ok "OS: $(grep PRETTY_NAME /etc/os-release | cut -d= -f2 | tr -d '"')"
else
    fail "This script requires Debian Linux"
    exit 1
fi

SERVER_IP=$(hostname -I 2>/dev/null | awk '{print $1}')
[ -z "$SERVER_IP" ] && SERVER_IP="127.0.0.1"
ok "Server IP: $SERVER_IP"
echo ""

# ===========================================================================
# STEP 1 — System prerequisites
# ===========================================================================
head_ "Step 1/8 — Installing system prerequisites"

apt-get update -qq
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
    sudo curl wget gnupg2 apt-transport-https ca-certificates lsb-release \
    build-essential python3 \
    nginx \
    openssl git rsync \
    fail2ban nftables \
    wireguard wireguard-tools \
    lua5.4 lua-cjson \
    unixodbc unixodbc-dev odbc-postgresql \
    net-tools iproute2 \
    dnsutils dkms linux-headers-$(uname -r)

ok "System prerequisites installed"

# Enable base services
systemctl enable --now nginx      2>/dev/null || true
systemctl enable fail2ban         2>/dev/null || true
systemctl enable --now nftables   2>/dev/null || true
ok "Base services enabled"

# ===========================================================================
# STEP 2 — Ring2All APT repository
# ===========================================================================
head_ "Step 2/8 — Configuring Ring2All APT repository"

REPO_URL="https://repo.softswitchone.com/apt"

if [ "$SKIP_REPO" = true ]; then
    warn "--skip-repo: Skipping Ring2All repo setup"
elif grep -r "softswitchone.com/apt" /etc/apt/sources.list.d/ &>/dev/null; then
    ok "Ring2All repository already configured"
else
    step "Adding Ring2All GPG key..."
    mkdir -p /etc/apt/keyrings
    curl -fsSL "${REPO_URL}/gpgkey/ring2all.gpg" \
        | gpg --dearmor -o /etc/apt/keyrings/ring2all.gpg 2>/dev/null
    chmod 644 /etc/apt/keyrings/ring2all.gpg

    step "Adding Ring2All repository sources..."
    cat > /etc/apt/sources.list.d/ring2all.list << EOF
# Ring2All Softswitch/Kalixor Repository
# Added by install-sbc.sh on $(date -u +%Y-%m-%dT%H:%M:%SZ)
deb [signed-by=/etc/apt/keyrings/ring2all.gpg] ${REPO_URL}/base stable main
deb [signed-by=/etc/apt/keyrings/ring2all.gpg] ${REPO_URL}/core stable main
EOF
    ok "Ring2All repository added"
fi

apt-get update -qq
ok "Package lists updated"

# ===========================================================================
# STEP 3 — Node.js 22.x LTS
# ===========================================================================
head_ "Step 3/8 — Installing Node.js 22.x LTS"

if command -v node &>/dev/null && node --version 2>/dev/null | grep -q "^v22"; then
    ok "Node.js $(node --version) already installed"
else
    step "Adding NodeSource repository..."
    curl -fsSL https://deb.nodesource.com/setup_22.x | bash - >/dev/null 2>&1
    apt-get install -y nodejs >/dev/null 2>&1
    ok "Node.js $(node --version) installed"
fi

# ===========================================================================
# STEP 4 — PostgreSQL 17
# ===========================================================================
head_ "Step 4/8 — Installing PostgreSQL 17"

if command -v psql &>/dev/null; then
    ok "PostgreSQL $(psql --version | awk '{print $3}') already installed"
else
    step "Adding PostgreSQL APT repository..."
    install -d /usr/share/postgresql-common/pgdg
    curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc \
        | gpg --dearmor -o /usr/share/postgresql-common/pgdg/apt.postgresql.org.gpg >/dev/null

    echo "deb [signed-by=/usr/share/postgresql-common/pgdg/apt.postgresql.org.gpg] \
https://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" \
        > /etc/apt/sources.list.d/pgdg.list

    apt-get update -qq
    DEBIAN_FRONTEND=noninteractive apt-get install -y postgresql-17 postgresql-contrib-17 >/dev/null
    ok "PostgreSQL $(psql --version | awk '{print $3}') installed"
fi

systemctl enable --now postgresql 2>/dev/null || true
ok "PostgreSQL running"

# ===========================================================================
# STEP 5 — Kamailio 6.x
# ===========================================================================
head_ "Step 5/8 — Installing Kamailio SBC"

if [ "$SKIP_KAMAILIO" = true ]; then
    warn "--skip-sbc-kamailio: Skipping Kamailio installation"
    command -v kamailio &>/dev/null \
        && ok "Kamailio $(kamailio -V 2>&1 | head -1 | awk '{print $3}') detected" \
        || warn "Kamailio binary not found — install manually and re-run"
else
    step "Adding Kamailio official APT repository..."

    # Kamailio PPA for Debian 13 (Trixie)
    KAM_KEYRING=/usr/share/keyrings/kamailio.gpg
    curl -fsSL https://deb.kamailio.org/kamailiodebkey.gpg \
        | gpg --dearmor -o "$KAM_KEYRING" 2>/dev/null

    echo "deb [signed-by=${KAM_KEYRING}] http://deb.kamailio.org/kamailio60 trixie main
deb-src [signed-by=${KAM_KEYRING}] http://deb.kamailio.org/kamailio60 trixie main" \
        > /etc/apt/sources.list.d/kamailio.list

    apt-get update -qq 2>/dev/null || true

    step "Installing Kamailio and required modules..."
    DEBIAN_FRONTEND=noninteractive apt-get install -y \
        sbc-kamailio \
        sbc-kamailio-postgres-modules \
        sbc-kamailio-tls-modules \
        sbc-kamailio-websocket-modules \
        sbc-kamailio-utils-modules \
        sbc-kamailio-json-modules \
        sbc-kamailio-extra-modules \
        sbc-kamailio-presence-modules \
        kamcli 2>/dev/null \
    || DEBIAN_FRONTEND=noninteractive apt-get install -y \
        sbc-kamailio \
        sbc-kamailio-postgres-modules \
        sbc-kamailio-tls-modules \
        sbc-kamailio-websocket-modules \
        sbc-kamailio-utils-modules \
        sbc-kamailio-json-modules \
        sbc-kamailio-extra-modules \
        kamcli 2>/dev/null || true

    if command -v kamailio &>/dev/null; then
        ok "Kamailio $(kamailio -V 2>&1 | head -1 | awk '{print $3}') installed"
    else
        warn "Kamailio install had issues — check: apt-get install sbc-kamailio"
    fi

    # kamctlrc — PostgreSQL connection
    if [ ! -f /etc/kamailio/kamctlrc ] || ! grep -q "DBENGINE=PGSQL" /etc/kamailio/kamctlrc; then
        step "Configuring kamctlrc (PostgreSQL backend)..."
        mkdir -p /etc/kamailio
        cat > /etc/kamailio/kamctlrc << 'KAMCTLRC'
DBENGINE=PGSQL
DBHOST=localhost
DBPORT=5432
DBNAME=sbc-kamailio
DBRWUSER=sbc-kamailio
DBRWPW=kamailio2024
DBROUSER=kamailioro
DBROPW=kamailioro2024
INSTALL_EXTRA_TABLES=yes
INSTALL_PRESENCE_TABLES=yes
KAMCTLRC
        ok "kamctlrc configured"
    fi
fi

# ===========================================================================
# STEP 6 — Kamailio native database (kamdbctl create)
# ===========================================================================
head_ "Step 6/8 — Initializing Kamailio native database"

if [ "$SKIP_KAMDB" = true ]; then
    warn "--skip-kamdb: Skipping Kamailio DB initialization"
else
    # Create kamailio PostgreSQL roles
    sudo -u postgres psql -qc "CREATE ROLE kamailio   WITH LOGIN PASSWORD 'kamailio2024';"   2>/dev/null || true
    sudo -u postgres psql -qc "CREATE ROLE kamailioro WITH LOGIN PASSWORD 'kamailioro2024';" 2>/dev/null || true
    sudo -u postgres psql -qc "GRANT kamailioro TO kamailio;" 2>/dev/null || true

    # Create the database
    sudo -u postgres createdb -O kamailio sbc-kamailio 2>/dev/null || true

    # Initialize Kamailio schema using standard SQL scripts
    step "Applying native Kamailio SQL schemas..."
    KAMDB_SQL_DIR=/usr/share/kamailio/postgres
    [ -d /usr/share/sbc-kamailio/postgres ] && KAMDB_SQL_DIR=/usr/share/sbc-kamailio/postgres
    
    for f in "$KAMDB_SQL_DIR"/standard-create.sql "$KAMDB_SQL_DIR"/presence-create.sql "$KAMDB_SQL_DIR"/extra-create.sql; do
        if [ -f "$f" ]; then
            sudo -u postgres psql -d sbc-kamailio -f "$f" >/dev/null 2>&1 || true
        fi
    done

    # Grant privileges
    sudo -u postgres psql -d sbc-kamailio -qc \
        "GRANT ALL PRIVILEGES ON ALL TABLES    IN SCHEMA public TO kamailio;" 2>/dev/null || true
    sudo -u postgres psql -d sbc-kamailio -qc \
        "GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO kamailio;" 2>/dev/null || true
    sudo -u postgres psql -d sbc-kamailio -qc \
        "GRANT ALL PRIVILEGES ON ALL TABLES    IN SCHEMA public TO \"sbc-kamailio\";" 2>/dev/null || true
    sudo -u postgres psql -d sbc-kamailio -qc \
        "GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO \"sbc-kamailio\";" 2>/dev/null || true

    ok "Kamailio native DB initialized"
fi


# ===========================================================================
# STEP 7 — Install RTPEngine and softswitch-sbc
# ===========================================================================
head_ "Step 7/8 — Installing RTPEngine and Kalixor SBC"

if [ "$SKIP_RTPENGINE" = true ]; then
    warn "--skip-rtpengine: Skipping RTPEngine installation"
else
    step "Installing RTPEngine and kernel module..."
    DEBIAN_FRONTEND=noninteractive apt-get install -y dkms linux-headers-$(uname -r) ngcp-rtpengine \
        && ok "RTPEngine installed successfully" \
        || warn "RTPEngine installation had issues — verify repositories and kernel headers"
fi

step "Installing softswitch-sbc (Kalixor Admin UI & API)..."
DEBIAN_FRONTEND=noninteractive apt-get install -y softswitch-sbc \
    && ok "softswitch-sbc installed successfully" \
    || {
        fail "apt install failed — trying local .deb fallback..."
        DEB_LOCAL=$(ls softswitch-sbc_*.deb 2>/dev/null | head -1)
        if [ -n "$DEB_LOCAL" ]; then
            step "Installing from local file: ${DEB_LOCAL}..."
            dpkg -i "${DEB_LOCAL}" \
                && apt-get install -f -y >/dev/null 2>&1 \
                && ok "softswitch-sbc installed from local .deb"
        else
            fail "No local .deb file found. Download from build server manually."
            exit 1
        fi
    }

# ===========================================================================
# STEP 8 — Post-install: WireGuard + Kamailio + RTPEngine + Security
# ===========================================================================
head_ "Step 8/8 — Post-installation configuration"

# Enable and start RTPEngine daemon
if systemctl list-unit-files | grep -q ngcp-rtpengine-daemon; then
    systemctl enable --now ngcp-rtpengine-daemon 2>/dev/null || true
    ok "RTPEngine service enabled and started"
fi

# Start WireGuard if wg0.conf exists and it's not already running
if [ -f /etc/wireguard/wg0.conf ]; then
    if ! wg show wg0 &>/dev/null; then
        step "Starting WireGuard tunnel (wg0)..."
        systemctl start wg-quick@wg0 2>/dev/null \
            && ok "WireGuard wg0 started" \
            || warn "wg-quick@wg0 failed — check /etc/wireguard/wg0.conf"
    else
        ok "WireGuard wg0 already running"
    fi
fi

# Start Kamailio (postinst already patched kamailio.cfg with wg0 listen)
if command -v kamailio &>/dev/null; then
    if ! systemctl is-active --quiet kamailio 2>/dev/null; then
        step "Starting Kamailio..."
        systemctl enable kamailio 2>/dev/null || true
        systemctl start  kamailio 2>/dev/null \
            && ok "Kamailio started" \
            || warn "Kamailio failed to start — check: journalctl -u kamailio -n 30"
    else
        ok "Kamailio already running"
    fi
fi

# fail2ban — SIP protection
systemctl enable --now fail2ban 2>/dev/null || true
if [ -f /etc/fail2ban/jail.local ] && grep -q "kamailio" /etc/fail2ban/jail.local; then
    ok "fail2ban Kamailio jail already configured"
else
    step "Adding fail2ban Kamailio SIP jail..."
    cat > /etc/fail2ban/jail.d/kamailio-sbc.conf << 'F2B'
[kamailio-sbc]
enabled  = true
port     = 5060,5061
protocol = udp
filter   = kamailio
logpath  = /var/log/kamailio/kamailio.log
maxretry = 10
bantime  = 3600
findtime = 300
F2B
    systemctl reload fail2ban 2>/dev/null || true
    ok "fail2ban SIP jail configured"
fi

# nftables — open SBC ports persistently
step "Opening SBC ports in nftables..."
for PORT_PROTO in "443 tcp" "80 tcp" "5060 udp" "5060 tcp" "5061 tcp" "51820 udp"; do
    PORT=$(echo $PORT_PROTO | cut -d' ' -f1)
    PROTO=$(echo $PORT_PROTO | cut -d' ' -f2)
    nft add rule inet filter input "$PROTO" dport "$PORT" accept 2>/dev/null || true
done
nft list ruleset > /etc/nftables.conf 2>/dev/null || true
ok "Firewall rules applied (443, 80, 5060, 5061, 51820)"

# ===========================================================================
# VERIFICATION
# ===========================================================================
echo ""
echo -e "${BLUE}================================================================${NC}"
echo -e "${BLUE}  Service Status                                                ${NC}"
echo -e "${BLUE}================================================================${NC}"
svc postgresql
svc nginx
svc sbc-api
svc kamailio
if systemctl list-unit-files | grep -q ngcp-rtpengine-daemon; then
    svc ngcp-rtpengine-daemon
fi
svc fail2ban
wg show wg0 &>/dev/null \
    && echo -e "  ${GREEN}✓${NC} WireGuard wg0 is running" \
    || echo -e "  ${YELLOW}!${NC} WireGuard wg0 not started — run: systemctl start wg-quick@wg0"

# ===========================================================================
# SUMMARY
# ===========================================================================
WG_PUB=""
if [ -f /etc/wireguard/wg0.conf ]; then
    WG_PRIV=$(grep '^PrivateKey' /etc/wireguard/wg0.conf | awk '{print $3}' 2>/dev/null || true)
    [ -n "$WG_PRIV" ] && WG_PUB=$(echo "$WG_PRIV" | wg pubkey 2>/dev/null || true)
fi

echo ""
echo -e "${GREEN}================================================================${NC}"
echo -e "${GREEN}  Kalixor SBC — Installation Complete!${NC}"
echo -e "${GREEN}================================================================${NC}"
echo ""
echo -e "  ${WHITE}Access:${NC}"
echo    "    Admin UI  : https://${SERVER_IP}"
echo    "    Health    : https://${SERVER_IP}/health"
echo ""
echo -e "  ${WHITE}Initial Admin Setup:${NC}"
echo    "    The admin password is blank by default."
echo    "    You will be prompted to set it upon your first access."
echo ""
echo -e "  ${WHITE}Credentials file:${NC}"
echo    "    /etc/softswitch/sbc-credentials"
echo ""
echo -e "  ${WHITE}Network ports:${NC}"
echo    "    443/TCP   → SBC Admin HTTPS"
echo    "    5060/UDP  → SIP (Kamailio)"
echo    "    5061/TLS  → SIP TLS (MS Teams Direct Routing)"
echo    "    51820/UDP → WireGuard VPN (PBX remote registration)"
echo ""
echo -e "  ${WHITE}WireGuard VPN:${NC}"
echo    "    Interface : wg0 (10.9.0.1/24)"
echo    "    Config    : /etc/wireguard/wg0.conf"
[ -n "$WG_PUB" ] && echo "    Public Key: ${WG_PUB}"
echo ""
echo -e "  ${WHITE}Useful commands:${NC}"
echo    "    journalctl -u sbc-api -f       # API logs"
echo    "    journalctl -u kamailio -f      # SIP logs"
echo    "    wg show                        # VPN peers"
echo    "    kamctl ul show                 # SIP registrations"
echo ""
echo -e "  ${WHITE}Documentation:${NC}"
echo    "    https://ring2all.com/docs/sbc"
echo ""
