#!/bin/bash
# ============================================================
#  fix-gpu-vm.sh  —  Run this INSIDE the VM (your app server)
#  Run AFTER fix-gpu-host.sh has completed and host has rebooted
# ============================================================
set -euo pipefail

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

log()  { echo -e "${GREEN}[✓]${NC} $1"; }
warn() { echo -e "${YELLOW}[!]${NC} $1"; }
fail() { echo -e "${RED}[✗]${NC} $1"; exit 1; }
info() { echo -e "${BLUE}[i]${NC} $1"; }

echo ""
echo "======================================================"
echo "  NVIDIA Driver Fix — VM Userspace"
echo "======================================================"
echo ""

[[ $EUID -ne 0 ]] && fail "Please run as root: sudo bash fix-gpu-vm.sh"

FFMPEG="/usr/lib/jellyfin-ffmpeg/ffmpeg"
TARGET="580.65.06"
APP_DIR="/var/www/videoplatform"

# ── 1. Check Proxmox host kernel module ──────────────────────────────────────
HOST_VER=$(cat /proc/driver/nvidia/version 2>/dev/null | grep -oP '\d+\.\d+\.\d+' | head -1 || echo "unknown")
info "Proxmox host kernel module: ${HOST_VER}"

if [[ "$HOST_VER" != "580.65.06" ]]; then
    warn "Host kernel module is ${HOST_VER}, not 580.65.06."
    warn "Please run fix-gpu-host.sh on the Proxmox host first, then reboot the host."
    read -p "Continue anyway? (yes/no): " FORCE
    [[ "$FORCE" != "yes" ]] && { warn "Aborted."; exit 0; }
fi

# ── 2. Check jellyfin-ffmpeg is installed ────────────────────────────────────
[[ -x "$FFMPEG" ]] || fail "jellyfin-ffmpeg not found at ${FFMPEG}. Install it first: dpkg -i /tmp/jellyfin-ffmpeg7.deb"
log "jellyfin-ffmpeg found: $($FFMPEG -version 2>&1 | head -1)"

# ── 3. Downgrade NVIDIA userspace packages ───────────────────────────────────
CURRENT_COMPUTE=$(dpkg -l libnvidia-compute-580 2>/dev/null | awk '/^ii/{print $3}' | cut -d- -f1 || echo "none")
info "Current libnvidia-compute-580 version: ${CURRENT_COMPUTE}"

if [[ "$CURRENT_COMPUTE" == "$TARGET" ]]; then
    log "NVIDIA userspace already at ${TARGET}. Skipping downgrade."
else
    warn "Downgrading NVIDIA userspace from ${CURRENT_COMPUTE} → ${TARGET}..."
    echo ""

    UBUNTU_VER="${TARGET}-0ubuntu0.22.04.1"

    apt-get install -y --allow-downgrades \
        "libnvidia-compute-580=${UBUNTU_VER}" \
        "libnvidia-encode-580=${UBUNTU_VER}"  \
        "libnvidia-decode-580=${UBUNTU_VER}"  \
        "nvidia-utils-580=${UBUNTU_VER}"      || \
        fail "Package downgrade failed. Try: apt-get update && then re-run this script."

    log "Packages downgraded successfully."

    # Pin to prevent apt from auto-upgrading and breaking things again
    for pkg in libnvidia-compute-580 libnvidia-encode-580 libnvidia-decode-580 nvidia-utils-580; do
        apt-mark hold "$pkg"
    done
    log "Packages pinned at ${TARGET} to prevent accidental upgrades."
fi

# ── 4. Test NVENC ─────────────────────────────────────────────────────────────
echo ""
info "Testing NVENC encoding with new setup..."
TMP=$(mktemp /tmp/nvenc_test_XXXX.mp4)

"$FFMPEG" -f lavfi -i color=c=black:s=128x72:r=25 -frames:v 1 \
    -c:v h264_nvenc -y "$TMP" > /tmp/nvenc_test.log 2>&1
EXIT=$?

if [[ $EXIT -eq 0 && -s "$TMP" ]]; then
    log "NVENC test PASSED! GPU encoding is working."
    rm -f "$TMP"
    NVENC_OK=true
else
    warn "NVENC test failed (exit ${EXIT}). Falling back to CPU encoding."
    cat /tmp/nvenc_test.log | tail -5
    rm -f "$TMP"
    NVENC_OK=false
fi

# ── 5. Update app settings ────────────────────────────────────────────────────
echo ""
info "Updating application settings..."

if [[ -d "$APP_DIR" ]]; then
    # Set ffmpeg binary path
    php "$APP_DIR/artisan" tinker --execute="
        App\Models\Setting::set('ffmpeg_binary', '$FFMPEG');
        echo 'ffmpeg_binary set to: ' . App\Models\Setting::ffmpegBinary();
    " 2>/dev/null && log "App FFmpeg binary path set to: ${FFMPEG}"

    if [[ "$NVENC_OK" == "true" ]]; then
        php "$APP_DIR/artisan" tinker --execute="
            App\Models\Setting::set('gpu_enabled', 'true');
            echo 'gpu_enabled: ' . App\Models\Setting::get('gpu_enabled');
        " 2>/dev/null && log "GPU encoding enabled in app settings."
    else
        php "$APP_DIR/artisan" tinker --execute="
            App\Models\Setting::set('gpu_enabled', 'false');
            echo 'gpu_enabled set to false (CPU fallback active)';
        " 2>/dev/null && warn "GPU disabled in app settings — CPU fallback active."
    fi
else
    warn "App directory not found at ${APP_DIR}, skipping settings update."
fi

# ── 6. Summary ────────────────────────────────────────────────────────────────
echo ""
echo "======================================================"
if [[ "$NVENC_OK" == "true" ]]; then
    echo -e "${GREEN}  ALL DONE — GPU encoding is active!${NC}"
    echo ""
    echo "  FFmpeg binary : ${FFMPEG}"
    echo "  GPU encoder   : h264_nvenc (NVIDIA RTX 3060)"
    echo "  Driver match  : kernel=${HOST_VER} / userspace=${TARGET}"
else
    echo -e "${YELLOW}  DONE — Running with CPU fallback (libx264)${NC}"
    echo ""
    echo "  Videos will still encode correctly, just slightly slower."
    echo "  Check /tmp/nvenc_test.log for NVENC error details."
fi
echo "======================================================"
echo ""
