#!/usr/bin/env bash

require() {
  local cmd="$1"
  local pkg="${2:-$1}"

  if ! command -v "$cmd" >/dev/null 2>&1; then
    log_error "Required command '$cmd' not found. Install with: sudo pacman -S $pkg"
    return 1
  fi
}

require_optional() {
  local cmd="$1"
  local pkg="${2:-$1}"

  if ! command -v "$cmd" >/dev/null 2>&1; then
    log_warn "'$cmd' not found. Install with: sudo pacman -S $pkg"
    return 1
  fi
}

have() {
  command -v "$1" >/dev/null 2>&1
}

is_arch() {
  [[ -f /etc/arch-release ]] || [[ -d /etc/pacman.d ]]
}

is_root() {
  [[ "$EUID" -eq 0 ]]
}

OMERON_SUDO_PID=""

OMERON_SUDO_PID=""

sudo_init() {
  if is_root; then
    return 0
  fi
  tui_info "Sudo access needed — enter your password once"
  sudo -v || {
    tui_error "Sudo authentication failed"
    return 1
  }
  (
    while true; do
      sleep 240
      sudo -v 2>/dev/null || break
    done
  ) &
  OMERON_SUDO_PID=$!
}

sudo_cleanup() {
  [[ -n "$OMERON_SUDO_PID" ]] && kill "$OMERON_SUDO_PID" 2>/dev/null || true
}

sudo_run() {
  if is_root; then
    "$@"
    return
  fi
  if [[ -n "${OMERON_SUDO_PID:-}" ]] && kill -0 "$OMERON_SUDO_PID" 2>/dev/null; then
    sudo -n "$@"
  else
    sudo "$@"
  fi
}

backup_file() {
  local target="$1"
  local backup_dir="${2:-$HOME/.dotfiles-backup/$(date +%Y%m%d-%H%M%S)}"
  local relative="${target#"$HOME"/}"
  local backup="$backup_dir/$relative"

  [[ -e "$target" || -L "$target" ]] || return 0

  mkdir -p "$(dirname "$backup")"
  cp -a "$target" "$backup"
  log_info "Backed up $target -> $backup"
  printf '%s' "$backup_dir"
}

symlink_path() {
  local source="$1"
  local target="$2"

  backup_file "$target"
  rm -rf "$target"
  mkdir -p "$(dirname "$target")"
  ln -sfn "$source" "$target"
  log_info "Linked $source -> $target"
}

copy_path() {
  local source="$1"
  local target="$2"

  backup_file "$target"
  rm -rf "$target"
  mkdir -p "$(dirname "$target")"
  cp -a "$source" "$target"
  log_info "Copied $source -> $target"
}

platform_packages() {
  if is_arch; then
    printf '%s\n' "arch"
  fi
  if [[ -f /etc/os-release ]]; then
    local id
    id="$(grep -oP '^ID=\K.*' /etc/os-release)"
    printf '%s\n' "$id"
  fi
}

is_package_installed() {
  local pkg="$1"

  if command -v pacman >/dev/null 2>&1; then
    pacman -Qi "$pkg" >/dev/null 2>&1 && return 0
    if command -v expac >/dev/null 2>&1; then
      expac -Q '%n %P' 2>/dev/null | awk -v pkg="$pkg" '
        { for (i=2; i<=NF; i++) if ($i == pkg) {found=1; exit} }
        END {exit !found}
      ' && return 0
    fi
    return 1
  fi

  return 1
}

install_pacman() {
  local packages=("$@")
  local to_install=()
  local pkg

  for pkg in "${packages[@]}"; do
    if ! pacman -Si "$pkg" >/dev/null 2>&1; then
      log_warn "Package '$pkg' not found in pacman repositories"
      continue
    fi
    if ! is_package_installed "$pkg"; then
      to_install+=("$pkg")
    fi
  done

  if ((${#to_install[@]})); then
    log_info "Installing: ${to_install[*]}"
    sudo_run pacman -S --needed --noconfirm "${to_install[@]}"
  else
    log_info "All packages already installed"
  fi
}

replace_home_paths() {
  local dir="$1"
  local original_home="${2:-/home/pascal}"

  if [[ "$original_home" == "$HOME" ]]; then
    return 0
  fi

  find "$dir" -type f -exec sed -i "s#${original_home}#${HOME}#g" {} + 2>/dev/null || true
  log_info "Rewrote home paths in $dir"
}

detect_gpu() {
  if ! command -v lspci >/dev/null 2>&1; then
    if have pacman; then
      sudo_run pacman -S --needed --noconfirm pciutils >/dev/null 2>&1 || true
    fi
  fi

  local gpu_info
  gpu_info="$(lspci -nn 2>/dev/null | grep -E '\[0300\]|\[0302\]|\[0380\]' || true)"
  [[ -z "$gpu_info" ]] && gpu_info="$(lspci -nn 2>/dev/null | grep -iE '(VGA|3D|Display).*controller' || true)"

  if printf '%s' "$gpu_info" | grep -qi "\[10de:"; then
    printf 'nvidia'
  elif printf '%s' "$gpu_info" | grep -qi "\[1002:\|\[1022:"; then
    printf 'amd'
  elif printf '%s' "$gpu_info" | grep -qi "\[8086:"; then
    printf 'intel'
  elif printf '%s' "$gpu_info" | grep -qi "vmware\|qemu\|virtualbox\|virtio"; then
    printf 'vm'
  elif printf '%s' "$gpu_info" | grep -qi "nvidia"; then
    printf 'nvidia'
  elif printf '%s' "$gpu_info" | grep -qi "amd\|advanced micro devices"; then
    printf 'amd'
  elif printf '%s' "$gpu_info" | grep -qi "intel"; then
    printf 'intel'
  else
    printf 'unknown'
  fi
}

gpu_packages() {
  local gpu_type
  gpu_type="$(detect_gpu)"

  case "$gpu_type" in
    intel)
      printf '%s\n' "xf86-video-intel" "vulkan-intel" "intel-media-driver" "libva-intel-driver"
      ;;
    amd)
      printf '%s\n' "xf86-video-amdgpu" "vulkan-radeon" "libva-mesa-driver" "mesa-vdpau"
      ;;
    nvidia)
      printf '%s\n' "nvidia-dkms" "nvidia-utils" "nvidia-settings" "libva-nvidia-driver" "vulkan-tools"
      ;;
    vm)
      printf '%s\n' "xf86-video-vmware" "mesa" "vulkan-swrast"
      ;;
    *)
      printf '%s\n' "mesa" "vulkan-swrast"
      ;;
  esac
}

is_fresh_install() {
  have hyprctl && return 1

  if have hyprland; then
    hyprland --version >/dev/null 2>&1 && return 1
  fi

  if [[ -n "${WAYLAND_DISPLAY:-}" || -n "${DISPLAY:-}" ]]; then
    return 1
  fi

  return 0
}

count_missing_packages() {
  local packages=("$@")
  local missing=0
  local pkg

  for pkg in "${packages[@]}"; do
    if ! is_package_installed "$pkg"; then
      ((missing++))
    fi
  done

  printf '%d' "$missing"
}

system_summary() {
  local gpu
  gpu="$(detect_gpu)"

  cat <<SUMMARY
┌─────────────────────────────────────────────┐
│ System Summary                               │
├─────────────────────────────────────────────┤
│ OS:      $(grep -oP '^PRETTY_NAME="?\K[^"\n]+' /etc/os-release 2>/dev/null | sed 's/"$//' || echo "Arch Linux")
│ Kernel:  $(uname -r)
│ GPU:     ${gpu} ($(lspci -nn 2>/dev/null | grep -E '\[0300\]|\[0302\]|\[0380\]' | sed 's/.*: //' | head -1 || echo "unknown"))
│ Session: $(printenv XDG_SESSION_TYPE || echo "none (TTY)")
│ Hyprland: $(have hyprctl && echo "installed" || echo "NOT installed")
│ AUR:     $(have paru && echo "paru" || (have yay && echo "yay" || echo "none"))
└─────────────────────────────────────────────┘
SUMMARY
}

install_aur_package() {
  local pkgname="$1"
  local build_dir
  build_dir="$(mktemp -d)"

  tui_info "Cloning $pkgname from AUR directly..."
  if ! git clone "https://aur.archlinux.org/$pkgname.git" "$build_dir/$pkgname" 2>/dev/null; then
    rm -rf "$build_dir"
    return 1
  fi

  tui_info "Building $pkgname..."
  if (cd "$build_dir/$pkgname" && makepkg -si --needed --noconfirm); then
    rm -rf "$build_dir"
    return 0
  fi

  local rc=$?
  rm -rf "$build_dir"
  return $rc
}

install_aur_helper() {
  if have paru || have yay; then
    return 0
  fi

  if is_root; then
    tui_warn "Running as root — makepkg refuses to run as root."
    tui_info "Switch to a normal user with sudo access and re-run."
    return 1
  fi

  command -v git >/dev/null 2>&1 || sudo_run pacman -S --needed --noconfirm git
  sudo_run pacman -S --needed --noconfirm base-devel

  local build_dir
  build_dir="$(mktemp -d)"

  tui_info "Installing yay-bin (statically linked, works on any libalpm)..."
  if git clone https://aur.archlinux.org/yay-bin.git "$build_dir/yay-bin" &&
     (cd "$build_dir/yay-bin" && makepkg -si --needed --noconfirm); then
    tui_success "yay installed"
    rm -rf "$build_dir"
    return 0
  fi

  rm -rf "$build_dir"
  mkdir -p "$build_dir"

  tui_info "yay-bin failed. Trying paru-bin..."
  if git clone https://aur.archlinux.org/paru-bin.git "$build_dir/paru-bin" &&
     (cd "$build_dir/paru-bin" && makepkg -si --needed --noconfirm) &&
     paru --version >/dev/null 2>&1; then
    tui_success "paru works"
    rm -rf "$build_dir"
    return 0
  fi

  rm -rf "$build_dir"
  tui_warn "No working AUR helper. Using direct git clone + makepkg for AUR packages."
  return 0
}

install_aur() {
  local packages=("$@")
  local pkg
  local rc=0

  for pkg in "${packages[@]}"; do
    if is_package_installed "$pkg"; then
      continue
    fi

    if have yay; then
      tui_info "Installing $pkg from AUR (via yay)..."
      if yay -S --needed --noconfirm "$pkg"; then
        tui_success "$pkg installed"
        continue
      fi
      tui_warn "yay failed for $pkg. Trying direct AUR install..."
    elif have paru && paru --version >/dev/null 2>&1; then
      tui_info "Installing $pkg from AUR (via paru)..."
      if paru -S --needed --noconfirm "$pkg"; then
        tui_success "$pkg installed"
        continue
      fi
      tui_warn "paru failed for $pkg. Trying direct AUR install..."
    fi

    if install_aur_package "$pkg"; then
      tui_success "$pkg installed"
    else
      tui_warn "$pkg could not be installed. Try manually:"
      tui_info "  cd /tmp && git clone https://aur.archlinux.org/$pkg.git"
      tui_info "  cd $pkg && makepkg -si"
      rc=1
    fi
  done

  return $rc
}
