#!/usr/bin/env bash
# SPDX-License-Identifier: GPL-3.0-only
set -euo pipefail

action="${1:-}"

log() { echo "[alma-creative-installer-helper] $*"; }

# -------------------------------------------------
# Repo enable actions (privileged)
# -------------------------------------------------
enable_epel() {
  log "Enabling EPEL..."
  dnf -y install epel-release
  log "Done."
}

enable_crb() {
  log "Enabling CRB / PowerTools..."
  if dnf -y config-manager --set-enabled crb >/dev/null 2>&1; then
    log "Enabled: crb"
  elif dnf -y config-manager --set-enabled powertools >/dev/null 2>&1; then
    log "Enabled: powertools"
  else
    echo "ERROR: Could not enable CRB/powertools automatically." >&2
    exit 4
  fi
  log "Done."
}

repo_status() {
  log "Enabled repos:"
  dnf repolist --enabled
}

# -------------------------------------------------
# DNF packages
# -------------------------------------------------
install_pkg() {
  local pkg="${1:-}"
  [[ -n "${pkg}" ]] || { echo "ERROR: missing package name" >&2; exit 2; }
  log "Installing: ${pkg}"
  dnf -y install "${pkg}"
  log "Done."
}

install_pkg_version() {
  local pkg_expr="${1:-}"
  [[ -n "${pkg_expr}" ]] || { echo "ERROR: missing package/version expression" >&2; exit 2; }
  log "Installing specific package version: ${pkg_expr}"
  dnf -y install "${pkg_expr}"
  log "Done."
}

remove_pkg() {
  local pkg="${1:-}"
  [[ -n "${pkg}" ]] || { echo "ERROR: missing package name" >&2; exit 2; }
  log "Removing: ${pkg}"
  dnf -y remove "${pkg}"
  log "Done."
}

pkg_status() {
  local pkg="${1:-}"
  [[ -n "${pkg}" ]] || { echo "ERROR: missing package name" >&2; exit 2; }
  if rpm -q "${pkg}" >/dev/null 2>&1; then
    log "Installed: ${pkg}"
    rpm -q "${pkg}"
  else
    log "Not installed: ${pkg}"
    exit 3
  fi
}

# -------------------------------------------------
# Flatpak / Krita support (system-wide)
# -------------------------------------------------
require_invoking_user() {
  if [[ -z "${PKEXEC_UID:-}" ]]; then
    echo "ERROR: PKEXEC_UID missing; cannot determine invoking user." >&2
    exit 6
  fi
  user="$(getent passwd "${PKEXEC_UID}" | cut -d: -f1 || true)"
  if [[ -z "${user}" ]]; then
    echo "ERROR: could not resolve invoking user for PKEXEC_UID=${PKEXEC_UID}" >&2
    exit 6
  fi
  echo "${user}"
}

require_invoking_user_home() {
  local user
  user="$(require_invoking_user)"
  local home
  home="$(getent passwd "${user}" | cut -d: -f6 || true)"
  if [[ -z "${home}" ]]; then
    echo "ERROR: could not resolve home directory for user ${user}" >&2
    exit 6
  fi
  echo "${home}"
}

run_flatpak_user() {
  local user home
  user="$(require_invoking_user)"
  home="$(require_invoking_user_home)"
  runuser -u "${user}" -- env HOME="${home}" flatpak --user "$@"
}

ensure_flatpak_flathub() {
  log "Ensuring Flatpak is installed..."
  dnf -y install flatpak

  log "Ensuring Flathub remote exists (system)..."
  flatpak remote-add --if-not-exists --system flathub https://flathub.org/repo/flathub.flatpakrepo

  log "Flatpak + Flathub ready."
}

ensure_flatpak_flathub_user() {
  log "Ensuring Flatpak is installed..."
  dnf -y install flatpak

  log "Ensuring Flathub remote exists (user)..."
  run_flatpak_user remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo

  log "Flatpak + Flathub ready (user)."
}

install_flatpak_app() {
  local appid="${1:-}"
  [[ -n "${appid}" ]] || { echo "ERROR: missing flatpak app id" >&2; exit 2; }
  ensure_flatpak_flathub
  log "Installing Flatpak app: ${appid}"
  flatpak install -y --system flathub "${appid}"
  log "Done."
}

install_flatpak_app_branch() {
  local appid="${1:-}"
  local branch="${2:-stable}"
  [[ -n "${appid}" ]] || { echo "ERROR: missing flatpak app id" >&2; exit 2; }
  ensure_flatpak_flathub
  log "Installing Flatpak app: ${appid} (branch: ${branch})"
  flatpak install -y --system flathub "${appid}//${branch}"
  log "Done."
}

install_flatpak_app_commit() {
  local appid="${1:-}"
  local branch="${2:-stable}"
  local commit="${3:-}"
  [[ -n "${appid}" ]] || { echo "ERROR: missing flatpak app id" >&2; exit 2; }
  [[ -n "${commit}" ]] || { echo "ERROR: missing flatpak commit" >&2; exit 2; }
  ensure_flatpak_flathub
  log "Installing Flatpak app: ${appid} (branch: ${branch}, commit: ${commit})"
  flatpak install -y --system flathub "${appid}//${branch}"
  flatpak update -y --system --commit="${commit}" "${appid}"
  log "Done."
}

install_flatpak_app_user() {
  local appid="${1:-}"
  [[ -n "${appid}" ]] || { echo "ERROR: missing flatpak app id" >&2; exit 2; }
  ensure_flatpak_flathub_user
  log "Installing Flatpak app (user): ${appid}"
  run_flatpak_user install -y flathub "${appid}"
  log "Done."
}

install_flatpak_app_user_branch() {
  local appid="${1:-}"
  local branch="${2:-stable}"
  [[ -n "${appid}" ]] || { echo "ERROR: missing flatpak app id" >&2; exit 2; }
  ensure_flatpak_flathub_user
  log "Installing Flatpak app (user): ${appid} (branch: ${branch})"
  run_flatpak_user install -y flathub "${appid}//${branch}"
  log "Done."
}

install_flatpak_app_user_commit() {
  local appid="${1:-}"
  local branch="${2:-stable}"
  local commit="${3:-}"
  [[ -n "${appid}" ]] || { echo "ERROR: missing flatpak app id" >&2; exit 2; }
  [[ -n "${commit}" ]] || { echo "ERROR: missing flatpak commit" >&2; exit 2; }
  ensure_flatpak_flathub_user
  log "Installing Flatpak app (user): ${appid} (branch: ${branch}, commit: ${commit})"
  run_flatpak_user install -y flathub "${appid}//${branch}"
  run_flatpak_user update -y --commit="${commit}" "${appid}"
  log "Done."
}

remove_flatpak_app() {
  local appid="${1:-}"
  [[ -n "${appid}" ]] || { echo "ERROR: missing flatpak app id" >&2; exit 2; }
  log "Removing Flatpak app: ${appid}"
  flatpak uninstall -y --system "${appid}"
  log "Done."
}

remove_flatpak_app_user() {
  local appid="${1:-}"
  [[ -n "${appid}" ]] || { echo "ERROR: missing flatpak app id" >&2; exit 2; }
  log "Removing Flatpak app (user): ${appid}"
  run_flatpak_user uninstall -y "${appid}"
  log "Done."
}

# -------------------------------------------------
# DaVinci Resolve
# -------------------------------------------------
prepare_resolve_deps() {
  log "Installing DaVinci Resolve dependencies (baseline set)..."
  dnf -y install \
    alsa-lib pulseaudio-libs \
    libxcrypt-compat \
    libX11 libXcursor libXext libXfixes libXi libXinerama libXrandr libXrender libXtst \
    libxcb xcb-util xcb-util-image xcb-util-keysyms xcb-util-renderutil xcb-util-wm \
    libxkbcommon libxkbcommon-x11 \
    mesa-libGLU fontconfig freetype \
    libcurl --allowerasing \
    || exit 1
  log "Dependencies installed."
}

set_selinux_mode() {
  local mode="${1:-}"
  [[ -n "${mode}" ]] || { echo "ERROR: missing selinux mode" >&2; exit 2; }

  case "${mode}" in
    permissive-temp)
      log "Setting SELinux to permissive (temporary)..."
      if command -v setenforce >/dev/null 2>&1; then
        setenforce 0 || true
      fi
      ;;
    permissive)
      log "Setting SELinux to permissive (permanent)..."
      sed -i 's/^SELINUX=.*/SELINUX=permissive/' /etc/selinux/config
      if command -v setenforce >/dev/null 2>&1; then
        setenforce 0 || true
      fi
      ;;
    disabled)
      log "Setting SELinux to disabled (permanent)..."
      sed -i 's/^SELINUX=.*/SELINUX=disabled/' /etc/selinux/config
      if command -v setenforce >/dev/null 2>&1; then
        setenforce 0 || true
      fi
      ;;
    enforcing)
      log "Setting SELinux to enforcing (permanent)..."
      sed -i 's/^SELINUX=.*/SELINUX=enforcing/' /etc/selinux/config
      if command -v setenforce >/dev/null 2>&1; then
        setenforce 1 || true
      fi
      ;;
    *)
      echo "ERROR: unknown selinux mode: ${mode}" >&2
      exit 2
      ;;
  esac

  log "SELinux change requested. A reboot may be required to fully apply."
}

install_local_file() {
  local path="${1:-}"
  if [[ -z "${path}" || ! -f "${path}" ]]; then
    echo "ERROR: installer path missing or not found." >&2
    exit 2
  fi

  case "${path}" in
    *.rpm)
      log "Installing local RPM via dnf: ${path}"
      dnf -y install "${path}"
      log "Done."
      ;;
    *.run)
      log "Running local .run installer: ${path}"
      chmod +x "${path}"
      if [[ "$(id -u)" -eq 0 ]]; then
        if [[ -n "${PKEXEC_UID:-}" ]]; then
          user="$(getent passwd "${PKEXEC_UID}" | cut -d: -f1 || true)"
          if [[ -z "${user}" ]]; then
            echo "ERROR: could not resolve invoking user for PKEXEC_UID=${PKEXEC_UID}" >&2
            exit 6
          fi
          log "Dropping privileges to run installer as ${user} (uid ${PKEXEC_UID})"
          runuser -u "${user}" -p -- env SKIP_PACKAGE_CHECK=1 "${path}"
        else
          echo "ERROR: .run installers must be run as a normal user (not root)." >&2
          exit 6
        fi
      else
        SKIP_PACKAGE_CHECK=1 "${path}"
      fi
      log "Installer finished (check output above)."
      ;;
    *)
      echo "ERROR: unsupported file type. Use .rpm or .run" >&2
      exit 5
      ;;
  esac
}

# -------------------------------------------------
# Dispatcher
# -------------------------------------------------
case "${action}" in
  # Repo
  enable_crb)          enable_crb;;
  enable_epel)         enable_epel;;
  repo_status)         repo_status;;

  # DNF apps
  install_pkg)         install_pkg "${2:-}";;
  install_pkg_version) install_pkg_version "${2:-}";;
  remove_pkg)          remove_pkg "${2:-}";;
  pkg_status)          pkg_status "${2:-}";;

  # Flatpak
  ensure_flatpak_flathub) ensure_flatpak_flathub;;
  install_flatpak_app)    install_flatpak_app "${2:-}";;
  install_flatpak_app_branch) install_flatpak_app_branch "${2:-}" "${3:-stable}";;
  install_flatpak_app_commit) install_flatpak_app_commit "${2:-}" "${3:-stable}" "${4:-}";;
  install_flatpak_app_user) install_flatpak_app_user "${2:-}";;
  install_flatpak_app_user_branch) install_flatpak_app_user_branch "${2:-}" "${3:-stable}";;
  install_flatpak_app_user_commit) install_flatpak_app_user_commit "${2:-}" "${3:-stable}" "${4:-}";;
  remove_flatpak_app)     remove_flatpak_app "${2:-}";;
  remove_flatpak_app_user) remove_flatpak_app_user "${2:-}";;

  # Resolve
  prepare_resolve_deps)  prepare_resolve_deps;;
  set_selinux_mode)      set_selinux_mode "${2:-}";;
  install_local_file)    install_local_file "${2:-}";;

  *)
    cat >&2 <<'EOF'
Usage: almalinux-creative-installer-helper <action>

Repo actions:
  enable_crb
  enable_epel
  repo_status

DNF apps:
  install_pkg <name>
  install_pkg_version <name-version-release>
  remove_pkg <name>
  pkg_status <name>

Flatpak:
  ensure_flatpak_flathub
  install_flatpak_app <appid>
  install_flatpak_app_branch <appid> <branch>
  install_flatpak_app_commit <appid> <branch> <commit>
  install_flatpak_app_user <appid>
  install_flatpak_app_user_branch <appid> <branch>
  install_flatpak_app_user_commit <appid> <branch> <commit>
  remove_flatpak_app <appid>
  remove_flatpak_app_user <appid>

Local installers:
  prepare_resolve_deps
  set_selinux_mode <permissive-temp|permissive|disabled|enforcing>
  install_local_file <path_to_.rpm_or_.run>
EOF
    exit 1
    ;;
esac
