#!/usr/bin/env bash

# ANSI color codes
RED='\033[0;31m'
CYAN='\033[0;36m'
YELLOW='\033[0;33m'
LIGHT_GREEN='\033[0;92m'
BOLD='\033[1m'
NC='\033[0m' # No Color

echo_error() {
  printf "${BOLD}${RED}ERROR: ${NC}${RED}%s${NC}\n" "$1" >&2
}

echo_info() {
  printf "${BOLD}${CYAN}INFO: ${NC}${CYAN}%s${NC}\n" "$1"
}

echo_warning() {
  printf "${BOLD}${YELLOW}WARNING: ${NC}${YELLOW}%s${NC}\n" "$1"
}

echo_note() {
  printf "${BOLD}${LIGHT_GREEN}NOTE: ${NC}${LIGHT_GREEN}%s${NC}\n" "$1"
}

# ─< Check if the given command exists silently >─────────────────────────────────────────
command_exists() {
  command -v "$@" >/dev/null 2>&1
}

# ─< Check if the user is root and set sudo variable if necessary >───────────────────────
check_root() {
  if ((EUID != 0)); then
    if command_exists sudo; then
      echo_info "User is not root. Using sudo for privileged operations."
      _sudo="sudo"
    else
      echo_error "No sudo found and you're not root! Can't install packages."
      return 1
    fi
  else
    echo_info "Root access confirmed."
    _sudo=""
  fi
}

# ─< Distribution detection and installation >────────────────────────────────────────
get_packager() {
  pkger=(
    "apt"
    "pacman"
    "dnf"
    "apk"
    "zypper"
  )

  for pkger in "${pkger[@]}"; do
    if command_exists "$pkger"; then
      echo_info "Found package manager: $pkger"
      case "$pkger" in
      "apt")
        $_sudo apt-get update
        _install() { $_sudo apt-get install --assume-yes "$@"; }
        ;;
      "pacman")
        $_sudo pacman -Syy
        _install() { $_sudo pacman -S --noconfirm "$@"; }
        ;;
      "dnf")
        $_sudo dnf update
        _install() { $_sudo dnf install -y "$@"; }
        ;;
      "apk")
        _install() { $_sudo apk add "$@"; }
        ;;
      "zypper")
        $_sudo zypper ref
        _install() { $_sudo zypper in -y "$@"; }
        ;;
      esac
    fi
  done
}

silentexec() {
  "$@" >/dev/null 2>&1
}

__pre_stow__() {
  echo_note "__pre_stow__"
  conf="$HOME/.config"
  bak_dir="$HOME/.bak"
  dirs=(
    "btop"
    "gBar"
    "yazi"
    "fastfetch"
    "hypr"
    "kitty"
    "neovide"
    "rofi"
    "waybar"
    "wlogout"
    "wob"
  )

  if [ ! -d "$bak_dir" ]; then
    echo_info "backup dir created at $bak_dir" &&
      silentexec mkdir "$bak_dir"
  else
    echo_info "Backup dir already present, clearing now" &&
      rm -rf "${bak_dir:?}/*"
  fi

  for _dirs in "${dirs[@]}"; do
    if [ -d "$conf/$_dirs" ]; then
      mv -f "$conf/$_dirs" "$bak_dir"
    fi
  done

  h_files=(
    ".zshrc"
    ".zshenv"
    ".tmux.conf"
    ".wezterm.lua"
  )

  h_dirs=(
    ".tmux"
    ".zsh"
  )

  for _f in "${h_files[@]}"; do
    if [ -f "$HOME/$_f" ]; then
      mv -f "$HOME/$_f" "$bak_dir" && echo_info "Moved $_f to $bak_dir"
    fi
  done

  for _d in "${h_dirs[@]}"; do
    if [ -d "$HOME/$_d" ]; then
      mv -f "$HOME/$_d" "$bak_dir" && echo_info "Moved $_d to $bak_dir"
    fi
  done

  if [ -d "$HOME/.local/share/fastfetch/" ]; then
    mv -f "$HOME/.local/share/fastfetch" "$bak_dir"
  fi
}

askThings() {
  echo_info "Choose a menu - [r]ofi || [t]ofi"
  read -r askMenu </dev/tty

  echo_info "Choose a cli filemanager - [y]azi || [r]anger || [l]f"
  read -r askFilemgr </dev/tty

  echo_info "Choose a bar provider - [w]aybar || [g]Bar || [h]yprpanel"
  read -r askBar </dev/tty

  echo_info "Choose a Terminal config (.)[G]hostty, [K]itty, [A]lacritty(.)"
  read -r askTerminal </dev/tty

  echo_info "Do you also want to install optional packages? (y/n)"
  read -r askOptional </dev/tty

  if [ ! -d "$HOME/.config/nvim" ]; then
    echo_info "Do you also want to install a neovim config? [m]inimal || [s]tandard || [n]o"
    read -r askNvim </dev/tty
  fi

  case "$askOptional" in
  [yY]) __optional__="true" ;;
  [nN]) __optional__="false" ;;
  esac
}

ask_Neovide(){
  echo_info "Do you also want to install a neovide config? [y/N]"
  read -r askNeovide </dev/tty

  case "$askNeovide" in
    [yY])
      cloneDots "neovide" ;;
  esac
}

cloneDots() {
  choise="$1"
  cloneName="${2:-$1}"

  if command_exists git; then
    [ -d ./dotfiles ] &&
      [ ! -d "./dotfiles/${choise}" ] &&
      git clone --depth=1 "https://git.k4li.de/dotfiles/${choise}.git" "./dotfiles/.config/${cloneName}"

  else
    echo_error "Git was not found"
  fi
}

__validate__() {
  if askThings; then
    case "$askMenu" in
    [rR] | rofi) cloneDots "rofi" ;;
    [tT] | tofi) cloneDots "tofi" ;;
    esac

    case "$askFilemgr" in
    [yY] | yazi) cloneDots "yazi" ;;
    [rR] | ranger) cloneDots "ranger" ;;
    [lL] | lf) cloneDots "lf" ;;
    esac

    case "$askBar" in
    [wW] | waybar) cloneDots "waybar" ;;
    [gG] | gBar | gbar) cloneDots "gBar" ;;
    [hH] | hyprpanel) cloneDots "hyprpanel" ;;
    esac

    case "$askTerminal" in
    [gG] | ghostty) cloneDots "ghostty" ;;
    [kK] | kitty) cloneDots "kitty" ;;
    [aA] | alacritty) cloneDots "alacritty" ;;
    esac

    case "$askNvim" in
    [mM] | minimal) cloneDots "nvim-mini" "nvim" && ask_Neovide ;;
    [sS] | standard) cloneDots "nvim" && ask_Neovide ;;
    [nN] | no) return 0 ;;
    esac

  else
    echo_error "Something went terribly wrong"
    exit 1
  fi
}

__dep__() {
  _depss=(
    "stow"
    "btop"
    "entr"
    "unzip"
    "zip"
    "fzf"
    "tmux"
    "copyq"
    "rsync"
    "wezterm"
    "wlogout"
    "zoxide"
  )

  for hyprdots_dependency in "${_depss[@]}"; do
    if ! command_exists "$hyprdots_dependency"; then
      echo_note "--- installing $hyprdots_dependency ---"
      _install "$hyprdots_dependency"
    else
      echo_info "$hyprdots_dependency is already installed"
    fi
  done
}

__monitors__() {
  if [ ! -e "$HOME/.monitors.conf" ]; then
    res="$(hyprctl monitors | grep -oP '\d+x\d+@\d+\.\d+' | head -n 1)"
    touch "$HOME/.monitors.conf"
    echo "monitor = eDP-1, ${res}, 0x0, 1" >"$HOME/.monitors.conf"
  fi
}

pkg_optional() {
  _ops=(
    "cowsay"
    "cmatrix"
    "trash-cli"
  )
  case "$_ops" in
  Y | y)
    for _o_ in "${_ops[@]}"; do
      if command_exists "$_o_"; then
        echo_note "$_o_ - is already installed"
      else
        echo_info "Installing $_o_"
        _install "$_o_"
      fi
    done
    ;;
  *)
    echo default
    ;;
  esac
}

__stow__() {
  stow --verbose --target="$HOME" --defer=.gitmodules --restow */
}

main() {
  check_root
  get_packager

  __validate__
  __dep__

  if ! command_exists stow; then
    echo_error "we couldn't find stow on the machine, do you want us to install it? (y/n): "
    read -r ask_stow
    case "$ask_stow" in
    Y | y)
      _install stow
      ;;
    *)
      echo_error "You cannot proceed without installing stow! Please install manually"
      exit 1
      ;;
    esac
  else
    echo_info "stow was found, going on to prepare to stow your config"
    sleep 0.3
  fi

  __pre_stow__
  __stow__

  sleep 2

  [ "$__optional__" = "true" ] &&
    pkg_optional

  __monitors__
  echo_note "found resolution ${res}"
}

main
