#!/bin/bash
set -Euo pipefail

TARGET_DIR="$HOME/.local/share/steam-launcher"
SWITCH_BIN="$TARGET_DIR/enter-gamesmode"
RETURN_BIN="$TARGET_DIR/leave-gamesmode"

# Try to find the user's bindings config file
BINDINGS_CONFIG=""
for location in \
    "$HOME/.config/hypr/bindings.conf" \
    "$HOME/.config/hypr/keybinds.conf" \
    "$HOME/.config/hypr/hyprland.conf"; do
  if [ -f "$location" ]; then
    BINDINGS_CONFIG="$location"
    break
  fi
done

CONFIG_FILE="/etc/gaming-mode.conf"
[[ -f "$HOME/.gaming-mode.conf" ]] && CONFIG_FILE="$HOME/.gaming-mode.conf"
# shellcheck source=/dev/null
source "$CONFIG_FILE" 2>/dev/null || true
# Set defaults for any unset variables (works even if config partially defines them)
: "${STEAM_LAUNCH_MODE:=bigpicture}"
: "${PERFORMANCE_MODE:=enabled}"

ADDED_BINDINGS=0
CREATED_TARGET_DIR=0
NEEDS_RELOGIN=0

info(){ echo "[*] $*"; }
err(){ echo "[!] $*" >&2; }

die() {
  local msg="$1"; local code="${2:-1}"
  echo "FATAL: $msg" >&2
  logger -t gaming-mode "Installation failed: $msg"
  rollback_changes
  exit "$code"
}

rollback_changes() {
  [ -f "$SWITCH_BIN" ] && rm -f "$SWITCH_BIN"
  [ -f "$RETURN_BIN" ] && rm -f "$RETURN_BIN"
  if [ "$CREATED_TARGET_DIR" -eq 1 ] && [ -d "$TARGET_DIR" ]; then
    rmdir "$TARGET_DIR" 2>/dev/null || true
  fi

  # Remove added bindings
  if [ "$ADDED_BINDINGS" -eq 1 ] && [ -n "$BINDINGS_CONFIG" ] && [ -f "$BINDINGS_CONFIG" ]; then
    sed -i '/# Gaming Mode bindings - added by installation script/,/# End Gaming Mode bindings/d' "$BINDINGS_CONFIG"
  fi
}

validate_environment() {
  command -v pacman  >/dev/null || die "pacman required"
  command -v hyprctl >/dev/null || die "hyprctl required"
  [ -n "$BINDINGS_CONFIG" ] || die "Could not find bindings config file (checked bindings.conf, keybinds.conf, hyprland.conf)"
  [ -f "$BINDINGS_CONFIG" ] || die "Bindings config file not found: $BINDINGS_CONFIG"
  # Verify Hyprland is actually configured (check if any hypr config exists)
  [ -d "$HOME/.config/hypr" ] || die "Hyprland config directory not found (~/.config/hypr)"
}

check_package() { pacman -Qi "$1" &>/dev/null; }

# Helper function: Detect Intel GPU type (xe=Arc, i915=iGPU)
# Returns: "arc", "igpu", "both", or "none"
# Sets global: has_arc, has_intel_igpu
detect_intel_gpu_type() {
  has_arc=false
  has_intel_igpu=false

  for card_device in /sys/class/drm/card*/device/driver; do
    [[ -e "$card_device" ]] || continue
    if [[ -L "$card_device" ]]; then
      local driver_name=$(basename "$(readlink -f "$card_device")" 2>/dev/null)
      case "$driver_name" in
        xe) has_arc=true ;;
        i915) has_intel_igpu=true ;;
      esac
    fi
  done

  if $has_arc && $has_intel_igpu; then
    echo "both"
  elif $has_arc; then
    echo "arc"
  elif $has_intel_igpu; then
    echo "igpu"
  else
    echo "none"
  fi
}

check_steam_dependencies() {
  info "Checking Steam dependencies for Arch Linux..."

  # Force refresh package database to avoid 404 errors from stale mirrors
  info "Force refreshing package database from all mirrors..."
  sudo pacman -Syy || die "Failed to refresh package database"

  # Prompt for full system upgrade before installing dependencies
  echo ""
  echo "════════════════════════════════════════════════════════════════"
  echo "  SYSTEM UPDATE RECOMMENDED"
  echo "════════════════════════════════════════════════════════════════"
  echo ""
  echo "  It's recommended to upgrade your system before installing"
  echo "  gaming dependencies to avoid package version conflicts."
  echo ""
  echo "  This will run: sudo pacman -Syu"
  echo ""
  echo "════════════════════════════════════════════════════════════════"
  echo ""
  read -p "Upgrade system now? [Y/n]: " -n 1 -r
  echo
  if [[ ! $REPLY =~ ^[Nn]$ ]]; then
    info "Upgrading system..."
    sudo pacman -Syu || die "Failed to upgrade system"
  else
    info "Skipping system upgrade - this may cause package conflicts"
  fi
  echo ""

  local -a missing_deps=()
  local -a optional_deps=()
  local multilib_enabled=false

  # Ensure pciutils is installed for GPU detection
  if ! command -v lspci >/dev/null 2>&1; then
    info "Installing pciutils for GPU detection..."
    sudo pacman -S --needed --noconfirm pciutils || die "Failed to install pciutils"
  fi

  # Check if multilib repository is enabled (required for 32-bit Steam libraries)
  if grep -q "^\[multilib\]" /etc/pacman.conf 2>/dev/null; then
    multilib_enabled=true
    info "Multilib repository: enabled"
  else
    err "Multilib repository: NOT enabled (required for Steam)"
    missing_deps+=("multilib-repository")
  fi

  # Core Steam dependencies
  local -a core_deps=(
    "steam"                    # Steam client
    "lib32-vulkan-icd-loader"  # 32-bit Vulkan loader
    "vulkan-icd-loader"        # 64-bit Vulkan loader
    "lib32-mesa"               # 32-bit Mesa (OpenGL)
    "mesa"                     # 64-bit Mesa
    "mesa-utils"               # Mesa utilities (glxinfo, etc.)
    "lib32-systemd"            # 32-bit systemd libs
    "lib32-glibc"              # 32-bit glibc
    "lib32-gcc-libs"           # 32-bit GCC libs
    "lib32-libx11"             # 32-bit X11
    "lib32-libxss"             # 32-bit X screensaver
    "lib32-alsa-plugins"       # 32-bit ALSA
    "lib32-libpulse"           # 32-bit PulseAudio
    "lib32-openal"             # 32-bit OpenAL
    "lib32-nss"                # 32-bit NSS
    "lib32-libcups"            # 32-bit CUPS (printing)
    "lib32-sdl2"               # 32-bit SDL2
    "lib32-freetype2"          # 32-bit fonts
    "lib32-fontconfig"         # 32-bit font config
    "ttf-liberation"           # Font package
    "xdg-user-dirs"            # User directories
  )

  # GPU-specific Vulkan drivers
  local gpu_vendor
  gpu_vendor=$(lspci 2>/dev/null | grep -iE 'vga|3d|display' || echo "")

  # Detect GPU type(s) - system may have multiple GPUs
  local has_nvidia=false has_amd=false has_intel=false has_arc=false has_intel_igpu=false

  if echo "$gpu_vendor" | grep -iq nvidia; then
    has_nvidia=true
    info "Detected NVIDIA GPU"
  fi
  if echo "$gpu_vendor" | grep -iqE 'amd|radeon|advanced micro'; then
    has_amd=true
    info "Detected AMD GPU"
  fi
  if echo "$gpu_vendor" | grep -iq intel; then
    has_intel=true
    local intel_type=$(detect_intel_gpu_type)
    case "$intel_type" in
      arc) info "Detected Intel Arc discrete GPU (xe driver)" ;;
      igpu) info "Detected Intel integrated GPU (i915 driver)" ;;
      both) info "Detected Intel Arc + integrated GPU" ;;
      *) info "Detected Intel GPU" ;;
    esac
  fi

  # Intel Arc-specific version checks
  if $has_intel; then
    echo ""
    info "Performing Intel Arc compatibility checks..."
    check_mesa_version            # Will die if Mesa too old
    echo ""
  fi

  local -a gpu_deps=()

  # NVIDIA drivers
  if $has_nvidia; then
    gpu_deps+=(
      "nvidia-utils"              # NVIDIA OpenGL/Vulkan driver
      "lib32-nvidia-utils"        # 32-bit NVIDIA driver
      "nvidia-settings"           # NVIDIA control panel
      "libva-nvidia-driver"       # VA-API support for NVIDIA
    )
    # Check if user has nvidia, nvidia-dkms, or nvidia-open-dkms installed
    if ! check_package "nvidia" && ! check_package "nvidia-dkms" && ! check_package "nvidia-open-dkms"; then
      info "Note: You may need to install 'nvidia', 'nvidia-dkms', or 'nvidia-open-dkms' kernel module"
      optional_deps+=("nvidia-dkms")
    fi
  fi

  # AMD drivers
  if $has_amd; then
    gpu_deps+=(
      "vulkan-radeon"             # AMD Vulkan driver (RADV)
      "lib32-vulkan-radeon"       # 32-bit AMD Vulkan driver
      "libva-mesa-driver"         # VA-API support for AMD
      "lib32-libva-mesa-driver"   # 32-bit VA-API
      "mesa-vdpau"                # VDPAU support
      "lib32-mesa-vdpau"          # 32-bit VDPAU
    )
    # Optional AMD-specific packages (only if not installed)
    ! check_package "xf86-video-amdgpu" && optional_deps+=("xf86-video-amdgpu")
  fi

  # Intel drivers
  if $has_intel; then
    if $has_arc; then
      # Intel Arc discrete GPUs:
      # Use a lean Vulkan + compute stack to avoid unnecessary VA-API complexity.
      gpu_deps+=(
        "vulkan-intel"              # Intel Vulkan driver (ANV)
        "lib32-vulkan-intel"        # 32-bit Intel Vulkan driver
        "vulkan-icd-loader"         # Vulkan ICD loader
        "lib32-vulkan-icd-loader"   # 32-bit Vulkan ICD loader
        "intel-compute-runtime"     # OpenCL/compute support (Arc / XE)
        "level-zero-loader"         # Intel oneAPI Level Zero (if available)
        "intel-gpu-tools"           # Intel GPU debugging and monitoring tools
      )
    else
      # Integrated Intel GPUs (UHD / Xe iGPU) – keep the full media stack.
      gpu_deps+=(
        "vulkan-intel"              # Intel Vulkan driver (ANV)
        "lib32-vulkan-intel"        # 32-bit Intel Vulkan driver
        "intel-media-driver"        # VA-API for Intel (Broadwell+)
        "libva-intel-driver"        # VA-API for older Intel
        "lib32-libva-intel-driver"  # 32-bit VA-API
        "intel-compute-runtime"     # OpenCL/compute support
        "level-zero-loader"         # Intel oneAPI Level Zero (if available)
        "intel-gpu-tools"           # Intel GPU debugging and monitoring tools
      )
    fi
  fi

  # Fallback if no GPU detected
  if ! $has_nvidia && ! $has_amd && ! $has_intel; then
    info "GPU vendor not auto-detected, installing generic Vulkan drivers..."
    gpu_deps+=("vulkan-radeon" "lib32-vulkan-radeon" "vulkan-intel" "lib32-vulkan-intel")
  fi

  # Common Vulkan tools for all GPUs
  gpu_deps+=(
    "vulkan-tools"                # vkcube and vulkaninfo
    "vulkan-mesa-layers"          # Mesa Vulkan layers
  )

  # Optional but recommended packages
  local -a recommended_deps=(
    "gamemode"                 # System optimization
    "lib32-gamemode"           # 32-bit gamemode
    "gamescope"                # Gaming compositor
    "mangohud"                 # Performance overlay
    "lib32-mangohud"           # 32-bit MangoHud
    "proton-ge-custom-bin"     # Custom Proton (AUR)
    "protontricks"             # Proton helper
  )

  # Check core dependencies
  info "Checking core Steam dependencies..."
  for dep in "${core_deps[@]}"; do
    if ! check_package "$dep"; then
      missing_deps+=("$dep")
    fi
  done

  # Check GPU-specific dependencies
  info "Checking GPU-specific dependencies..."
  for dep in "${gpu_deps[@]}"; do
    if ! check_package "$dep"; then
      missing_deps+=("$dep")
    fi
  done

  # Check recommended dependencies
  info "Checking recommended dependencies..."
  for dep in "${recommended_deps[@]}"; do
    if ! check_package "$dep"; then
      optional_deps+=("$dep")
    fi
  done

  # Report findings
  echo ""
  echo "════════════════════════════════════════════════════════════════"
  echo "  STEAM DEPENDENCY CHECK RESULTS"
  echo "════════════════════════════════════════════════════════════════"
  echo ""

  if [ "$multilib_enabled" = false ]; then
    echo "  CRITICAL: Multilib repository must be enabled!"
    echo ""
    echo "  To enable multilib, edit /etc/pacman.conf and uncomment:"
    echo "    [multilib]"
    echo "    Include = /etc/pacman.d/mirrorlist"
    echo ""
    echo "  Then run: sudo pacman -Syu"
    echo ""
    read -p "Enable multilib repository now? [y/N]: " -n 1 -r
    echo
    if [[ $REPLY =~ ^[Yy]$ ]]; then
      enable_multilib_repo
    else
      die "Multilib repository is required for Steam"
    fi
  fi

  # Remove "multilib-repository" from missing_deps if it was added
  local -a clean_missing=()
  for item in "${missing_deps[@]}"; do
    [[ -n "$item" && "$item" != "multilib-repository" ]] && clean_missing+=("$item")
  done
  missing_deps=("${clean_missing[@]}")

  if ((${#missing_deps[@]})); then
    echo "  MISSING REQUIRED PACKAGES (${#missing_deps[@]}):"
    for dep in "${missing_deps[@]}"; do
      echo "    • $dep"
    done
    echo ""

    read -p "Install missing required packages? [Y/n]: " -n 1 -r
    echo
    if [[ ! $REPLY =~ ^[Nn]$ ]]; then
      info "Installing missing dependencies..."
      sudo pacman -S --needed "${missing_deps[@]}" || die "Failed to install Steam dependencies"
      info "Required dependencies installed successfully"
    else
      err "Cannot proceed without required dependencies"
      die "Missing required Steam dependencies"
    fi
  else
    info "All required Steam dependencies are installed!"
  fi

  echo ""
  if ((${#optional_deps[@]})); then
    echo "  RECOMMENDED PACKAGES (${#optional_deps[@]}):"
    for dep in "${optional_deps[@]}"; do
      echo "    • $dep"
    done
    echo ""

    read -p "Install recommended packages? [y/N]: " -n 1 -r
    echo
    if [[ $REPLY =~ ^[Yy]$ ]]; then
      info "Installing recommended packages..."
      # Filter out AUR packages (proton-ge-custom-bin needs AUR helper)
      local -a pacman_optional=()
      local -a aur_optional=()
      for dep in "${optional_deps[@]}"; do
        if pacman -Si "$dep" &>/dev/null; then
          pacman_optional+=("$dep")
        else
          aur_optional+=("$dep")
        fi
      done

      if ((${#pacman_optional[@]})); then
        sudo pacman -S --needed --noconfirm "${pacman_optional[@]}" || info "Some optional packages failed to install"
      fi

      if ((${#aur_optional[@]})); then
        echo ""
        info "The following packages are from AUR and need an AUR helper:"
        for dep in "${aur_optional[@]}"; do
          echo "    • $dep"
        done
        echo ""

        # Check for AUR helpers
        if command -v yay >/dev/null 2>&1; then
          read -p "Install AUR packages with yay? [y/N]: " -n 1 -r
          echo
          if [[ $REPLY =~ ^[Yy]$ ]]; then
            yay -S --needed --noconfirm "${aur_optional[@]}" || info "Some AUR packages failed to install"
          fi
        elif command -v paru >/dev/null 2>&1; then
          read -p "Install AUR packages with paru? [y/N]: " -n 1 -r
          echo
          if [[ $REPLY =~ ^[Yy]$ ]]; then
            paru -S --needed --noconfirm "${aur_optional[@]}" || info "Some AUR packages failed to install"
          fi
        else
          info "No AUR helper found (yay/paru). Install manually if desired."
        fi
      fi
    fi
  else
    info "All recommended packages are already installed!"
  fi

  echo ""
  echo "════════════════════════════════════════════════════════════════"

  # Additional Steam configuration checks
  check_steam_config
}

enable_multilib_repo() {
  info "Enabling multilib repository..."

  # Backup pacman.conf
  sudo cp /etc/pacman.conf "/etc/pacman.conf.backup.$(date +%Y%m%d%H%M%S)" || die "Failed to backup pacman.conf"

  # Enable multilib by uncommenting the lines
  sudo sed -i '/^#\[multilib\]/,/^#Include/ s/^#//' /etc/pacman.conf || die "Failed to enable multilib"

  # Verify it was enabled
  if grep -q "^\[multilib\]" /etc/pacman.conf 2>/dev/null; then
    info "Multilib repository enabled successfully"
    echo ""
    info "Updating system to enable multilib packages..."
    read -p "Proceed with system upgrade? [Y/n]: " -n 1 -r
    echo
    if [[ ! $REPLY =~ ^[Nn]$ ]]; then
      sudo pacman -Syu || die "Failed to update and upgrade system"
    else
      die "System upgrade required after enabling multilib - run 'sudo pacman -Syu' and try again"
    fi
  else
    die "Failed to enable multilib repository"
  fi
}

check_steam_config() {
  info "Checking Steam configuration..."

  # Check for proper permissions and offer to add user to groups
  local missing_groups=()

  if ! groups | grep -q '\bvideo\b'; then
    missing_groups+=("video")
  fi

  if ! groups | grep -q '\binput\b'; then
    missing_groups+=("input")
  fi

  if ((${#missing_groups[@]})); then
    echo ""
    echo "════════════════════════════════════════════════════════════════"
    echo "  USER GROUP PERMISSIONS"
    echo "════════════════════════════════════════════════════════════════"
    echo ""
    echo "  Your user needs to be added to the following groups:"
    echo ""
    for group in "${missing_groups[@]}"; do
      case "$group" in
        video)
          echo "    • video  - Required for GPU hardware access"
          ;;
        input)
          echo "    • input  - Required for controller/gamepad support"
          ;;
      esac
    done
    echo ""
    echo "  Without these groups, you may experience:"
    echo "    - GPU access issues"
    echo "    - Controller/gamepad not working in games"
    echo ""
    echo "  NOTE: After adding groups, you MUST log out and log back in"
    echo "        for the changes to take effect."
    echo ""
    echo "════════════════════════════════════════════════════════════════"
    echo ""

    read -p "Add user to ${missing_groups[*]} group(s)? [Y/n]: " -n 1 -r
    echo
    if [[ ! $REPLY =~ ^[Nn]$ ]]; then
      # Join groups with comma for usermod
      local groups_to_add=$(IFS=,; echo "${missing_groups[*]}")

      info "Adding user to groups: $groups_to_add"
      if sudo usermod -aG "$groups_to_add" "$USER"; then
        info "Successfully added user to group(s): $groups_to_add"
        NEEDS_RELOGIN=1
      else
        err "Failed to add user to groups"
        info "You can manually add yourself with: sudo usermod -aG $groups_to_add $USER"
      fi
    else
      info "Skipping group assignment - you may encounter GPU/controller issues"
    fi
  else
    info "User is in video and input groups - permissions OK"
  fi

  # Check for Steam directory
  if [ -d "$HOME/.steam" ]; then
    info "Steam directory found at ~/.steam"
  fi

  if [ -d "$HOME/.local/share/Steam" ]; then
    info "Steam data directory found at ~/.local/share/Steam"
  fi

  # Check for Proton/Wine dependencies
  if check_package "wine"; then
    info "Wine is installed (helps with some Windows games)"
  else
    info "Tip: Install 'wine' for better Windows game compatibility"
  fi

  # Check for controller support
  if check_package "steam-native-runtime"; then
    info "Steam native runtime installed (better compatibility)"
  fi

  # Check kernel parameters for gaming
  if [ -f /proc/sys/vm/swappiness ]; then
    local swappiness
    swappiness=$(cat /proc/sys/vm/swappiness)
    if [ "$swappiness" -gt 10 ]; then
      info "Tip: Consider lowering vm.swappiness to 10 for better gaming performance"
      info "     Current value: $swappiness"
    fi
  fi

  # Check for esync/fsync support
  local max_files
  max_files=$(ulimit -n 2>/dev/null || echo "0")
  if [ "$max_files" -lt 524288 ]; then
    info "Tip: Increase open file limit for esync support"
    info "     Add to /etc/security/limits.conf:"
    info "     * hard nofile 524288"
    info "     * soft nofile 524288"
  fi
}

check_mesa_version() {
  local mesa_version=""

  # Try to get Mesa version from multiple sources
  if command -v glxinfo >/dev/null 2>&1; then
    # Extract Mesa version without Perl regex
    mesa_version=$(glxinfo 2>/dev/null | grep "OpenGL version string" | sed -n 's/.*Mesa \([0-9]\+\.[0-9]\+\).*/\1/p' | head -n1)
  fi

  # Fallback: check package version
  if [ -z "$mesa_version" ]; then
    mesa_version=$(pacman -Q mesa 2>/dev/null | awk '{print $2}' | cut -d'-' -f1)
  fi

  if [ -z "$mesa_version" ]; then
    info "Could not detect Mesa version - will install latest from repositories"
    return 0
  fi

  # Strip epoch prefix if present (e.g., "1:25.0.0" -> "25.0.0")
  mesa_version=$(echo "$mesa_version" | sed 's/^[0-9]*://')

  local major minor
  major=$(echo "$mesa_version" | cut -d'.' -f1)
  minor=$(echo "$mesa_version" | cut -d'.' -f2)

  local version_number=$((major * 100 + minor))
  local required_version=2202  # 22.2
  local recommended_version=2300  # 23.0

  if [ "$version_number" -lt "$required_version" ]; then
    echo ""
    echo "════════════════════════════════════════════════════════════════"
    echo "  ⚠️  MESA VERSION WARNING"
    echo "════════════════════════════════════════════════════════════════"
    echo ""
    echo "  Current Mesa: $mesa_version"
    echo "  Required for Intel Arc: 22.2 or higher"
    echo "  Recommended: 23.0 or higher"
    echo ""
    echo "  Intel Arc GPUs require Mesa 22.2+ for proper Vulkan support."
    echo "  Your current version is too old and will cause issues."
    echo ""
    echo "════════════════════════════════════════════════════════════════"
    echo ""
    die "Mesa version too old for Intel Arc. Update your system: sudo pacman -Syu"
  elif [ "$version_number" -lt "$recommended_version" ]; then
    info "Mesa $mesa_version detected (meets minimum 22.2, but 23.0+ recommended)"
  else
    info "Mesa version $mesa_version meets Intel Arc recommendations (23.0+)"
  fi

  return 0
}

setup_performance_permissions() {
  local udev_rules_file="/etc/udev/rules.d/99-gaming-performance.rules"

  # Check if udev rules already exist
  if [ -f "$udev_rules_file" ]; then
    info "Performance udev rules already installed"
    return 0
  fi

  echo ""
  echo "════════════════════════════════════════════════════════════════"
  echo "  ⚠️  PERFORMANCE PERMISSIONS SETUP"
  echo "════════════════════════════════════════════════════════════════"
  echo ""
  echo "  To avoid sudo password prompts during gaming, we need to set"
  echo "  up permissions for CPU and GPU performance control."
  echo ""
  echo "  This will create udev rules to allow users to modify:"
  echo "  • CPU governor (performance mode)"
  echo "  • GPU performance settings (AMD/Intel/NVIDIA)"
  echo ""
  echo "  This is a one-time setup that requires sudo."
  echo "  After this, gaming mode will launch without password prompts."
  echo ""
  echo "════════════════════════════════════════════════════════════════"
  echo ""

  read -p "Set up passwordless performance controls? [Y/n]: " -n 1 -r
  echo

  if [[ $REPLY =~ ^[Nn]$ ]]; then
    info "Skipping udev rules setup"
    info "Note: You'll need to enter your password each time you launch gaming mode"
    return 0
  fi

  info "Creating udev rules for performance control..."

  # Create the udev rules file
  sudo tee "$udev_rules_file" > /dev/null <<'UDEV_RULES'
# Gaming Mode Performance Control Rules
# Allow users to modify CPU governor and GPU performance settings without sudo

# CPU governor control (all CPUs)
KERNEL=="cpu[0-9]*", SUBSYSTEM=="cpu", ACTION=="add", RUN+="/bin/chmod 666 /sys/devices/system/cpu/%k/cpufreq/scaling_governor"

# AMD GPU performance control
KERNEL=="card[0-9]", SUBSYSTEM=="drm", DRIVERS=="amdgpu", ACTION=="add", RUN+="/bin/chmod 666 /sys/class/drm/%k/device/power_dpm_force_performance_level"

# Intel GPU frequency control (i915 driver - NOT used for xe driver GPUs)
# Note: This script ignores i915 GPUs at runtime to prevent conflicts with xe driver
KERNEL=="card[0-9]", SUBSYSTEM=="drm", DRIVERS=="i915", ACTION=="add", RUN+="/bin/chmod 666 /sys/class/drm/%k/gt_boost_freq_mhz"
KERNEL=="card[0-9]", SUBSYSTEM=="drm", DRIVERS=="i915", ACTION=="add", RUN+="/bin/chmod 666 /sys/class/drm/%k/gt_min_freq_mhz"
KERNEL=="card[0-9]", SUBSYSTEM=="drm", DRIVERS=="i915", ACTION=="add", RUN+="/bin/chmod 666 /sys/class/drm/%k/gt_max_freq_mhz"

# Intel Arc (Xe) GPU control - NOT CURRENTLY FUNCTIONAL
# The xe driver does not expose user-controllable frequency knobs in sysfs yet
# Leaving these here for future kernel support
KERNEL=="card[0-9]", SUBSYSTEM=="drm", DRIVERS=="xe", ACTION=="add", RUN+="/bin/chmod 666 /sys/class/drm/%k/device/power/control"
UDEV_RULES

  if [ $? -ne 0 ]; then
    err "Failed to create udev rules"
    info "You can manually create $udev_rules_file later"
    return 1
  fi

  info "Udev rules created successfully"

  # Reload udev rules
  info "Reloading udev rules..."
  sudo udevadm control --reload-rules || info "Failed to reload udev rules"
  sudo udevadm trigger --subsystem-match=cpu --subsystem-match=drm || info "Failed to trigger udev"

  # Apply permissions immediately (don't wait for reboot)
  info "Applying permissions immediately..."

  # CPU governor permissions
  if [ -d /sys/devices/system/cpu/cpu0/cpufreq ]; then
    sudo chmod 666 /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor 2>/dev/null || \
      info "Could not set CPU governor permissions (will work after reboot)"
  fi

  # Detect GPU and apply permissions
  local gpu_vendor
  gpu_vendor=$(lspci 2>/dev/null | grep -iE 'vga|3d|display' || echo "")

  # AMD GPU permissions
  if echo "$gpu_vendor" | grep -iqE 'amd|radeon|advanced micro'; then
    sudo chmod 666 /sys/class/drm/card*/device/power_dpm_force_performance_level 2>/dev/null || \
      info "Could not set AMD GPU permissions (will work after reboot)"
  fi

  # Intel i915 GPU permissions (will be ignored at runtime)
  if echo "$gpu_vendor" | grep -iq intel; then
    sudo chmod 666 /sys/class/drm/card*/gt_boost_freq_mhz 2>/dev/null || true
    sudo chmod 666 /sys/class/drm/card*/gt_min_freq_mhz 2>/dev/null || true
    sudo chmod 666 /sys/class/drm/card*/gt_max_freq_mhz 2>/dev/null || true
  fi

  info "✓ Performance permissions configured"
  info "Gaming mode will now launch without password prompts"

  return 0
}

setup_intel_arc_workarounds() {
  # Fix GTK4 rendering issues on Intel Arc GPUs (Nautilus, GNOME apps)
  # Force OpenGL renderer instead of Vulkan to prevent visual glitches

  local intel_type=$(detect_intel_gpu_type)
  [[ "$intel_type" == "arc" || "$intel_type" == "both" ]] || return 0

  local env_dir="$HOME/.config/environment.d"
  local env_file="$env_dir/10-intel-arc-gtk.conf"

  # Check if workaround already applied
  if [[ -f "$env_file" ]] && grep -q "GSK_RENDERER=" "$env_file" 2>/dev/null; then
    local current_renderer=$(grep "GSK_RENDERER=" "$env_file" | cut -d'=' -f2)
    info "Intel Arc GTK4 workaround already configured (GSK_RENDERER=$current_renderer)"
    return 0
  fi

  echo ""
  info "Intel Arc GTK4 Rendering Fix (REQUIRED)"
  info "Applying GSK_RENDERER=gl to fix Nautilus/GTK4 visual glitches"
  info "Config: $env_file"
  info "Note: Log out and log back in after installation"
  echo ""

  local renderer="gl"

  # Create environment.d directory if it doesn't exist
  mkdir -p "$env_dir" || die "Failed to create $env_dir"

  # Create the environment file
  info "Creating GTK4 renderer configuration..."
  cat > "$env_file" <<ENV_CONFIG
# Intel Arc GTK4 Rendering Fix
# Added by gaming mode installer
# Fixes visual glitches in GTK4 applications on Wayland with Intel Arc GPUs

GSK_RENDERER=$renderer
ENV_CONFIG

  if [ $? -ne 0 ]; then
    err "Failed to create environment file"
    info "You can manually create $env_file with: GSK_RENDERER=$renderer"
    return 1
  fi

  info "✓ Intel Arc GTK4 fix configured (GSK_RENDERER=$renderer)"
  info "Changes will take effect after logging out and back in"

  # Set a flag to remind user to log out
  NEEDS_RELOGIN=1

  return 0
}

setup_requirements() {
  local -a required_packages=("steam" "gamescope" "mangohud" "gum" "python" "libcap" "gamemode" "curl" "pciutils")
  local -a packages_to_install=()
  for pkg in "${required_packages[@]}"; do
    check_package "$pkg" || packages_to_install+=("$pkg")
  done

  if ((${#packages_to_install[@]})); then
    info "The following packages are required: ${packages_to_install[*]}"
    read -p "Install missing packages? [Y/n]: " -n 1 -r
    echo
    if [[ ! $REPLY =~ ^[Nn]$ ]]; then
      sudo pacman -S --needed "${packages_to_install[@]}" || die "package install failed"
    else
      die "Required packages missing - cannot continue"
    fi
  else
    info "All required packages present."
  fi

  # Set up passwordless performance controls
  setup_performance_permissions

  # Fix Intel Arc GTK4 rendering issues (Nautilus glitches, etc.)
  setup_intel_arc_workarounds

  if [[ "${PERFORMANCE_MODE,,}" == "enabled" ]] && command -v gamescope >/dev/null 2>&1; then
    # Check if capability is already set before trying to set it
    if ! getcap "$(command -v gamescope)" 2>/dev/null | grep -q 'cap_sys_nice'; then
      echo ""
      echo "════════════════════════════════════════════════════════════════"
      echo "  ⚠️  GAMESCOPE CAPABILITY REQUEST"
      echo "════════════════════════════════════════════════════════════════"
      echo ""
      echo "  Performance mode requires granting cap_sys_nice to gamescope."
      echo ""
      echo "  This allows gamescope to:"
      echo "  • Run with real-time priority (--rt flag)"
      echo "  • Reduce latency and improve frame pacing"
      echo ""
      echo "  Security note: This capability will be granted to ALL users"
      echo "  who can execute $(command -v gamescope)"
      echo ""
      echo "  You can remove it later with:"
      echo "  sudo setcap -r $(command -v gamescope)"
      echo ""
      echo "════════════════════════════════════════════════════════════════"
      echo ""
      read -p "Grant cap_sys_nice to gamescope? [y/N]: " -n 1 -r
      echo
      if [[ $REPLY =~ ^[Yy]$ ]]; then
        sudo setcap 'cap_sys_nice+ep' "$(command -v gamescope)" || info "setcap failed; --rt may be ignored."
        info "cap_sys_nice granted to gamescope"
      else
        info "Skipping cap_sys_nice - gamescope will run without real-time priority"
        info "Performance mode will still work but with slightly higher latency"
      fi
    else
      info "Gamescope already has cap_sys_nice capability"
    fi
  fi
}

deploy_launchers() {
  if [ ! -d "$TARGET_DIR" ]; then
    mkdir -p "$TARGET_DIR" || die "cannot create $TARGET_DIR"
    CREATED_TARGET_DIR=1
  fi

  cat > "$SWITCH_BIN" <<'EOF'
#!/bin/bash
set -Euo pipefail
STATE_DIR="$HOME/.cache/gaming-session"
LOCK_FILE="$STATE_DIR/idle-prevention.lock"
SESSION_FILE="$STATE_DIR/session.pid"
CONFIG_FILE="/etc/gaming-mode.conf"
[[ -f "$HOME/.gaming-mode.conf" ]] && CONFIG_FILE="$HOME/.gaming-mode.conf"
source "$CONFIG_FILE" 2>/dev/null || true
# Set defaults for any unset variables (works even if config partially defines them)
: "${STEAM_LAUNCH_MODE:=bigpicture}"
: "${PERFORMANCE_MODE:=enabled}"

# Cleanup function to restore system state on failure
cleanup_on_error() {
  echo "[!] Error occurred, restoring system state..." >&2

  # Restore CPU governor
  if [[ -f "$STATE_DIR/original_governors" ]]; then
    while IFS=: read -r cpu_path original_gov; do
      [[ -z "$cpu_path" || -z "$original_gov" || "$original_gov" == "unknown" ]] && continue
      if [[ -f "$cpu_path" ]]; then
        echo "$original_gov" > "$cpu_path" 2>/dev/null || \
          echo "$original_gov" | sudo tee "$cpu_path" >/dev/null 2>&1 || true
      fi
    done < "$STATE_DIR/original_governors"
    rm -f "$STATE_DIR/original_governors"
  fi

  # Restore GPU performance mode
  if [[ -f "$STATE_DIR/gpu_perf_mode" ]]; then
    while IFS=: read -r gpu_path original_mode; do
      [[ -z "$gpu_path" || -z "$original_mode" ]] && continue
      [[ "$original_mode" == "nvidia_optimized" || "$original_mode" == "amd_optimized" || "$original_mode" == "xe_optimized" ]] && continue
      if [[ -f "$gpu_path" ]]; then
        echo "$original_mode" > "$gpu_path" 2>/dev/null || \
          echo "$original_mode" | sudo tee "$gpu_path" >/dev/null 2>&1 || true
      fi
    done < "$STATE_DIR/gpu_perf_mode"
    # Restore NVIDIA settings
    if grep -q "nvidia_optimized" "$STATE_DIR/gpu_perf_mode" 2>/dev/null; then
      command -v nvidia-settings >/dev/null 2>&1 && nvidia-settings -a "[gpu:0]/GpuPowerMizerMode=0" >/dev/null 2>&1 || true
      command -v nvidia-smi >/dev/null 2>&1 && nvidia-smi -pm 0 >/dev/null 2>&1 || true
    fi
    rm -f "$STATE_DIR/gpu_perf_mode"
  fi

  # Restart hypridle only if it was running before gaming mode
  if [[ -f "$STATE_DIR/hypridle_state" ]]; then
    if [[ "$(cat "$STATE_DIR/hypridle_state" 2>/dev/null)" == "running" ]]; then
      if command -v hypridle >/dev/null 2>&1 && ! pgrep -x hypridle >/dev/null 2>&1; then
        nohup hypridle >/dev/null 2>&1 &
        disown
      fi
    fi
    rm -f "$STATE_DIR/hypridle_state"
  fi

  # Clean up state files
  rm -f "$LOCK_FILE" "$SESSION_FILE" 2>/dev/null || true
}

# Set trap to cleanup on any error
trap cleanup_on_error ERR

steam_icon() { echo "steam"; }

# Helper function to center output in terminal
center_output() {
  local width=${1:-70}
  local term_width=$(tput cols)
  local padding=$(( (term_width - width) / 2 ))
  [[ $padding -lt 0 ]] && padding=0
  while IFS= read -r line; do
    printf "%${padding}s%s\n" "" "$line"
  done
}

center_notify() {
  local msg="$*"
  # TUI notification using gum - centered (uses terminal theme colors)
  clear
  local term_width=$(tput cols)
  local box_width=50
  local padding=$(( (term_width - box_width) / 2 ))
  [[ $padding -lt 0 ]] && padding=0
  echo ""
  gum style --align center --width 50 --border normal --padding "1 2" "$msg" | while IFS= read -r line; do printf "%${padding}s%s\\n" "" "$line"; done
  sleep 2
}

get_display() {
  local j; j="$(hyprctl monitors -j 2>/dev/null || true)"
  if [[ -z "$j" ]]; then echo "1920 1080 60"; return; fi
  echo "$j" | python3 -c "
import json,sys
try:
  d=json.load(sys.stdin); m=d[0] if d else {}
  print(int(m.get('width',1920)), int(m.get('height',1080)), int(round(m.get('refreshRate',60))))
except Exception:
  print('1920 1080 60')
"
}

read -r horizontal_res vertical_res monitor_hz <<<"$(get_display)"
DISPLAY_WIDTH="$horizontal_res"; DISPLAY_HEIGHT="$vertical_res"; REFRESH_RATE="$monitor_hz"

# Detect system theme and set gum colors to match Omarchy theme
detect_system_theme() {
  local omarchy_theme_dir="$HOME/.config/omarchy/current/theme"
  local ghostty_conf="$omarchy_theme_dir/ghostty.conf"

  # Default colors (fallback)
  local accent_color="6"      # Cyan (ANSI color 6)
  local border_color="7"      # White/light gray
  local cursor_color="6"      # Cyan

  # Read colors from Omarchy ghostty theme if available
  if [[ -f "$ghostty_conf" ]]; then
    # Extract accent color (use palette 6 or 2 as accent - typically cyan/green)
    local palette_6=$(grep "^palette = 6=" "$ghostty_conf" 2>/dev/null | cut -d'=' -f3 | tr -d ' #')
    local palette_2=$(grep "^palette = 2=" "$ghostty_conf" 2>/dev/null | cut -d'=' -f3 | tr -d ' #')

    if [[ -n "$palette_6" ]]; then
      # Convert hex to gum color (use the hex directly)
      accent_color="#$palette_6"
      cursor_color="#$palette_6"
    elif [[ -n "$palette_2" ]]; then
      accent_color="#$palette_2"
      cursor_color="#$palette_2"
    fi

    # Get foreground color for borders
    local fg_color=$(grep "^foreground = " "$ghostty_conf" 2>/dev/null | cut -d'=' -f2 | tr -d ' ')
    if [[ -n "$fg_color" ]]; then
      border_color="$fg_color"
    fi
  fi

  # Set gum environment variables to match theme
  export GUM_CHOOSE_CURSOR_FOREGROUND="$cursor_color"
  export GUM_CHOOSE_SELECTED_FOREGROUND="$accent_color"
  export GUM_STYLE_BORDER_FOREGROUND="$border_color"
  export GUM_SPIN_SPINNER_FOREGROUND="$accent_color"
}

detect_system_theme

# Check if previous settings exist
SETTINGS_FILE="$STATE_DIR/last-settings"
USE_PREVIOUS=false

# Initialize padding for centering (used in all paths)
term_width=$(tput cols)
menu_width=75
menu_pad=$(( (term_width - menu_width) / 2 ))
[[ $menu_pad -lt 0 ]] && menu_pad=0
pad_str=$(printf "%${menu_pad}s" "")

clear
echo ""
gum style --align center --width 70 --border double --padding "1 2" $'W.O.P.R\n\nShall we play a game?' | center_output 74

if [[ -f "$SETTINGS_FILE" ]]; then
  # Ask user if they want to use previous settings
  echo ""
  gum style --align center --width 70 --bold "Previous settings found." | center_output 70
  echo ""

  # Calculate padding for confirm dialog
  term_width=$(tput cols)
  confirm_width=40
  confirm_pad=$(( (term_width - confirm_width) / 2 ))
  [[ $confirm_pad -lt 0 ]] && confirm_pad=0
  confirm_pad_str=$(printf "%${confirm_pad}s" "")

  gum style --align center --width 70 "Use previous settings?" | center_output 70
  echo ""

  CONFIRM_CHOICE=$(gum choose --height 6 \
    "${confirm_pad_str}Yes - Use previous settings" \
    "${confirm_pad_str}No - Configure new settings") || CONFIRM_CHOICE=""

  if [[ "$CONFIRM_CHOICE" == *"Yes"* ]]; then
    USE_PREVIOUS=true
    source "$SETTINGS_FILE"
  else
    USE_PREVIOUS=false
  fi
fi

if [[ "$USE_PREVIOUS" == false ]]; then
  # Show resolution selection menu
  clear
  echo ""
  gum style --align center --width 70 --border double --padding "1 2" "🎮 Gaming Mode - Resolution Settings" | center_output 74
  echo ""
  gum style --align center --width 70 --faint "Current Display: ${DISPLAY_WIDTH}x${DISPLAY_HEIGHT} @ ${REFRESH_RATE}Hz" | center_output 70
  echo ""
  gum style --align center --width 70 "Select your preferred gaming resolution:" | center_output 70
  echo ""

  # Format native resolution option to align with others (30 chars before │)
  native_res="${DISPLAY_WIDTH}x${DISPLAY_HEIGHT}"
  native_option=$(printf "%-30s" "$native_res")

  RESOLUTION_CHOICE=$(gum choose --height 12 \
    "${pad_str}${native_option}│  Render at native resolution (best quality)" \
    "${pad_str}1440p Upscaled                │  Render at 1080p, upscale to 1440p (better FPS)" \
    "${pad_str}1440p (2560x1440)             │  Render at 1440p resolution" \
    "${pad_str}UHD Upscaled                  │  Render at 1440p, upscale to 4K (balanced)" \
    "${pad_str}UHD (3840x2160)               │  Render at 4K/UHD resolution") || {
    center_notify "Gaming Mode cancelled"
    exit 0
  }

  # If user cancelled, exit
  if [[ -z "$RESOLUTION_CHOICE" ]]; then
    center_notify "Gaming Mode cancelled"
    exit 0
  fi

  # Extract just the resolution name (before the │), removing padding
  RESOLUTION_CHOICE=$(echo "$RESOLUTION_CHOICE" | sed 's/^[[:space:]]*//' | sed 's/[[:space:]]*│.*//' | xargs)

  # Convert native resolution to standard format for matching
  if [[ "$RESOLUTION_CHOICE" == "${DISPLAY_WIDTH}x${DISPLAY_HEIGHT}" ]]; then
    RESOLUTION_CHOICE="Native (${DISPLAY_WIDTH}x${DISPLAY_HEIGHT})"
  fi

  # Show MangoHud preset selection
  clear
  echo ""
  gum style --align center --width 70 --border double --padding "1 2" "🎮 Gaming Mode - MangoHud Settings" | center_output 74
  echo ""
  gum style --align center --width 70 "Select your preferred performance overlay:" | center_output 70
  echo ""

  MANGOHUD_CHOICE=$(gum choose --height 10 \
    "${pad_str}Off         │  No performance overlay (cleanest view)" \
    "${pad_str}Minimal     │  FPS counter only (recommended)" \
    "${pad_str}Full Stats  │  Detailed metrics (CPU, GPU, temps, frametime)") || {
    center_notify "Gaming Mode cancelled"
    exit 0
  }

  # If user cancelled, exit
  if [[ -z "$MANGOHUD_CHOICE" ]]; then
    center_notify "Gaming Mode cancelled"
    exit 0
  fi

  # Extract just the preset name (before the │), removing padding
  MANGOHUD_CHOICE=$(echo "$MANGOHUD_CHOICE" | sed 's/^[[:space:]]*//' | sed 's/  │.*//' | xargs)

  # Save settings for next time
  mkdir -p "$STATE_DIR"
  cat > "$SETTINGS_FILE" <<SETTINGS
RESOLUTION_CHOICE="$RESOLUTION_CHOICE"
MANGOHUD_CHOICE="$MANGOHUD_CHOICE"
SETTINGS

fi

# Set game rendering and output resolution based on choice
game_width="$DISPLAY_WIDTH"
game_height="$DISPLAY_HEIGHT"
output_width="$DISPLAY_WIDTH"
output_height="$DISPLAY_HEIGHT"

case "$RESOLUTION_CHOICE" in
  "Native (${DISPLAY_WIDTH}x${DISPLAY_HEIGHT})")
    game_width="$DISPLAY_WIDTH"
    game_height="$DISPLAY_HEIGHT"
    output_width="$DISPLAY_WIDTH"
    output_height="$DISPLAY_HEIGHT"
    ;;
  "UHD (3840x2160)")
    game_width=3840
    game_height=2160
    output_width=3840
    output_height=2160
    ;;
  "UHD Upscaled")
    game_width=2560
    game_height=1440
    output_width=3840
    output_height=2160
    ;;
  "1440p (2560x1440)")
    game_width=2560
    game_height=1440
    output_width=2560
    output_height=1440
    ;;
  "1440p Upscaled")
    game_width=1920
    game_height=1080
    output_width=2560
    output_height=1440
    ;;
esac

mkdir -p "$STATE_DIR"
: > "$LOCK_FILE"

# Save hypridle state and terminate if running
if pgrep -x hypridle >/dev/null 2>&1; then
  # Mark that hypridle was running so we can restore it later
  echo "running" > "$STATE_DIR/hypridle_state"

  pkill hypridle 2>/dev/null
  # Wait up to 2 seconds for graceful shutdown
  for i in {1..4}; do
    sleep 0.5
    pgrep -x hypridle >/dev/null 2>&1 || break
  done
  # Force kill if still running
  pkill -9 hypridle 2>/dev/null || true
else
  # Mark that hypridle was not running
  echo "stopped" > "$STATE_DIR/hypridle_state"
fi

# ===== CPU GOVERNOR OPTIMIZATION =====
# Set CPU to performance mode for lower latency and consistent frame times
if [[ -d /sys/devices/system/cpu/cpu0/cpufreq ]]; then
  # Save current governor for each CPU (handles hybrid CPUs with different governors)
  : > "$STATE_DIR/original_governors"
  for cpu in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor; do
    if [[ -f "$cpu" ]]; then
      current_gov=$(cat "$cpu" 2>/dev/null || echo "unknown")
      echo "$cpu:$current_gov" >> "$STATE_DIR/original_governors"
    fi
  done

  # Set all CPUs to performance mode
  for cpu in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor; do
    if [[ -f "$cpu" ]]; then
      if [[ -w "$cpu" ]]; then
        echo performance > "$cpu" 2>/dev/null || \
          echo performance | sudo tee "$cpu" >/dev/null 2>&1
      else
        echo performance | sudo tee "$cpu" >/dev/null 2>&1 || true
      fi
    fi
  done
fi

# ===== GPU PERFORMANCE MODE =====
# Force GPU to maximum clocks for stable performance
# Initialize GPU state file (clear any old data)
: > "$STATE_DIR/gpu_perf_mode"

GPU_VENDOR=$(lspci 2>/dev/null | grep -iE 'vga|3d|display' || echo "")

# Detect all GPU types
HAS_AMD=false
HAS_NVIDIA=false
HAS_INTEL=false

echo "$GPU_VENDOR" | grep -iqE 'amd|radeon|advanced micro' && HAS_AMD=true
echo "$GPU_VENDOR" | grep -iq nvidia && HAS_NVIDIA=true
echo "$GPU_VENDOR" | grep -iq intel && HAS_INTEL=true

# AMD GPU optimization
if $HAS_AMD; then
  for gpu in /sys/class/drm/card*/device/power_dpm_force_performance_level; do
    if [[ -f "$gpu" ]]; then
      # Save current mode
      current_mode=$(cat "$gpu" 2>/dev/null || echo "auto")
      echo "$gpu:$current_mode" >> "$STATE_DIR/gpu_perf_mode"

      # Set to high performance
      if [[ -w "$gpu" ]]; then
        echo high > "$gpu" 2>/dev/null || \
          echo high | sudo tee "$gpu" >/dev/null 2>&1
      fi
    fi
  done
  echo "amd_optimized" >> "$STATE_DIR/gpu_perf_mode"
fi

# NVIDIA GPU optimization
if $HAS_NVIDIA; then
  # nvidia-settings requires X display, may not work on pure Wayland
  if command -v nvidia-settings >/dev/null 2>&1 && [[ -n "${DISPLAY:-}" || -n "${WAYLAND_DISPLAY:-}" ]]; then
    # Set PowerMizer to max performance (mode 1)
    if nvidia-settings -a "[gpu:0]/GpuPowerMizerMode=1" >/dev/null 2>&1; then
      echo "nvidia_optimized" >> "$STATE_DIR/gpu_perf_mode"
    fi
  fi
  # Also try nvidia-smi for persistence mode (doesn't require display)
  if command -v nvidia-smi >/dev/null 2>&1; then
    nvidia-smi -pm 1 >/dev/null 2>&1 || true
  fi
fi

# ===== INTEL GPU OPTIMIZATION (XE DRIVER ONLY) =====
# IMPORTANT: This section ONLY optimizes Intel GPUs using the xe driver (Arc GPUs)
# It IGNORES i915 GPUs (integrated graphics) to prevent conflicts
# DISABLED: xe driver optimization causes visual glitches on Arc B580 with kernel 6.17
# The xe driver power management is not mature enough for forced always-on mode
if $HAS_INTEL; then
  # Check each Intel card to see which driver it uses
  for card_device in /sys/class/drm/card*/device/driver; do
    if [[ -L "$card_device" ]]; then
      # Get the driver name
      driver_name=$(basename "$(readlink -f "$card_device")")

      # Only process xe driver cards
      if [[ "$driver_name" == "xe" ]]; then
        # Extract card name (e.g., card0)
        card_path=$(dirname "$(dirname "$card_device")")
        card_name=$(basename "$card_path")

        echo "# xe driver detected on $card_name - SKIPPED (optimization disabled)" >> "$STATE_DIR/gpu_perf_mode"

        # NOTE: Power management optimization for xe driver is DISABLED
        # Forcing the GPU to always-on mode causes visual glitches on Arc B580
        # with kernel 6.17.x. Let the driver manage power automatically.
        #
        # This may be revisited when xe driver matures in future kernels.

      elif [[ "$driver_name" == "i915" ]]; then
        # Explicitly skip i915 cards
        card_path=$(dirname "$(dirname "$card_device")")
        card_name=$(basename "$card_path")
        echo "# i915 driver detected on $card_name - SKIPPED (not optimized)" >> "$STATE_DIR/gpu_perf_mode"
      fi
    fi
  done
fi

# center_notify "Starting Gamesmode at ${game_width}x${game_height}…"

gamescope_perf=""
[[ "${PERFORMANCE_MODE,,}" == "enabled" ]] && gamescope_perf="--rt --immediate-flips"
steam_args=""
case "${STEAM_LAUNCH_MODE,,}" in
  gamepadui) steam_args="-gamepadui" ;;
  bigpicture|"") steam_args="-tenfoot" ;;
  *) steam_args="-tenfoot" ;;
esac

# Configure MangoHud based on user choice
mangohud_flag=""
mangohud_config=""
case "$MANGOHUD_CHOICE" in
  "Off")
    mangohud_flag=""
    ;;
  "Minimal")
    mangohud_flag="--mangoapp"
    mangohud_config="fps,fps_only,position=top-left,font_size=24"
    ;;
  "Full Stats")
    mangohud_flag="--mangoapp"
    mangohud_config="cpu_temp,gpu_temp,cpu_power,gpu_power,ram,vram,fps,frametime,frame_timing=1,gpu_stats,cpu_stats,position=top-left"
    ;;
esac

# Show launch status
clear
echo ""
gum style --align center --width 70 --border double --padding "1 2" "🎮 Launching Gaming Mode" | center_output 74
echo ""
gum style --align center --width 70 --faint "Resolution: ${game_width}x${game_height}" | center_output 70
gum style --align center --width 70 --faint "Output: ${output_width}x${output_height}" | center_output 70
gum style --align center --width 70 --faint "Refresh: ${REFRESH_RATE}Hz" | center_output 70
gum style --align center --width 70 --faint "MangoHud: ${MANGOHUD_CHOICE}" | center_output 70
echo ""
echo "${pad_str}" | tr -d '\\n'
gum spin --spinner dot --title "Starting gamescope..." -- sleep 2

# Launch gamescope with MangoHud configuration and Gamemode optimizations
# Gamemode adds: process priority, I/O scheduling, and additional system tweaks
if [[ -n "$mangohud_config" ]]; then
  export MANGOHUD_CONFIG="$mangohud_config"
fi
setsid gamemoderun /usr/bin/gamescope $gamescope_perf $mangohud_flag -f -w "$game_width" -h "$game_height" -W "$output_width" -H "$output_height" -r "$REFRESH_RATE" --force-grab-cursor -e -- /usr/bin/steam $steam_args &

# Capture the actual PID of our gamescope instance (not all gamescope processes)
gamescope_pid=$!

# Give gamescope a moment to initialize
sleep 2

# Verify gamescope started successfully
if ! kill -0 "$gamescope_pid" 2>/dev/null; then
  echo "[!] ERROR: Gamescope failed to start!" >&2
  echo "[!] Restoring system state..." >&2
  cleanup_on_error
  exit 1
fi

# Save our specific gamescope PID for cleanup
echo "$gamescope_pid" > "$SESSION_FILE"

exit 0
EOF
  chmod +x "$SWITCH_BIN" || die "cannot chmod $SWITCH_BIN"

  cat > "$RETURN_BIN" <<'EOF'
#!/bin/bash
set -Euo pipefail
STATE_DIR="$HOME/.cache/gaming-session"
LOCK_FILE="$STATE_DIR/idle-prevention.lock"
SESSION_FILE="$STATE_DIR/session.pid"

steam_icon() { echo "steam"; }
center_notify() {
  # TUI notification - brief message on exit (uses terminal theme colors)
  if command -v gum >/dev/null 2>&1; then
    clear
    local term_width=$(tput cols)
    local box_width=50
    local padding=$(( (term_width - box_width) / 2 ))
    [[ $padding -lt 0 ]] && padding=0
    echo ""
    gum style --align center --width 50 --border normal --padding "1 2" "BACK TO WORK" | while IFS= read -r line; do printf "%${padding}s%s\\n" "" "$line"; done
    sleep 1
  else
    echo "BACK TO WORK"
    sleep 1
  fi
}

# First, gracefully terminate Steam to allow it to save state
if pgrep -x steam >/dev/null 2>&1; then
  pkill -TERM steam 2>/dev/null
  # Wait up to 3 seconds for graceful shutdown
  for i in {1..6}; do
    sleep 0.5
    pgrep -x steam >/dev/null 2>&1 || break
  done
  # Force kill if still running
  pkill -9 steam 2>/dev/null || true
fi

# Kill any remaining Steam processes (reaper, fossilize, etc.)
pkill -9 -f "steam" 2>/dev/null || true

# Terminate gamescope (this should also kill Steam if it's still inside)
if [[ -f "$SESSION_FILE" ]]; then
  PID="$(cat "$SESSION_FILE" 2>/dev/null || true)"
  if [[ -n "$PID" ]] && kill -0 "$PID" 2>/dev/null; then
    kill "$PID" 2>/dev/null || true
    # Wait up to 2 seconds for graceful shutdown
    for i in {1..4}; do
      sleep 0.5
      kill -0 "$PID" 2>/dev/null || break
    done
    # Force kill if still running
    kill -9 "$PID" 2>/dev/null || true
  fi
fi

# Gracefully terminate gamescope with proper verification
if pgrep -x gamescope >/dev/null 2>&1; then
  pkill gamescope 2>/dev/null
  # Wait up to 2 seconds for graceful shutdown
  for i in {1..4}; do
    sleep 0.5
    pgrep -x gamescope >/dev/null 2>&1 || break
  done
  # Force kill if still running
  pkill -9 gamescope 2>/dev/null || true
fi

# ===== RESTORE CPU GOVERNOR =====
if [[ -f "$STATE_DIR/original_governors" ]]; then
  while IFS=: read -r cpu_path original_gov; do
    [[ -z "$cpu_path" || -z "$original_gov" || "$original_gov" == "unknown" ]] && continue
    if [[ -f "$cpu_path" ]]; then
      if [[ -w "$cpu_path" ]]; then
        echo "$original_gov" > "$cpu_path" 2>/dev/null || \
          echo "$original_gov" | sudo tee "$cpu_path" >/dev/null 2>&1
      else
        echo "$original_gov" | sudo tee "$cpu_path" >/dev/null 2>&1 || true
      fi
    fi
  done < "$STATE_DIR/original_governors"
  rm -f "$STATE_DIR/original_governors"
fi

# ===== RESTORE GPU PERFORMANCE MODE =====
if [[ -f "$STATE_DIR/gpu_perf_mode" ]]; then
  while IFS=: read -r gpu_path original_mode; do
    # Skip empty or malformed lines
    [[ -z "$gpu_path" || -z "$original_mode" ]] && continue

    # Skip marker lines and comments
    [[ "$original_mode" == "nvidia_optimized" || "$original_mode" == "amd_optimized" || "$original_mode" == "xe_optimized" ]] && continue
    [[ "$gpu_path" == "#"* ]] && continue

    if [[ -f "$gpu_path" ]]; then
      if [[ -w "$gpu_path" ]]; then
        echo "$original_mode" > "$gpu_path" 2>/dev/null || \
          echo "$original_mode" | sudo tee "$gpu_path" >/dev/null 2>&1
      fi
    fi
  done < "$STATE_DIR/gpu_perf_mode"

  # Restore NVIDIA settings if they were changed
  if grep -q "nvidia_optimized" "$STATE_DIR/gpu_perf_mode" 2>/dev/null; then
    if command -v nvidia-settings >/dev/null 2>&1; then
      # Set back to Adaptive mode (0)
      nvidia-settings -a "[gpu:0]/GpuPowerMizerMode=0" >/dev/null 2>&1
    fi
    # Disable persistence mode
    if command -v nvidia-smi >/dev/null 2>&1; then
      nvidia-smi -pm 0 >/dev/null 2>&1 || true
    fi
  fi

  rm -f "$STATE_DIR/gpu_perf_mode"
fi

# ===== RESTART HYPRIDLE =====
# Restart hypridle only if it was running before gaming mode
if [[ -f "$STATE_DIR/hypridle_state" ]]; then
  if [[ "$(cat "$STATE_DIR/hypridle_state" 2>/dev/null)" == "running" ]]; then
    if command -v hypridle >/dev/null 2>&1; then
      # Check if hypridle is not already running
      if ! pgrep -x hypridle >/dev/null 2>&1; then
        nohup hypridle >/dev/null 2>&1 &
        disown
      fi
    fi
  fi
  rm -f "$STATE_DIR/hypridle_state"
fi

rm -f "$LOCK_FILE" "$SESSION_FILE" 2>/dev/null || true
EOF
  chmod +x "$RETURN_BIN" || die "cannot chmod $RETURN_BIN"
}

configure_shortcuts() {
  info "Adding keybindings to: $BINDINGS_CONFIG"

  # Check if bindings already exist
  if grep -q "# Gaming Mode bindings - added by installation script" "$BINDINGS_CONFIG" 2>/dev/null; then
    info "Gaming mode bindings already exist in config, skipping..."
    return 0
  fi

  # Detect the binding style used in the config
  local bind_style="bindd"
  if ! grep -q "^bindd[[:space:]]*=" "$BINDINGS_CONFIG" 2>/dev/null; then
    if grep -q "^bind[[:space:]]*=" "$BINDINGS_CONFIG" 2>/dev/null; then
      bind_style="bind"
    fi
  fi

  # Detect preferred terminal (ghostty preferred, fallback to others)
  local terminal_cmd="ghostty -e"
  local terminal_class="com.mitchellh.ghostty"

  if ! command -v ghostty >/dev/null 2>&1; then
    if command -v kitty >/dev/null 2>&1; then
      terminal_cmd="kitty -e"
      terminal_class="kitty"
    elif command -v alacritty >/dev/null 2>&1; then
      terminal_cmd="alacritty -e"
      terminal_class="Alacritty"
    elif command -v foot >/dev/null 2>&1; then
      terminal_cmd="foot -e"
      terminal_class="foot"
    else
      terminal_cmd="xterm -e"
      terminal_class="XTerm"
    fi
  fi

  info "Using terminal: ${terminal_cmd%% -*} (class: $terminal_class)"

  # Add bindings to the config file (TUI needs terminal with window rules)
  {
    echo ""
    echo "# Gaming Mode bindings - added by installation script"
    echo "windowrulev2 = float, class:($terminal_class)"
    echo "windowrulev2 = size 800 600, class:($terminal_class)"
    echo "windowrulev2 = center, class:($terminal_class)"
    echo "windowrulev2 = pin, class:($terminal_class)"
    if [ "$bind_style" = "bindd" ]; then
      echo "bindd = SUPER SHIFT, S, Steam Gaming Mode, exec, $terminal_cmd $SWITCH_BIN"
      echo "bindd = SUPER SHIFT, R, Exit Gaming Mode, exec, $RETURN_BIN"
    else
      echo "bind = SUPER SHIFT, S, exec, $terminal_cmd $SWITCH_BIN"
      echo "bind = SUPER SHIFT, R, exec, $RETURN_BIN"
    fi
    echo "# End Gaming Mode bindings"
  } >> "$BINDINGS_CONFIG" || die "failed to add bindings to $BINDINGS_CONFIG"

  ADDED_BINDINGS=1

  # Reload Hyprland config
  hyprctl reload >/dev/null 2>&1 || info "Hyprland reload may have failed; relog if binds inactive."
}

check_component() {
  case "$1" in
    launcher)
      [ -x "$SWITCH_BIN" ] && [ -x "$RETURN_BIN" ] || {
        err "launcher check failed"
        return 1
      }
      ;;
    shortcuts)
      if [ ! -f "$BINDINGS_CONFIG" ] || ! grep -q "# Gaming Mode bindings" "$BINDINGS_CONFIG"; then
        err "shortcuts check failed"
        return 1
      fi
      ;;
    capabilities)
      if [[ "${PERFORMANCE_MODE,,}" == "enabled" ]] && command -v gamescope >/dev/null 2>&1; then
        if ! getcap "$(command -v gamescope)" 2>/dev/null | grep -q 'cap_sys_nice'; then
          info "gamescope lacks cap_sys_nice; --rt may be ignored."
        fi
      fi
      ;;
    *)
      err "unknown component: $1"
      return 1
      ;;
  esac
}

validate_deployment() {
  local errors=0
  for component in launcher shortcuts capabilities; do
    check_component "$component" || ((errors++))
  done
  return $errors
}

execute_setup() {
  validate_environment
  info "Found bindings config at: $BINDINGS_CONFIG"

  # Check if this is a first install or re-run
  local is_reinstall=false
  if [ -x "$SWITCH_BIN" ] && [ -x "$RETURN_BIN" ]; then
    is_reinstall=true
  fi

  # Only check dependencies on fresh install or if user requests it
  if [ "$is_reinstall" = false ]; then
    check_steam_dependencies
  else
    info "Gaming mode already installed - skipping dependency check"
    echo ""
    read -p "Run dependency check anyway? [y/N]: " -n 1 -r
    echo
    if [[ $REPLY =~ ^[Yy]$ ]]; then
      check_steam_dependencies
    fi
  fi

  # Handle reinstall option
  if [ -x "$SWITCH_BIN" ] && [ -x "$RETURN_BIN" ]; then
    # Launchers exist - offer fresh install option
    info "Gaming mode launchers found"

    echo ""
    read -p "Gaming mode is already installed. Reinstall? [y/N]: " -n 1 -r
    echo

    if [[ ! $REPLY =~ ^[Yy]$ ]]; then
      info "Installation cancelled"
      exit 0
    fi
  fi

  setup_requirements
  deploy_launchers
  configure_shortcuts
  validate_deployment || die "deployment validation failed"
  echo ""
  info "✓ Install complete!"
  info "  Launch: Super+Shift+S"
  info "  Exit:   Super+Shift+R"
  info ""
  info "Binaries:  $TARGET_DIR"
  info "Bindings:  $BINDINGS_CONFIG"
  info "Config:    $CONFIG_FILE"

  # Check if user needs to log out/reboot for group changes
  if [ "$NEEDS_RELOGIN" -eq 1 ]; then
    echo ""
    echo "════════════════════════════════════════════════════════════════"
    echo "  ⚠️  IMPORTANT: LOG OUT REQUIRED"
    echo "════════════════════════════════════════════════════════════════"
    echo ""
    echo "  User groups have been updated. You MUST log out and log back in"
    echo "  (or reboot) for the changes to take effect."
    echo ""
    echo "  The gaming mode has been installed, but the group permissions"
    echo "  will not be active until you log out and log back in."
    echo ""
    echo "════════════════════════════════════════════════════════════════"
    echo ""
    read -r -p "Press Enter to exit (remember to log out/log back in)..."
  fi
}

gaming_mode::initialize() { validate_environment; setup_requirements; }
gaming_mode::install()    { deploy_launchers; }
gaming_mode::configure()  { configure_shortcuts; validate_deployment || die "validation failed"; }

execute_setup

# Intel Arc (xe driver) Gaming Mode Installer
# - Detects and differentiates Arc (xe) vs integrated (i915) GPUs
# - Applies GSK_RENDERER=gl fix for GTK4 apps on Arc GPUs
# - Installs appropriate drivers for NVIDIA, AMD, Intel Arc, Intel iGPU
