#!/bin/bash
# Fedora Setup Script - Replicates Arch dwm/zsh/nvim environment
# Run as your regular user (uses sudo when needed)

set -e

LOGFILE="$HOME/fedora-setup.log"
exec > >(tee -a "$LOGFILE") 2>&1

echo "Starting Fedora setup at $(date)"

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

info() { echo -e "${GREEN}[INFO]${NC} $1"; }
warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
error() { echo -e "${RED}[ERROR]${NC} $1"; exit 1; }

# Check if running as root
if [ "$EUID" -eq 0 ]; then
    error "Do not run this script as root. Run as your regular user."
fi

# Confirm before proceeding
echo "This script will install dwm, st, dmenu, neovim, zsh, and related tools."
echo "It will also configure your shell and window manager."
read -p "Continue? [y/N] " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
    exit 0
fi

# ============================================================================
# PHASE 1: Enable RPM Fusion and update system
# ============================================================================
info "Enabling RPM Fusion repositories..."
sudo dnf install -y \
    https://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm \
    https://download1.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$(rpm -E %fedora).noarch.rpm || true

info "Updating system..."
sudo dnf update -y

# ============================================================================
# PHASE 2: Install packages
# ============================================================================
info "Installing core packages..."

# Development tools needed for building suckless software
DEVEL_PKGS="
    @development-tools
    libX11-devel
    libXft-devel
    libXinerama-devel
    freetype-devel
    fontconfig-devel
    harfbuzz-devel
    imlib2-devel
    libXrender-devel
"

# Terminal and shell
TERMINAL_PKGS="
    zsh
    alacritty
    tmux
"

# Editors and dev tools
DEV_PKGS="
    neovim
    git
    fzf
    ripgrep
    fd-find
    bat
    htop
    curl
    wget
    unzip
    rsync
    man-db
    man-pages
"

# X11 and window manager dependencies
X11_PKGS="
    xorg-x11-server-Xorg
    xorg-x11-xinit
    xorg-x11-xauth
    xorg-x11-drv-libinput
    xclip
    xdotool
    xprop
    xset
    xrandr
    autorandr
    picom
    dunst
    unclutter
    feh
    maim
    xwallpaper
    redshift
    light
"

# Fonts
FONT_PKGS="
    jetbrains-mono-fonts
    jetbrains-mono-nl-fonts
    google-noto-emoji-fonts
    google-noto-sans-cjk-fonts
    fontawesome-fonts
    dejavu-fonts-all
"

# Multimedia and utilities
UTIL_PKGS="
    pipewire
    pipewire-pulseaudio
    wireplumber
    mpd
    mpc
    mpv
    yt-dlp
    ffmpeg
    imagemagick
    zathura
    zathura-pdf-mupdf
    keepassxc
    firefox
"

# Container and cloud tools
CLOUD_PKGS="
    podman
    buildah
    skopeo
    kubectl
    helm
"

# Additional tools for scripts
EXTRA_PKGS="
    jq
    arandr
    tesseract
    psmisc
    slop
    nsxiv
"

sudo dnf install -y $DEVEL_PKGS $TERMINAL_PKGS $DEV_PKGS $X11_PKGS $FONT_PKGS $UTIL_PKGS $CLOUD_PKGS $EXTRA_PKGS

# Install Nerd Fonts (JetBrainsMono)
info "Installing JetBrainsMono Nerd Font..."
mkdir -p ~/.local/share/fonts
cd /tmp
if [ ! -f ~/.local/share/fonts/JetBrainsMonoNerdFont-Regular.ttf ]; then
    wget -q https://github.com/ryanoasis/nerd-fonts/releases/download/v3.1.1/JetBrainsMono.zip
    unzip -o JetBrainsMono.zip -d ~/.local/share/fonts/
    fc-cache -fv
fi

# ============================================================================
# PHASE 3: Build suckless software from source
# ============================================================================
info "Setting up suckless software..."

mkdir -p ~/.local/src

# dwm
info "Building dwm..."
cd ~/.local/src
if [ ! -d dwm ]; then
    git clone https://github.com/LukeSmithxyz/dwm.git
fi
cd dwm
sudo make clean install

# st (simple terminal)
info "Building st..."
cd ~/.local/src
if [ ! -d st ]; then
    git clone https://github.com/LukeSmithxyz/st.git
fi
cd st
sudo make clean install

# dmenu
info "Building dmenu..."
cd ~/.local/src
if [ ! -d dmenu ]; then
    git clone https://github.com/LukeSmithxyz/dmenu.git
fi
cd dmenu
sudo make clean install

# dwmblocks
info "Building dwmblocks..."
cd ~/.local/src
if [ ! -d dwmblocks ]; then
    git clone https://github.com/LukeSmithxyz/dwmblocks.git
fi
cd dwmblocks
sudo make clean install

# slock (screen locker)
info "Building slock..."
cd ~/.local/src
if [ ! -d slock ]; then
    git clone https://git.suckless.org/slock
fi
cd slock
sudo make clean install

# Apply custom dwmblocks config
info "Configuring dwmblocks with custom blocks..."
cat > ~/.local/src/dwmblocks/config.h << 'EOF'
//Modify this file to change what commands output to your statusbar, and recompile using the make command.
static const Block blocks[] = {
	/*Icon*/	/*Command*/		/*Update Interval*/	/*Update Signal*/
	{"", "cat /tmp/recordingicon 2>/dev/null",	0,	9},
	{"",	"sb-lastdose",	60,	11},
	{"",	"sb-volume",	0,	10},
	{"",	"sb-battery",	5,	3},
	{"",	"sb-clocks",	60,	1},
};

//Sets delimiter between status commands. NULL character ('\0') means no delimiter.
static char *delim = " ";
EOF
cd ~/.local/src/dwmblocks
sudo make clean install

# Create statusbar scripts
info "Installing statusbar scripts..."
mkdir -p ~/.local/bin/statusbar

# sb-battery
cat > ~/.local/bin/statusbar/sb-battery << 'EOF'
#!/bin/sh

case $BLOCK_BUTTON in
	3) notify-send "Battery module" "Discharging/Not charging/Stagnant/Charging/Charged
- Scroll to change adjust xbacklight." ;;
	4) xbacklight -inc 10 ;;
	5) xbacklight -dec 10 ;;
	6) setsid -f "$TERMINAL" -e "$EDITOR" "$0" ;;
esac

for battery in /sys/class/power_supply/BAT?*; do
	[ -n "${capacity+x}" ] && printf " "
	case "$(cat "$battery/status" 2>&1)" in
		"Full") status="[CHG]" ;;
		"Discharging") status="[BAT]" ;;
		"Charging") status="[CHG]" ;;
		"Not charging") status="[---]" ;;
		"Unknown") status="[???]" ;;
		*) exit 1 ;;
	esac
	capacity="$(cat "$battery/capacity" 2>&1)"
	[ "$status" = "[BAT]" ] && [ "$capacity" -le 25 ] && warn="!"
	printf "%s%s%d%%" "$status" "$warn" "$capacity"; unset warn
done && printf "\\n"
EOF
chmod +x ~/.local/bin/statusbar/sb-battery

# sb-clocks
cat > ~/.local/bin/statusbar/sb-clocks << 'EOF'
#!/bin/sh

# Multi-timezone clock: US, UK, CH + local if different

us=$(TZ="America/New_York" date "+%H:%M")
uk=$(TZ="Europe/London" date "+%H:%M")
ch=$(TZ="Europe/Zurich" date "+%H:%M")
local=$(date "+%H:%M")
localtz=$(date "+%Z")

case $BLOCK_BUTTON in
	1) notify-send "This Month" "$(cal | sed "s/\<$(date +'%e'|sed 's/ //g')\>/<b><span color='red'>&<\/span><\/b>/")" && notify-send "Appointments" "$(calcurse -d3)" ;;
	2) setsid -f "$TERMINAL" -e calcurse ;;
	3) notify-send "Time Zones" "US: $(TZ='America/New_York' date '+%Y-%m-%d %H:%M:%S')
UK: $(TZ='Europe/London' date '+%Y-%m-%d %H:%M:%S')
CH: $(TZ='Europe/Zurich' date '+%Y-%m-%d %H:%M:%S')
Local: $(date '+%Y-%m-%d %H:%M:%S %Z')" ;;
	6) setsid -f "$TERMINAL" -e "$EDITOR" "$0" ;;
esac

localpart=""
if [ "$local" != "$us" ] && [ "$local" != "$uk" ] && [ "$local" != "$ch" ]; then
	localpart=" here:$local"
fi

date "+%b %d" | tr -d '\n'
echo " US:$us UK:$uk CH:$ch$localpart"
EOF
chmod +x ~/.local/bin/statusbar/sb-clocks

# sb-volume
cat > ~/.local/bin/statusbar/sb-volume << 'EOF'
#!/bin/sh

case $BLOCK_BUTTON in
	1) setsid -w -f "$TERMINAL" -e pulsemixer; pkill -RTMIN+10 "${STATUSBAR:-dwmblocks}" ;;
	2) wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle ;;
	4) wpctl set-volume @DEFAULT_AUDIO_SINK@ 1%+ ;;
	5) wpctl set-volume @DEFAULT_AUDIO_SINK@ 1%- ;;
	3) notify-send "Volume module" "Shows volume, muted if muted.
- Middle click to mute.
- Scroll to change." ;;
	6) setsid -f "$TERMINAL" -e "$EDITOR" "$0" ;;
esac

vol="$(wpctl get-volume @DEFAULT_AUDIO_SINK@)"

[ "$vol" != "${vol%\[MUTED\]}" ] && echo "[MUTE]" && exit

vol="${vol#Volume: }"

split() {
	IFS=$2
	set -- $1
	printf '%s' "$@"
}

vol="$(printf "%.0f" "$(split "$vol" ".")")"

case 1 in
	$((vol >= 70)) ) icon="[HI]" ;;
	$((vol >= 30)) ) icon="[MD]" ;;
	$((vol >= 1)) ) icon="[LO]" ;;
	* ) echo "[MUTE]" && exit ;;
esac

echo "$icon$vol%"
EOF
chmod +x ~/.local/bin/statusbar/sb-volume

# sb-lastdose (health tracking integration)
cat > ~/.local/bin/statusbar/sb-lastdose << 'EOF'
#!/bin/sh

# Last dose tracker from api.josie.health
# Toggle visibility: touch/rm ~/.cache/lastdose-visible

CACHE_DIR="${XDG_CACHE_HOME:-$HOME/.cache}"
TOGGLE_FILE="$CACHE_DIR/lastdose-visible"
CACHE_FILE="$CACHE_DIR/lastdose-cache"
USER_ID="imnotjosie"
API_URL="https://api.josie.health/v1/metrics/users/$USER_ID/lastdose"
AUTH="admin:admin_password_change_me"

case $BLOCK_BUTTON in
	1) setsid -f sh -c '
	   cf="'"$CACHE_FILE"'"
	   auth="'"$AUTH"'"
	   [ ! -f "$cf" ] && notify-send "Last Dose" "No data cached" && exit
	   ts=$(sed -n "s/^Time: //p" "$cf")
	   [ -z "$ts" ] && notify-send "Last Dose" "No timestamp" && exit
	   dose_epoch=$(date -d "$ts" +%s 2>/dev/null)
	   [ -z "$dose_epoch" ] && notify-send "Last Dose" "Invalid timestamp" && exit
	   fetch_epoch=$(date +%s)
	   hh=$(curl -s -m 3 -u "$auth" "https://api.josie.health/v1/metrics/users/'"$USER_ID"'/howhighami" 2>/dev/null)
	   hours_remaining=""
	   if [ -n "$hh" ] && ! echo "$hh" | grep -q "error"; then
	     hours_remaining=$(echo "$hh" | jq -r ".active_substances[0].hours_remaining // empty" 2>/dev/null)
	     active=$(echo "$hh" | jq -r ".active_substances[] | \"\(.name): \(.dosage) (\(.status))\"" 2>/dev/null | head -5)
	     consecutive=$(echo "$hh" | jq -r ".session_summary.entries_count // empty" 2>/dev/null)
	     session_dur=$(echo "$hh" | jq -r ".session_summary.duration_minutes // empty" 2>/dev/null)
	   fi
	   remaining_at_fetch=""
	   if [ -n "$hours_remaining" ] && [ "$hours_remaining" != "null" ]; then
	     remaining_at_fetch=$(echo "$hours_remaining * 3600" | bc 2>/dev/null | cut -d. -f1)
	   fi
	   while true; do
	     now_epoch=$(date +%s)
	     diff=$((now_epoch - dose_epoch))
	     ago_h=$((diff / 3600))
	     ago_m=$(((diff % 3600) / 60))
	     ago_s=$((diff % 60))
	     if [ $ago_h -gt 0 ]; then
	       ago_long="${ago_h}h ${ago_m}m ${ago_s}s ago"
	     elif [ $ago_m -gt 0 ]; then
	       ago_long="${ago_m}m ${ago_s}s ago"
	     else
	       ago_long="${ago_s}s ago"
	     fi
	     body="$ago_long"
	     if [ -n "$remaining_at_fetch" ]; then
	       elapsed_since_fetch=$((now_epoch - fetch_epoch))
	       remaining_secs=$((remaining_at_fetch - elapsed_since_fetch))
	       if [ $remaining_secs -gt 0 ]; then
	         rem_h=$((remaining_secs / 3600))
	         rem_m=$(((remaining_secs % 3600) / 60))
	         if [ $rem_h -gt 0 ]; then
	           body="$body (${rem_h}h ${rem_m}m left)"
	         else
	           body="$body (${rem_m}m left)"
	         fi
	       fi
	     fi
	     [ -n "$consecutive" ] && [ "$consecutive" -gt 1 ] && body="$body\nSession: ${consecutive} doses"
	     [ -n "$session_dur" ] && [ "$session_dur" -gt 0 ] && body="$body (${session_dur}min)"
	     [ -n "$active" ] && body="$body\n\n$active"
	     reason=$(dunstify -r 91234 -t 1100 -b "Last Dose" "$body")
	     [ "$reason" != "1" ] && break
	   done
	   ' >/dev/null 2>&1 ;;
	2) [ -f "$TOGGLE_FILE" ] && rm "$TOGGLE_FILE" || touch "$TOGGLE_FILE"
	   kill -45 $(pidof dwmblocks) 2>/dev/null ;;
	3) notify-send "Last Dose" "Middle-click to toggle visibility
User: $USER_ID
API: $API_URL" ;;
	6) setsid -f "$TERMINAL" -e "$EDITOR" "$0" ;;
esac

[ ! -f "$TOGGLE_FILE" ] && printf "[RX]\n" && exit 0

response=$(curl -s -m 3 -u "$AUTH" "$API_URL" 2>/dev/null)

[ -z "$response" ] && exit 0
echo "$response" | grep -q '"error"' && exit 0

substance=$(echo "$response" | sed -n 's/.*"normalized_substance"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p')
dosage=$(echo "$response" | sed -n 's/.*"dosage"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p')
timestamp=$(echo "$response" | sed -n 's/.*"timestamp"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p')
route=$(echo "$response" | sed -n 's/.*"normalized_route"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p')

[ -z "$substance" ] && exit 0

remaining=""
if [ -n "$timestamp" ]; then
	dose_epoch=$(date -d "$timestamp" +%s 2>/dev/null)
	now_epoch=$(date +%s)
	if [ -n "$dose_epoch" ]; then
		diff=$((now_epoch - dose_epoch))
		if [ $diff -lt 60 ]; then
			ago="now"
		elif [ $diff -lt 3600 ]; then
			ago="$((diff / 60))m"
		elif [ $diff -lt 86400 ]; then
			ago="$((diff / 3600))h"
		else
			ago="$((diff / 86400))d"
		fi
		ago_h=$((diff / 3600))
		ago_m=$(((diff % 3600) / 60))
		ago_s=$((diff % 60))
		if [ $ago_h -gt 0 ]; then
			ago_long="${ago_h}h ${ago_m}m ${ago_s}s"
		elif [ $ago_m -gt 0 ]; then
			ago_long="${ago_m}m ${ago_s}s"
		else
			ago_long="${ago_s}s"
		fi

		hh_resp=$(curl -s -m 2 -u "$AUTH" "https://api.josie.health/v1/metrics/users/$USER_ID/howhighami" 2>/dev/null)
		if [ -n "$hh_resp" ] && ! echo "$hh_resp" | grep -q '"error"'; then
			hours_remaining=$(echo "$hh_resp" | jq -r ".active_substances[0].hours_remaining // empty" 2>/dev/null)
			if [ -n "$hours_remaining" ] && [ "$hours_remaining" != "null" ]; then
				remaining_secs=$(echo "$hours_remaining * 3600" | bc 2>/dev/null | cut -d. -f1)
				if [ -n "$remaining_secs" ] && [ "$remaining_secs" -gt 0 ]; then
					if [ $remaining_secs -lt 3600 ]; then
						remaining="$((remaining_secs / 60))m left"
					else
						remaining="$((remaining_secs / 3600))h left"
					fi
				fi
			fi
		fi
	else
		ago=""
	fi
fi

printf "Substance: %s\nDosage: %s\nRoute: %s\nTime: %s\nAgo: %s\nRemaining: %s\n" \
	"$substance" "$dosage" "$route" "$timestamp" "$ago_long" "$remaining" > "$CACHE_FILE"

if [ -n "$ago" ]; then
	if [ -n "$remaining" ]; then
		printf "[RX] %s %s (%s; %s)\n" "$dosage" "$substance" "$ago" "$remaining"
	else
		printf "[RX] %s %s (%s)\n" "$dosage" "$substance" "$ago"
	fi
else
	printf "[RX] %s %s\n" "$dosage" "$substance"
fi
EOF
chmod +x ~/.local/bin/statusbar/sb-lastdose

# ============================================================================
# PHASE 4: Set up directory structure (XDG compliant)
# ============================================================================
info "Creating XDG directory structure..."

mkdir -p ~/.config/{zsh,x11,shell,dunst,alacritty,nvim,lf}
mkdir -p ~/.local/{bin,share,src}
mkdir -p ~/.local/bin/statusbar
mkdir -p ~/.cache

# ============================================================================
# PHASE 5: Configure zsh
# ============================================================================
info "Configuring zsh..."

# Install oh-my-zsh
if [ ! -d ~/.oh-my-zsh ]; then
    info "Installing oh-my-zsh..."
    sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" "" --unattended
fi

# Install powerlevel10k
if [ ! -d ~/.oh-my-zsh/custom/themes/powerlevel10k ]; then
    info "Installing powerlevel10k..."
    git clone --depth=1 https://github.com/romkatv/powerlevel10k.git ~/.oh-my-zsh/custom/themes/powerlevel10k
fi

# Install zsh-fast-syntax-highlighting
if [ ! -d ~/.oh-my-zsh/custom/plugins/fast-syntax-highlighting ]; then
    info "Installing fast-syntax-highlighting..."
    git clone https://github.com/zdharma-continuum/fast-syntax-highlighting.git ~/.oh-my-zsh/custom/plugins/fast-syntax-highlighting
fi

# Create zprofile
cat > ~/.zprofile << 'EOF'
#!/bin/sh

# Add all directories in ~/.local/bin to $PATH
export PATH="$PATH:$(find ~/.local/bin -type d | paste -sd ':' -)"

unsetopt PROMPT_SP 2>/dev/null

# Default programs
export EDITOR="nvim"
export TERMINAL="alacritty"
export TERMINAL_PROG="alacritty"
export BROWSER="firefox"

# XDG directories
export XDG_CONFIG_HOME="$HOME/.config"
export XDG_DATA_HOME="$HOME/.local/share"
export XDG_CACHE_HOME="$HOME/.cache"
export XINITRC="$XDG_CONFIG_HOME/x11/xinitrc"
export ZDOTDIR="$XDG_CONFIG_HOME/zsh"
export HISTFILE="$XDG_DATA_HOME/history"
export CARGO_HOME="$XDG_DATA_HOME/cargo"
export GOPATH="$XDG_DATA_HOME/go"
export GOMODCACHE="$XDG_CACHE_HOME/go/mod"

# Other settings
export FZF_DEFAULT_OPTS="--layout=reverse --height 40%"
export LESS="R"
export QT_QPA_PLATFORMTHEME="gtk2"
export MOZ_USE_XINPUT2=1
export _JAVA_AWT_WM_NONREPARENTING=1

# Start X on tty1
[ "$(tty)" = "/dev/tty1" ] && ! pidof -s Xorg >/dev/null 2>&1 && exec startx "$XINITRC"
EOF

# Create zshrc
cat > ~/.config/zsh/.zshrc << 'EOF'
# Enable Powerlevel10k instant prompt
if [[ -r "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh" ]]; then
  source "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh"
fi

export SHELL="/bin/zsh"

# Enable colors
autoload -U colors && colors
setopt autocd
setopt interactive_comments

# History settings
HISTSIZE=10000000
SAVEHIST=10000000
HISTFILE=~/.zsh_history
setopt APPEND_HISTORY
setopt EXTENDED_HISTORY
setopt HIST_VERIFY
setopt SHARE_HISTORY
setopt INC_APPEND_HISTORY
setopt HIST_EXPIRE_DUPS_FIRST
setopt HIST_IGNORE_DUPS
setopt HIST_FIND_NO_DUPS
setopt HIST_REDUCE_BLANKS

# Tab completion
autoload -U compinit -C
zstyle ':completion:*' menu select
zmodload zsh/complist
compinit -C
_comp_options+=(globdots)

# vi mode
bindkey -v
export KEYTIMEOUT=1

# Vim keys in tab complete menu
bindkey -M menuselect 'h' vi-backward-char
bindkey -M menuselect 'k' vi-up-line-or-history
bindkey -M menuselect 'l' vi-forward-char
bindkey -M menuselect 'j' vi-down-line-or-history
bindkey -v '^?' backward-delete-char

# Cursor shape for vi modes
function zle-keymap-select () {
    case $KEYMAP in
        vicmd) echo -ne '\e[1 q';;
        viins|main) echo -ne '\e[5 q';;
    esac
}
zle -N zle-keymap-select
zle-line-init() { zle -K viins; echo -ne "\e[5 q"; }
zle -N zle-line-init
echo -ne '\e[5 q'
preexec() { echo -ne '\e[5 q'; }

# Useful keybindings
bindkey -s '^f' 'cd "$(dirname "$(fzf)")"\n'
bindkey '^[[P' delete-char
autoload edit-command-line; zle -N edit-command-line
bindkey '^e' edit-command-line
bindkey '^R' history-incremental-search-backward

export GPG_TTY=$(tty)

# oh-my-zsh
export ZSH="$HOME/.oh-my-zsh"
ZSH_THEME="powerlevel10k/powerlevel10k"

plugins=(
    git
    kubectl
    fast-syntax-highlighting
)

source $ZSH/oh-my-zsh.sh

# Aliases
[ -f "${XDG_CONFIG_HOME:-$HOME/.config}/shell/aliasrc" ] && source "${XDG_CONFIG_HOME:-$HOME/.config}/shell/aliasrc"

# PATH
export PATH="${KREW_ROOT:-$HOME/.krew}/bin:$PATH"
export PATH=$PATH:$HOME/bin
export PATH=$PATH:$HOME/.local/bin
export PATH=$PATH:$HOME/.local/bin/statusbar
export PATH=$PATH:$GOPATH/bin
export PATH=$PATH:~/.local/share/cargo/bin

# p10k config
[[ ! -f ~/.config/zsh/.p10k.zsh ]] || source ~/.config/zsh/.p10k.zsh
typeset -g POWERLEVEL9K_INSTANT_PROMPT=quiet
EOF

# Create p10k config (full local config)
cat > ~/.config/zsh/.p10k.zsh << 'ENDP10K'
# Generated by Powerlevel10k configuration wizard
# Based on romkatv/powerlevel10k/config/p10k-rainbow.zsh
# Wizard options: awesome-fontconfig, large icons, rainbow, unicode, 24h time,
# flat heads, flat tails, 1 line, compact, few icons, concise, transient_prompt

'builtin' 'local' '-a' 'p10k_config_opts'
[[ ! -o 'aliases'         ]] || p10k_config_opts+=('aliases')
[[ ! -o 'sh_glob'         ]] || p10k_config_opts+=('sh_glob')
[[ ! -o 'no_brace_expand' ]] || p10k_config_opts+=('no_brace_expand')
'builtin' 'setopt' 'no_aliases' 'no_sh_glob' 'brace_expand'

() {
  emulate -L zsh -o extended_glob
  unset -m '(POWERLEVEL9K_*|DEFAULT_USER)~POWERLEVEL9K_GITSTATUS_DIR'
  [[ $ZSH_VERSION == (5.<1->*|<6->.*) ]] || return

  typeset -g POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(dir vcs)
  typeset -g POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS=(
    status command_execution_time background_jobs direnv asdf virtualenv anaconda
    pyenv goenv rbenv rvm fvm luaenv jenv plenv perlbrew phpenv scalaenv
    haskell_stack kubecontext terraform aws aws_eb_env azure gcloud google_app_cred
    toolbox context nordvpn ranger nnn lf xplr vim_shell midnight_commander nix_shell
    vi_mode todo timewarrior taskwarrior time
  )

  typeset -g POWERLEVEL9K_MODE=awesome-fontconfig
  typeset -g POWERLEVEL9K_ICON_PADDING=moderate
  typeset -g POWERLEVEL9K_ICON_BEFORE_CONTENT=
  typeset -g POWERLEVEL9K_PROMPT_ADD_NEWLINE=false

  typeset -g POWERLEVEL9K_MULTILINE_FIRST_PROMPT_PREFIX='%242F\u256D\u2500'
  typeset -g POWERLEVEL9K_MULTILINE_NEWLINE_PROMPT_PREFIX='%242F\u251C\u2500'
  typeset -g POWERLEVEL9K_MULTILINE_LAST_PROMPT_PREFIX='%242F\u2570\u2500'
  typeset -g POWERLEVEL9K_MULTILINE_FIRST_PROMPT_SUFFIX='%242F\u2500\u256E'
  typeset -g POWERLEVEL9K_MULTILINE_NEWLINE_PROMPT_SUFFIX='%242F\u2500\u2524'
  typeset -g POWERLEVEL9K_MULTILINE_LAST_PROMPT_SUFFIX='%242F\u2500\u256F'
  typeset -g POWERLEVEL9K_MULTILINE_FIRST_PROMPT_GAP_CHAR=' '
  typeset -g POWERLEVEL9K_MULTILINE_FIRST_PROMPT_GAP_BACKGROUND=
  typeset -g POWERLEVEL9K_MULTILINE_NEWLINE_PROMPT_GAP_BACKGROUND=

  typeset -g POWERLEVEL9K_LEFT_SUBSEGMENT_SEPARATOR='\u2502'
  typeset -g POWERLEVEL9K_RIGHT_SUBSEGMENT_SEPARATOR='\u2502'
  typeset -g POWERLEVEL9K_LEFT_SEGMENT_SEPARATOR=''
  typeset -g POWERLEVEL9K_RIGHT_SEGMENT_SEPARATOR=''
  typeset -g POWERLEVEL9K_LEFT_PROMPT_LAST_SEGMENT_END_SYMBOL=''
  typeset -g POWERLEVEL9K_RIGHT_PROMPT_FIRST_SEGMENT_START_SYMBOL=''
  typeset -g POWERLEVEL9K_LEFT_PROMPT_FIRST_SEGMENT_START_SYMBOL=''
  typeset -g POWERLEVEL9K_RIGHT_PROMPT_LAST_SEGMENT_END_SYMBOL=''
  typeset -g POWERLEVEL9K_EMPTY_LINE_LEFT_PROMPT_LAST_SEGMENT_END_SYMBOL=

  # Directory
  typeset -g POWERLEVEL9K_DIR_BACKGROUND=4
  typeset -g POWERLEVEL9K_DIR_FOREGROUND=254
  typeset -g POWERLEVEL9K_SHORTEN_STRATEGY=truncate_to_unique
  typeset -g POWERLEVEL9K_SHORTEN_DELIMITER=
  typeset -g POWERLEVEL9K_DIR_SHORTENED_FOREGROUND=250
  typeset -g POWERLEVEL9K_DIR_ANCHOR_FOREGROUND=255
  typeset -g POWERLEVEL9K_DIR_ANCHOR_BOLD=true
  typeset -g POWERLEVEL9K_SHORTEN_DIR_LENGTH=1
  typeset -g POWERLEVEL9K_DIR_MAX_LENGTH=80
  typeset -g POWERLEVEL9K_DIR_MIN_COMMAND_COLUMNS=40
  typeset -g POWERLEVEL9K_DIR_MIN_COMMAND_COLUMNS_PCT=50
  typeset -g POWERLEVEL9K_DIR_HYPERLINK=false
  typeset -g POWERLEVEL9K_DIR_SHOW_WRITABLE=v3
  typeset -g POWERLEVEL9K_DIR_CLASSES=()

  # VCS (Git)
  typeset -g POWERLEVEL9K_VCS_CLEAN_BACKGROUND=2
  typeset -g POWERLEVEL9K_VCS_MODIFIED_BACKGROUND=3
  typeset -g POWERLEVEL9K_VCS_UNTRACKED_BACKGROUND=2
  typeset -g POWERLEVEL9K_VCS_CONFLICTED_BACKGROUND=3
  typeset -g POWERLEVEL9K_VCS_LOADING_BACKGROUND=8
  typeset -g POWERLEVEL9K_VCS_BRANCH_ICON=
  typeset -g POWERLEVEL9K_VCS_UNTRACKED_ICON='?'
  typeset -g POWERLEVEL9K_VCS_MAX_INDEX_SIZE_DIRTY=-1
  typeset -g POWERLEVEL9K_VCS_DISABLED_WORKDIR_PATTERN='~'
  typeset -g POWERLEVEL9K_VCS_DISABLE_GITSTATUS_FORMATTING=true
  typeset -g POWERLEVEL9K_VCS_VISUAL_IDENTIFIER_EXPANSION=
  typeset -g POWERLEVEL9K_VCS_BACKENDS=(git)
  typeset -g POWERLEVEL9K_VCS_{STAGED,UNSTAGED,UNTRACKED,CONFLICTED,COMMITS_AHEAD,COMMITS_BEHIND}_MAX_NUM=-1

  function my_git_formatter() {
    emulate -L zsh
    if [[ -n $P9K_CONTENT ]]; then
      typeset -g my_git_format=$P9K_CONTENT
      return
    fi
    local meta='%7F' clean='%0F' modified='%0F' untracked='%0F' conflicted='%1F'
    local res
    if [[ -n $VCS_STATUS_LOCAL_BRANCH ]]; then
      local branch=${(V)VCS_STATUS_LOCAL_BRANCH}
      (( $#branch > 32 )) && branch[13,-13]="..."
      res+="${clean}${(g::)POWERLEVEL9K_VCS_BRANCH_ICON}${branch//\%/%%}"
    fi
    if [[ -n $VCS_STATUS_TAG && -z $VCS_STATUS_LOCAL_BRANCH ]]; then
      local tag=${(V)VCS_STATUS_TAG}
      (( $#tag > 32 )) && tag[13,-13]="..."
      res+="${meta}#${clean}${tag//\%/%%}"
    fi
    [[ -z $VCS_STATUS_LOCAL_BRANCH && -z $VCS_STATUS_TAG ]] && res+="${meta}@${clean}${VCS_STATUS_COMMIT[1,8]}"
    [[ -n ${VCS_STATUS_REMOTE_BRANCH:#$VCS_STATUS_LOCAL_BRANCH} ]] && res+="${meta}:${clean}${(V)VCS_STATUS_REMOTE_BRANCH//\%/%%}"
    [[ $VCS_STATUS_COMMIT_SUMMARY == (|*[^[:alnum:]])(wip|WIP)(|[^[:alnum:]]*) ]] && res+=" ${modified}wip"
    (( VCS_STATUS_COMMITS_BEHIND )) && res+=" ${clean}\u21E3${VCS_STATUS_COMMITS_BEHIND}"
    (( VCS_STATUS_COMMITS_AHEAD && !VCS_STATUS_COMMITS_BEHIND )) && res+=" "
    (( VCS_STATUS_COMMITS_AHEAD )) && res+="${clean}\u21E1${VCS_STATUS_COMMITS_AHEAD}"
    (( VCS_STATUS_PUSH_COMMITS_BEHIND )) && res+=" ${clean}\u21E0${VCS_STATUS_PUSH_COMMITS_BEHIND}"
    (( VCS_STATUS_PUSH_COMMITS_AHEAD && !VCS_STATUS_PUSH_COMMITS_BEHIND )) && res+=" "
    (( VCS_STATUS_PUSH_COMMITS_AHEAD )) && res+="${clean}\u21E2${VCS_STATUS_PUSH_COMMITS_AHEAD}"
    (( VCS_STATUS_STASHES )) && res+=" ${clean}*${VCS_STATUS_STASHES}"
    [[ -n $VCS_STATUS_ACTION ]] && res+=" ${conflicted}${VCS_STATUS_ACTION}"
    (( VCS_STATUS_NUM_CONFLICTED )) && res+=" ${conflicted}~${VCS_STATUS_NUM_CONFLICTED}"
    (( VCS_STATUS_NUM_STAGED )) && res+=" ${modified}+${VCS_STATUS_NUM_STAGED}"
    (( VCS_STATUS_NUM_UNSTAGED )) && res+=" ${modified}!${VCS_STATUS_NUM_UNSTAGED}"
    (( VCS_STATUS_NUM_UNTRACKED )) && res+=" ${untracked}${(g::)POWERLEVEL9K_VCS_UNTRACKED_ICON}${VCS_STATUS_NUM_UNTRACKED}"
    (( VCS_STATUS_HAS_UNSTAGED == -1 )) && res+=" ${modified}\u2500"
    typeset -g my_git_format=$res
  }
  functions -M my_git_formatter 2>/dev/null
  typeset -g POWERLEVEL9K_VCS_CONTENT_EXPANSION='${$((my_git_formatter()))+${my_git_format}}'

  # Status
  typeset -g POWERLEVEL9K_STATUS_EXTENDED_STATES=true
  typeset -g POWERLEVEL9K_STATUS_OK=true
  typeset -g POWERLEVEL9K_STATUS_OK_VISUAL_IDENTIFIER_EXPANSION='\u2714'
  typeset -g POWERLEVEL9K_STATUS_OK_FOREGROUND=2
  typeset -g POWERLEVEL9K_STATUS_OK_BACKGROUND=0
  typeset -g POWERLEVEL9K_STATUS_OK_PIPE=true
  typeset -g POWERLEVEL9K_STATUS_OK_PIPE_VISUAL_IDENTIFIER_EXPANSION='\u2714'
  typeset -g POWERLEVEL9K_STATUS_OK_PIPE_FOREGROUND=2
  typeset -g POWERLEVEL9K_STATUS_OK_PIPE_BACKGROUND=0
  typeset -g POWERLEVEL9K_STATUS_ERROR=true
  typeset -g POWERLEVEL9K_STATUS_ERROR_VISUAL_IDENTIFIER_EXPANSION='\u2718'
  typeset -g POWERLEVEL9K_STATUS_ERROR_FOREGROUND=3
  typeset -g POWERLEVEL9K_STATUS_ERROR_BACKGROUND=1
  typeset -g POWERLEVEL9K_STATUS_ERROR_SIGNAL=true
  typeset -g POWERLEVEL9K_STATUS_VERBOSE_SIGNAME=false
  typeset -g POWERLEVEL9K_STATUS_ERROR_SIGNAL_VISUAL_IDENTIFIER_EXPANSION='\u2718'
  typeset -g POWERLEVEL9K_STATUS_ERROR_SIGNAL_FOREGROUND=3
  typeset -g POWERLEVEL9K_STATUS_ERROR_SIGNAL_BACKGROUND=1
  typeset -g POWERLEVEL9K_STATUS_ERROR_PIPE=true
  typeset -g POWERLEVEL9K_STATUS_ERROR_PIPE_VISUAL_IDENTIFIER_EXPANSION='\u2718'
  typeset -g POWERLEVEL9K_STATUS_ERROR_PIPE_FOREGROUND=3
  typeset -g POWERLEVEL9K_STATUS_ERROR_PIPE_BACKGROUND=1

  # Command execution time
  typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_FOREGROUND=0
  typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_BACKGROUND=3
  typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_THRESHOLD=3
  typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_PRECISION=0
  typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_FORMAT='d h m s'
  typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_VISUAL_IDENTIFIER_EXPANSION=

  # Background jobs
  typeset -g POWERLEVEL9K_BACKGROUND_JOBS_FOREGROUND=6
  typeset -g POWERLEVEL9K_BACKGROUND_JOBS_BACKGROUND=0
  typeset -g POWERLEVEL9K_BACKGROUND_JOBS_VERBOSE=false

  # Context
  typeset -g POWERLEVEL9K_CONTEXT_ROOT_FOREGROUND=1
  typeset -g POWERLEVEL9K_CONTEXT_ROOT_BACKGROUND=0
  typeset -g POWERLEVEL9K_CONTEXT_{REMOTE,REMOTE_SUDO}_FOREGROUND=3
  typeset -g POWERLEVEL9K_CONTEXT_{REMOTE,REMOTE_SUDO}_BACKGROUND=0
  typeset -g POWERLEVEL9K_CONTEXT_FOREGROUND=3
  typeset -g POWERLEVEL9K_CONTEXT_BACKGROUND=0
  typeset -g POWERLEVEL9K_CONTEXT_ROOT_TEMPLATE='%n@%m'
  typeset -g POWERLEVEL9K_CONTEXT_{REMOTE,REMOTE_SUDO}_TEMPLATE='%n@%m'
  typeset -g POWERLEVEL9K_CONTEXT_TEMPLATE='%n@%m'
  typeset -g POWERLEVEL9K_CONTEXT_{DEFAULT,SUDO}_{CONTENT,VISUAL_IDENTIFIER}_EXPANSION=

  # Virtualenv
  typeset -g POWERLEVEL9K_VIRTUALENV_FOREGROUND=0
  typeset -g POWERLEVEL9K_VIRTUALENV_BACKGROUND=4
  typeset -g POWERLEVEL9K_VIRTUALENV_SHOW_PYTHON_VERSION=false
  typeset -g POWERLEVEL9K_VIRTUALENV_SHOW_WITH_PYENV=false
  typeset -g POWERLEVEL9K_VIRTUALENV_{LEFT,RIGHT}_DELIMITER=
  typeset -g POWERLEVEL9K_VIRTUALENV_VISUAL_IDENTIFIER_EXPANSION='\U0001F40D'

  # Kubecontext
  typeset -g POWERLEVEL9K_KUBECONTEXT_SHOW_ON_COMMAND='kubectl|helm|kubens|kubectx|oc|istioctl|kogito|k9s|helmfile|flux|fluxctl|stern|kubeseal|skaffold|kubent|kubecolor'
  typeset -g POWERLEVEL9K_KUBECONTEXT_CLASSES=('*' DEFAULT)
  typeset -g POWERLEVEL9K_KUBECONTEXT_DEFAULT_FOREGROUND=7
  typeset -g POWERLEVEL9K_KUBECONTEXT_DEFAULT_BACKGROUND=5
  typeset -g POWERLEVEL9K_KUBECONTEXT_DEFAULT_CONTENT_EXPANSION='${P9K_KUBECONTEXT_CLOUD_CLUSTER:-${P9K_KUBECONTEXT_NAME}}${${:-/$P9K_KUBECONTEXT_NAMESPACE}:#/default}'

  # AWS
  typeset -g POWERLEVEL9K_AWS_SHOW_ON_COMMAND='aws|awless|terraform|pulumi|terragrunt'
  typeset -g POWERLEVEL9K_AWS_CLASSES=('*' DEFAULT)
  typeset -g POWERLEVEL9K_AWS_DEFAULT_FOREGROUND=7
  typeset -g POWERLEVEL9K_AWS_DEFAULT_BACKGROUND=1
  typeset -g POWERLEVEL9K_AWS_CONTENT_EXPANSION='${P9K_AWS_PROFILE//\%/%%}${P9K_AWS_REGION:+ ${P9K_AWS_REGION//\%/%%}}'

  # Time
  typeset -g POWERLEVEL9K_TIME_FOREGROUND=0
  typeset -g POWERLEVEL9K_TIME_BACKGROUND=7
  typeset -g POWERLEVEL9K_TIME_FORMAT='%D{%H:%M:%S}'
  typeset -g POWERLEVEL9K_TIME_UPDATE_ON_COMMAND=false
  typeset -g POWERLEVEL9K_TIME_VISUAL_IDENTIFIER_EXPANSION=

  # Vi mode
  typeset -g POWERLEVEL9K_VI_MODE_FOREGROUND=0
  typeset -g POWERLEVEL9K_VI_COMMAND_MODE_STRING=NORMAL
  typeset -g POWERLEVEL9K_VI_MODE_NORMAL_BACKGROUND=2
  typeset -g POWERLEVEL9K_VI_VISUAL_MODE_STRING=VISUAL
  typeset -g POWERLEVEL9K_VI_MODE_VISUAL_BACKGROUND=4
  typeset -g POWERLEVEL9K_VI_OVERWRITE_MODE_STRING=OVERTYPE
  typeset -g POWERLEVEL9K_VI_MODE_OVERWRITE_BACKGROUND=3
  typeset -g POWERLEVEL9K_VI_INSERT_MODE_STRING=
  typeset -g POWERLEVEL9K_VI_MODE_INSERT_FOREGROUND=8

  # Transient prompt
  typeset -g POWERLEVEL9K_TRANSIENT_PROMPT=always
  typeset -g POWERLEVEL9K_INSTANT_PROMPT=verbose
  typeset -g POWERLEVEL9K_DISABLE_HOT_RELOAD=true

  (( ! $+functions[p10k] )) || p10k reload
}

typeset -g POWERLEVEL9K_CONFIG_FILE=${${(%):-%x}:a}
(( ${#p10k_config_opts} )) && setopt ${p10k_config_opts[@]}
'builtin' 'unset' 'p10k_config_opts'
ENDP10K

# Create shell aliases
cat > ~/.config/shell/aliasrc << 'EOF'
#!/bin/sh

# Use neovim for vim
[ -x "$(command -v nvim)" ] && alias vim="nvim" vimdiff="nvim -d"

# sudo for common system commands
for command in mount umount sv dnf updatedb su shutdown poweroff reboot; do
    alias $command="sudo $command"
done; unset command

# Verbosity and safety
alias cp="cp -iv"
alias mv="mv -iv"
alias rm="rm -vI"
alias bc="bc -ql"
alias rsync="rsync -vrPlu"
alias mkd="mkdir -pv"
alias yt="yt-dlp --embed-metadata -i"
alias yta="yt -x -f bestaudio/best"
alias ffmpeg="ffmpeg -hide_banner"

# Colorize
alias ls="ls -hN --color=auto --group-directories-first"
alias grep="grep --color=auto"
alias diff="diff --color=auto"
alias ip="ip -color=auto"

# Abbreviations
alias ka="killall"
alias g="git"
alias sdn="shutdown -h now"
alias e="nvim"
alias v="nvim"
alias p="sudo dnf"
alias z="zathura"
EOF

# ============================================================================
# PHASE 6: Configure X11 and dwm
# ============================================================================
info "Configuring X11..."

# xinitrc
cat > ~/.config/x11/xinitrc << 'EOF'
#!/bin/sh

if [ -f "${XDG_CONFIG_HOME:-$HOME/.config}/x11/xprofile" ]; then
    . "${XDG_CONFIG_HOME:-$HOME/.config}/x11/xprofile"
else
    . "$HOME/.xprofile"
fi

dbus-update-activation-environment --all
exec dbus-launch ssh-agent dwm
EOF
chmod +x ~/.config/x11/xinitrc

# xprofile
cat > ~/.config/x11/xprofile << 'EOF'
#!/bin/sh

xrandr --dpi 96
xset r rate 300 50 &
setxkbmap -option compose:caps &

# Set background (create setbg script or use feh)
[ -f ~/.config/wall.png ] && feh --bg-scale ~/.config/wall.png &

# Autostart programs
autostart="dunst unclutter pipewire"
for program in $autostart; do
    pidof -sx "$program" || "$program" &
done >/dev/null 2>&1
EOF
chmod +x ~/.config/x11/xprofile

# Create symlink for startx compatibility
ln -sf ~/.config/x11/xinitrc ~/.xinitrc

# ============================================================================
# PHASE 7: Configure Alacritty
# ============================================================================
info "Configuring Alacritty..."

cat > ~/.config/alacritty/alacritty.toml << 'EOF'
[env]
WINIT_X11_SCALE_FACTOR = "1.0"

[font]
size = 11

[font.normal]
family = "JetBrainsMono Nerd Font"
style = "Regular"

[font.bold]
family = "JetBrainsMono Nerd Font"
style = "Bold"

[font.italic]
family = "JetBrainsMono Nerd Font"
style = "Italic"

[window]
padding = { x = 8, y = 8 }
decorations = "None"
opacity = 1.0

[cursor]
style = { shape = "Block", blinking = "Off" }

# Gruvbox Dark
[colors.primary]
background = "#1d2021"
foreground = "#ebdbb2"

[colors.normal]
black   = "#3c3836"
red     = "#cc241d"
green   = "#98971a"
yellow  = "#d79921"
blue    = "#458588"
magenta = "#b16286"
cyan    = "#689d6a"
white   = "#a89984"

[colors.bright]
black   = "#928374"
red     = "#fb4934"
green   = "#b8bb26"
yellow  = "#fabd2f"
blue    = "#83a598"
magenta = "#d3869b"
cyan    = "#8ec07c"
white   = "#ebdbb2"
EOF

# ============================================================================
# PHASE 8: Configure Dunst
# ============================================================================
info "Configuring Dunst..."

cat > ~/.config/dunst/dunstrc << 'EOF'
[global]
    monitor = 0
    follow = keyboard
    width = 370
    height = 350
    offset = 0x19
    padding = 2
    horizontal_padding = 2
    transparency = 25
    font = JetBrainsMono Nerd Font 11
    format = "<b>%s</b>\n%b"

[urgency_low]
    background = "#1d2021"
    foreground = "#928374"
    timeout = 3

[urgency_normal]
    foreground = "#ebdbb2"
    background = "#458588"
    timeout = 5

[urgency_critical]
    background = "#cc241d"
    foreground = "#ebdbb2"
    frame_color = "#fabd2f"
    timeout = 10
EOF

# ============================================================================
# PHASE 9: Create utility scripts
# ============================================================================
info "Creating utility scripts..."

# setbg - set wallpaper (full version with pywal support)
cat > ~/.local/bin/setbg << 'EOF'
#!/bin/sh

# This script does the following:
#	Run by itself, set the wallpaper (at X start).
#	If given a file, set that as the new wallpaper.
#	If given a directory, choose random file in it.
#	If wal is installed, also generates a colorscheme.

bgloc="${XDG_DATA_HOME:-$HOME/.local/share}/bg"
dunstconf="${XDG_CONFIG_HOME:-$HOME/.config}/dunst/dunstrc"
zathuraconf="${XDG_CONFIG_HOME:-$HOME/.config}/zathura/zathurarc"

while getopts "s" o; do case "${o}" in
	s) silent='1' ;;
esac done

shift $((OPTIND - 1))

trueloc="$(readlink -f "$1")" &&
case "$(file --mime-type -b "$trueloc")" in
	image/* ) ln -sf "$trueloc" "$bgloc" && [ -z "$silent" ] && notify-send -i "$bgloc" "Changing wallpaper..." ;;
	inode/directory ) ln -sf "$(find "$trueloc" -iregex '.*.\(jpg\|jpeg\|png\|gif\)' -type f | shuf -n 1)" "$bgloc" && [ -z "$silent" ] && notify-send -i "$bgloc" "Random Wallpaper chosen." ;;
	*) [ -z "$silent" ] && notify-send "Error" "Not a valid image or directory." ; exit 1;;
esac

if command -v wal >/dev/null 2>&1 ; then
	wal -n -i "$(readlink -f $bgloc)" -o "${XDG_CONFIG_HOME:-$HOME/.config}/wal/postrun" >/dev/null 2>&1
else
	[ -f "$dunstconf.bak" ] && unlink "$dunstconf" && mv "$dunstconf.bak" "$dunstconf"
	[ -f "$zathuraconf.bak" ] && unlink "$zathuraconf" && mv "$zathuraconf.bak" "$zathuraconf"
fi

xwallpaper --zoom "$bgloc"
pidof dwm >/dev/null && xdotool key super+F5
EOF
chmod +x ~/.local/bin/setbg

# displayselect - xrandr display picker
cat > ~/.local/bin/displayselect << 'EOF'
#!/bin/sh

twoscreen() {
    mirror=$(printf "no\\nyes" | dmenu -i -p "Mirror displays?")
    if [ "$mirror" = "yes" ]; then
        external=$(echo "$screens" | dmenu -i -p "Optimize resolution for:")
        internal=$(echo "$screens" | grep -v "$external")
        res_external=$(xrandr --query | sed -n "/^$external/,/\+/p" | tail -n 1 | awk '{print $1}')
        res_internal=$(xrandr --query | sed -n "/^$internal/,/\+/p" | tail -n 1 | awk '{print $1}')
        res_ext_x=$(echo "$res_external" | sed 's/x.*//')
        res_ext_y=$(echo "$res_external" | sed 's/.*x//')
        res_int_x=$(echo "$res_internal" | sed 's/x.*//')
        res_int_y=$(echo "$res_internal" | sed 's/.*x//')
        scale_x=$(echo "$res_ext_x / $res_int_x" | bc -l)
        scale_y=$(echo "$res_ext_y / $res_int_y" | bc -l)
        xrandr --output "$external" --auto --scale 1.0x1.0 \
            --output "$internal" --auto --same-as "$external" \
            --scale "$scale_x"x"$scale_y"
    else
        primary=$(echo "$screens" | dmenu -i -p "Select primary display:")
        secondary=$(echo "$screens" | grep -v ^"$primary"$)
        direction=$(printf "left\\nright" | dmenu -i -p "What side of $primary should $secondary be on?")
        xrandr --output "$primary" --auto --scale 1.0x1.0 --output "$secondary" --"$direction"-of "$primary" --auto --scale 1.0x1.0
    fi
}

morescreen() {
	primary=$(echo "$screens" | dmenu -i -p "Select primary display:")
	secondary=$(echo "$screens" | grep -v ^"$primary"$ | dmenu -i -p "Select secondary display:")
	direction=$(printf "left\\nright" | dmenu -i -p "What side of $primary should $secondary be on?")
	tertiary=$(echo "$screens" | grep -v ^"$primary"$ | grep -v ^"$secondary"$ | dmenu -i -p "Select third display:")
	xrandr --output "$primary" --auto --output "$secondary" --"$direction"-of "$primary" --auto --output "$tertiary" --"$(printf "left\\nright" | grep -v "$direction")"-of "$primary" --auto
}

multimon() {
	case "$(echo "$screens" | wc -l)" in
		2) twoscreen ;;
		*) morescreen ;;
	esac
}

onescreen() {
	xrandr --output "$1" --auto --scale 1.0x1.0 $(echo "$allposs" | grep -v "\b$1" | awk '{print "--output", $1, "--off"}' | paste -sd ' ' -)
}

postrun() {
	setbg
	{ killall dunst ; setsid -f dunst ;} >/dev/null 2>&1
}

allposs=$(xrandr -q | grep "connected")
screens=$(echo "$allposs" | awk '/ connected/ {print $1}')

[ "$(echo "$screens" | wc -l)" -lt 2 ] &&
	{ onescreen "$screens"; postrun; notify-send "Only one screen detected." "Using it in its optimal settings..."; exit ;}

chosen=$(printf "%s\\nmulti-monitor\\nmanual selection" "$screens" | dmenu -i -p "Select display arangement:") &&
case "$chosen" in
	"manual selection") arandr ; exit ;;
	"multi-monitor") multimon ;;
	*) onescreen "$chosen" ;;
esac

postrun
EOF
chmod +x ~/.local/bin/displayselect

# maimpick - screenshot tool
cat > ~/.local/bin/maimpick << 'EOF'
#!/bin/sh

output="$(date '+%y%m%d-%H%M-%S').png"
xclip_cmd="xclip -sel clip -t image/png"

case "$(printf "a selected area\\ncurrent window\\nfull screen\\na selected area (copy)\\ncurrent window (copy)\\nfull screen (copy)" | dmenu -l 6 -i -p "Screenshot which area?")" in
    "a selected area") maim -u -s pic-selected-"${output}" ;;
    "current window") maim -B -q -d 0.2 -i "$(xdotool getactivewindow)" pic-window-"${output}" ;;
    "full screen") maim -q -d 0.2 pic-full-"${output}" ;;
    "a selected area (copy)") maim -u -s | ${xclip_cmd} ;;
    "current window (copy)") maim -q -d 0.2 -i "$(xdotool getactivewindow)" | ${xclip_cmd} ;;
    "full screen (copy)") maim -q -d 0.2 | ${xclip_cmd} ;;
esac
EOF
chmod +x ~/.local/bin/maimpick

# sysact - system actions menu
cat > ~/.local/bin/sysact << 'EOF'
#!/bin/sh

export WM="dwm"
case "$(readlink -f /sbin/init)" in
	*systemd*) ctl='systemctl' ;;
	*) ctl='loginctl' ;;
esac

wmpid(){
	tree="$(pstree -ps $$)"
	tree="${tree#*$WM(}"
	echo "${tree%%)*}"
}

case "$(printf "lock\nleave $WM\nrenew $WM\nhibernate\nreboot\nshutdown\nsleep\ndisplay off" | dmenu -i -p 'Action: ')" in
	'lock') slock ;;
	"leave $WM") kill -TERM "$(wmpid)" ;;
	"renew $WM") kill -HUP "$(wmpid)" ;;
	'hibernate') slock $ctl hibernate -i ;;
	'sleep') slock $ctl suspend -i ;;
	'reboot') $ctl reboot -i ;;
	'shutdown') $ctl poweroff -i ;;
	'display off') xset dpms force off ;;
	*) exit 1 ;;
esac
EOF
chmod +x ~/.local/bin/sysact

# remaps - keyboard remaps
cat > ~/.local/bin/remaps << 'EOF'
#!/bin/sh

# This script is called on startup to remap keys.
xset r rate 300 50
setxkbmap -option altwin:menu_win,compose:caps
EOF
chmod +x ~/.local/bin/remaps

# dmenuunicode - emoji picker
cat > ~/.local/bin/dmenuunicode << 'EOF'
#!/bin/sh

chosen=$(cut -d ';' -f1 ~/.local/share/larbs/emoji | dmenu -i -l 30 | sed "s/ .*//")
[ -z "$chosen" ] && exit

if [ -n "$1" ]; then
	xdotool type "$chosen"
else
	printf "%s" "$chosen" | xclip -selection clipboard
	notify-send "'$chosen' copied to clipboard." &
fi
EOF
chmod +x ~/.local/bin/dmenuunicode

# dmenurecord - screen recording
cat > ~/.local/bin/dmenurecord << 'EOF'
#!/bin/sh

getdim() { xrandr | grep -oP '(?<=current ).*(?=,)' | tr -d ' ' ;}

updateicon() {
	echo "$1" > /tmp/recordingicon
	pkill -RTMIN+9 "${STATUSBAR:-dwmblocks}"
}

killrecording() {
	recpid="$(cat /tmp/recordingpid)"
	kill -15 "$recpid"
	rm -f /tmp/recordingpid
	updateicon ""
	pkill -RTMIN+9 "${STATUSBAR:-dwmblocks}"
}

screencast() {
	ffmpeg -y \
	-f x11grab \
	-framerate 30 \
	-s "$(getdim)" \
	-i "$DISPLAY" \
	-r 24 \
	-use_wallclock_as_timestamps 1 \
	-f alsa -thread_queue_size 1024 -i default \
	-c:v h264 \
	-crf 0 -preset ultrafast -c:a aac \
	"$HOME/screencast-$(date '+%y%m%d-%H%M-%S').mp4" &
	echo $! > /tmp/recordingpid
	updateicon "REC"
}

video() {
	ffmpeg \
	-f x11grab \
	-framerate 30 \
	-s "$(getdim)" \
	-i "$DISPLAY" \
	-c:v libx264 -qp 0 -r 30 \
	"$HOME/video-$(date '+%y%m%d-%H%M-%S').mkv" &
	echo $! > /tmp/recordingpid
	updateicon "REC"
}

audio() {
	ffmpeg \
	-f alsa -i default \
	-c:a flac \
	"$HOME/audio-$(date '+%y%m%d-%H%M-%S').flac" &
	echo $! > /tmp/recordingpid
	updateicon "MIC"
}

videoselected() {
	slop -f "%x %y %w %h" > /tmp/slop
	read -r X Y W H < /tmp/slop
	rm /tmp/slop
	ffmpeg \
	-f x11grab \
	-framerate 30 \
	-video_size "$W"x"$H" \
	-i :0.0+"$X,$Y" \
	-c:v libx264 -qp 0 -r 30 \
	"$HOME/box-$(date '+%y%m%d-%H%M-%S').mkv" &
	echo $! > /tmp/recordingpid
	updateicon "REC"
}

askrecording() {
	choice=$(printf "screencast\\nvideo\\nvideo selected\\naudio" | dmenu -i -p "Select recording style:")
	case "$choice" in
		screencast) screencast;;
		audio) audio;;
		video) video;;
		*selected) videoselected;;
	esac
}

asktoend() {
	response=$(printf "No\\nYes" | dmenu -i -p "Recording still active. End recording?") &&
	[ "$response" = "Yes" ] && killrecording
}

case "$1" in
	screencast) screencast;;
	audio) audio;;
	video) video;;
	*selected) videoselected;;
	kill) killrecording;;
	*) ([ -f /tmp/recordingpid ] && asktoend && exit) || askrecording;;
esac
EOF
chmod +x ~/.local/bin/dmenurecord

# linkhandler - URL handler
cat > ~/.local/bin/linkhandler << 'EOF'
#!/bin/sh

if [ -z "$1" ]; then
	url="$(xclip -o)"
else
	url="$1"
fi

case "$url" in
	*mkv|*webm|*mp4|*youtube.com/watch*|*youtube.com/playlist*|*youtube.com/shorts*|*youtu.be*|*odysee.com*)
		setsid -f mpv -quiet "$url" >/dev/null 2>&1 ;;
	*png|*jpg|*jpe|*jpeg|*gif|*webp)
		curl -sL "$url" > "/tmp/$(echo "$url" | sed "s/.*\///;s/%20/ /g")" && nsxiv -a "/tmp/$(echo "$url" | sed "s/.*\///;s/%20/ /g")" >/dev/null 2>&1 & ;;
	*pdf|*cbz|*cbr)
		curl -sL "$url" > "/tmp/$(echo "$url" | sed "s/.*\///;s/%20/ /g")" && zathura "/tmp/$(echo "$url" | sed "s/.*\///;s/%20/ /g")" >/dev/null 2>&1 & ;;
	*mp3|*flac|*opus|*mp3?source*)
		curl -LO "$url" >/dev/null 2>&1 ;;
	*)
		[ -f "$url" ] && setsid -f "$TERMINAL" -e "$EDITOR" "$url" >/dev/null 2>&1 || setsid -f "$BROWSER" "$url" >/dev/null 2>&1
esac
EOF
chmod +x ~/.local/bin/linkhandler

# Create LARBS data directory and download emoji file
info "Setting up emoji data for dmenuunicode..."
mkdir -p ~/.local/share/larbs
curl -sL "https://raw.githubusercontent.com/LukeSmithxyz/voidrice/master/.local/share/larbs/emoji" -o ~/.local/share/larbs/emoji

# ============================================================================
# PHASE 10: Configure Neovim (full config mirroring local setup)
# ============================================================================
info "Setting up Neovim..."

mkdir -p ~/.config/nvim/lua/config
mkdir -p ~/.config/nvim/lua/plugins

# init.lua
cat > ~/.config/nvim/init.lua << 'EOF'
-- Ensure nvm node/npm are in PATH (before system ones)
local nvm_node = vim.fn.expand("~/.config/nvm/versions/node/v20.19.1/bin")
if vim.fn.isdirectory(nvm_node) == 1 then
  vim.env.PATH = nvm_node .. ":" .. vim.env.PATH
end

-- Bootstrap lazy.nvim
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not vim.loop.fs_stat(lazypath) then
  vim.fn.system({
    "git",
    "clone",
    "--filter=blob:none",
    "https://github.com/folke/lazy.nvim.git",
    "--branch=stable",
    lazypath,
  })
end
vim.opt.rtp:prepend(lazypath)

-- Set leader before lazy so mappings are correct
vim.g.mapleader = ","
vim.g.maplocalleader = ","

-- Load config modules
require("config.options")
require("config.keymaps")
require("config.autocmds")
require("config.lazy")
EOF

# config/options.lua
cat > ~/.config/nvim/lua/config/options.lua << 'EOF'
local opt = vim.opt

-- General
opt.mouse = "a"
opt.clipboard = "unnamedplus"
opt.encoding = "utf-8"
opt.title = true

-- UI
opt.number = true
opt.relativenumber = true
opt.background = "dark"
opt.showmode = false
opt.ruler = false
opt.laststatus = 0
opt.showcmd = false
opt.hlsearch = false
opt.termguicolors = true
opt.signcolumn = "yes"
opt.cursorline = true

-- Splits
opt.splitbelow = true
opt.splitright = true

-- Tabs and indentation
opt.tabstop = 2
opt.shiftwidth = 2
opt.expandtab = true
opt.smartindent = true

-- Search
opt.ignorecase = true
opt.smartcase = true

-- Completion
opt.wildmode = { "longest", "list", "full" }
opt.completeopt = { "menu", "menuone", "noselect" }

-- Files
opt.swapfile = false
opt.undofile = true

-- Performance
opt.updatetime = 250
opt.timeoutlen = 300
EOF

# config/keymaps.lua
cat > ~/.config/nvim/lua/config/keymaps.lua << 'EOF'
local map = vim.keymap.set

-- Split navigation (Ctrl+hjkl)
map("n", "<C-h>", "<C-w>h", { desc = "Move to left split" })
map("n", "<C-j>", "<C-w>j", { desc = "Move to below split" })
map("n", "<C-k>", "<C-w>k", { desc = "Move to above split" })
map("n", "<C-l>", "<C-w>l", { desc = "Move to right split" })

-- Don't yank on change
map("n", "c", '"_c', { desc = "Change without yanking" })

-- Perform dot commands over visual blocks
map("v", ".", ":normal .<CR>", { desc = "Dot command over selection" })

-- Replace ex mode with gq
map("n", "Q", "gq", { desc = "Format text" })

-- Replace all aliased to S
map("n", "S", ":%s//g<Left><Left>", { desc = "Search and replace" })

-- Spell check toggle
map("n", "<leader>o", ":setlocal spell! spelllang=en_us<CR>", { desc = "Toggle spell check" })

-- Shellcheck current file
map("n", "<leader>s", ":!clear && shellcheck -x %<CR>", { desc = "Run shellcheck" })

-- Save as sudo
vim.cmd([[cabbrev w!! execute 'silent! write !sudo tee % >/dev/null' <bar> edit!]])

-- Placeholder navigation (,, jumps to next <++>)
map("n", ",,", ":keepp /<++><CR>ca<", { desc = "Jump to placeholder" })
map("i", ",,", "<Esc>:keepp /<++><CR>ca<", { desc = "Jump to placeholder" })
EOF

# config/autocmds.lua
cat > ~/.config/nvim/lua/config/autocmds.lua << 'EOF'
local augroup = vim.api.nvim_create_augroup
local autocmd = vim.api.nvim_create_autocmd

-- Disable auto-commenting on newline
autocmd("FileType", {
  group = augroup("DisableAutoComment", { clear = true }),
  pattern = "*",
  callback = function()
    vim.opt_local.formatoptions:remove({ "c", "r", "o" })
  end,
})

-- Trim trailing whitespace on save
autocmd("BufWritePre", {
  group = augroup("TrimWhitespace", { clear = true }),
  pattern = "*",
  callback = function()
    local pos = vim.api.nvim_win_get_cursor(0)
    vim.cmd([[%s/\s\+$//e]])
    vim.cmd([[%s/\n\+\%$//e]])
    pcall(vim.api.nvim_win_set_cursor, 0, pos)
  end,
})

-- Add trailing newline for C files (ANSI C standard)
autocmd("BufWritePre", {
  group = augroup("CTrailingNewline", { clear = true }),
  pattern = { "*.c", "*.h" },
  callback = function()
    local last_line = vim.fn.getline("$")
    if last_line ~= "" then
      vim.fn.append("$", "")
    end
  end,
})

-- Filetype detection
autocmd({ "BufRead", "BufNewFile" }, {
  group = augroup("FiletypeDetect", { clear = true }),
  pattern = { "*.ms", "*.me", "*.mom", "*.man" },
  callback = function()
    vim.bo.filetype = "groff"
  end,
})

autocmd({ "BufRead", "BufNewFile" }, {
  group = augroup("XresourcesFiletype", { clear = true }),
  pattern = { "Xresources", "Xdefaults", "xresources", "xdefaults" },
  callback = function()
    vim.bo.filetype = "xdefaults"
  end,
})

-- Highlight on yank
autocmd("TextYankPost", {
  group = augroup("HighlightYank", { clear = true }),
  callback = function()
    vim.highlight.on_yank({ timeout = 200 })
  end,
})

-- Resize splits on window resize
autocmd("VimResized", {
  group = augroup("ResizeSplits", { clear = true }),
  callback = function()
    vim.cmd("tabdo wincmd =")
  end,
})
EOF

# config/lazy.lua
cat > ~/.config/nvim/lua/config/lazy.lua << 'EOF'
require("lazy").setup({
  spec = {
    { import = "plugins" },
  },
  defaults = {
    lazy = false,
  },
  install = {
    colorscheme = { "gruvbox", "habamax" },
  },
  checker = {
    enabled = true,
    notify = false,
  },
  change_detection = {
    notify = false,
  },
  performance = {
    rtp = {
      disabled_plugins = {
        "gzip",
        "tarPlugin",
        "tohtml",
        "tutor",
        "zipPlugin",
      },
    },
  },
})
EOF

# plugins/colorscheme.lua
cat > ~/.config/nvim/lua/plugins/colorscheme.lua << 'EOF'
return {
  {
    "ellisonleao/gruvbox.nvim",
    lazy = false,
    priority = 1000,
    config = function()
      require("gruvbox").setup({
        terminal_colors = true,
        undercurl = true,
        underline = true,
        bold = true,
        italic = {
          strings = false,
          emphasis = true,
          comments = true,
          operators = false,
          folds = true,
        },
        strikethrough = true,
        invert_selection = false,
        invert_signs = false,
        invert_tabline = false,
        invert_intend_guides = false,
        inverse = true,
        contrast = "hard",
        palette_overrides = {},
        overrides = {
          SignColumn = { bg = "#1d2021" },
          GruvboxRedSign = { fg = "#fb4934", bg = "#1d2021" },
          GruvboxGreenSign = { fg = "#b8bb26", bg = "#1d2021" },
          GruvboxYellowSign = { fg = "#fabd2f", bg = "#1d2021" },
          GruvboxBlueSign = { fg = "#83a598", bg = "#1d2021" },
          GruvboxPurpleSign = { fg = "#d3869b", bg = "#1d2021" },
          GruvboxAquaSign = { fg = "#8ec07c", bg = "#1d2021" },
          GruvboxOrangeSign = { fg = "#fe8019", bg = "#1d2021" },
          LineNr = { fg = "#8a7c71" },
          CursorLineNr = { fg = "#fabd2f" },
          GitSignsAdd = { fg = "#b8bb26", bg = "#1d2021" },
          GitSignsChange = { fg = "#83a598", bg = "#1d2021" },
          GitSignsDelete = { fg = "#fb4934", bg = "#1d2021" },
          DiagnosticError = { fg = "#cc241d" },
          DiagnosticWarn = { fg = "#d79921" },
          DiagnosticInfo = { fg = "#458588" },
          DiagnosticHint = { fg = "#8ec07c" },
          TelescopeBorder = { fg = "#3c3836" },
          TelescopePromptBorder = { fg = "#3c3836" },
          TelescopeResultsBorder = { fg = "#3c3836" },
          TelescopePreviewBorder = { fg = "#3c3836" },
          NvimTreeNormal = { bg = "#1d2021" },
          NvimTreeFolderIcon = { fg = "#83a598" },
          NvimTreeFolderName = { fg = "#83a598" },
          NvimTreeOpenedFolderName = { fg = "#8ec07c" },
          StatusLine = { bg = "#1d2021", fg = "#ebdbb2" },
          StatusLineNC = { bg = "#1d2021", fg = "#928374" },
          NormalFloat = { bg = "#1d2021" },
          FloatBorder = { fg = "#3c3836", bg = "#1d2021" },
          Pmenu = { bg = "#1d2021", fg = "#ebdbb2" },
          PmenuSel = { bg = "#3c3836", fg = "#8ec07c" },
          PmenuSbar = { bg = "#3c3836" },
          PmenuThumb = { bg = "#689d6a" },
          DiffAdd = { bg = "#3d4220" },
          DiffDelete = { bg = "#4c2a2a" },
          DiffChange = { bg = "#2e3b3b" },
          DiffText = { bg = "#4d4426" },
        },
        dim_inactive = false,
        transparent_mode = false,
      })
      vim.o.background = "dark"
      vim.cmd.colorscheme("gruvbox")
    end,
  },
}
EOF

# plugins/lsp.lua
cat > ~/.config/nvim/lua/plugins/lsp.lua << 'EOF'
return {
  {
    "williamboman/mason.nvim",
    cmd = "Mason",
    build = ":MasonUpdate",
    config = function()
      require("mason").setup()
    end,
  },
  {
    "neovim/nvim-lspconfig",
    event = { "BufReadPre", "BufNewFile" },
    dependencies = {
      "williamboman/mason.nvim",
      "williamboman/mason-lspconfig.nvim",
      "hrsh7th/cmp-nvim-lsp",
    },
    config = function()
      local lspconfig = require("lspconfig")
      local cmp_nvim_lsp = require("cmp_nvim_lsp")
      local capabilities = cmp_nvim_lsp.default_capabilities()
      require("mason-lspconfig").setup({
        ensure_installed = { "lua_ls", "ts_ls", "gopls", "pyright" },
        automatic_installation = true,
        handlers = {
          function(server_name)
            lspconfig[server_name].setup({ capabilities = capabilities })
          end,
          ["lua_ls"] = function()
            lspconfig.lua_ls.setup({
              capabilities = capabilities,
              settings = {
                Lua = {
                  diagnostics = { globals = { "vim" } },
                  workspace = { library = vim.api.nvim_get_runtime_file("", true), checkThirdParty = false },
                  telemetry = { enable = false },
                },
              },
            })
          end,
        },
      })
      vim.api.nvim_create_autocmd("LspAttach", {
        group = vim.api.nvim_create_augroup("UserLspConfig", { clear = true }),
        callback = function(ev)
          local opts = { buffer = ev.buf, silent = true }
          local map = vim.keymap.set
          map("n", "gD", vim.lsp.buf.declaration, opts)
          map("n", "gd", vim.lsp.buf.definition, opts)
          map("n", "K", vim.lsp.buf.hover, opts)
          map("n", "gi", vim.lsp.buf.implementation, opts)
          map("n", "<C-k>", vim.lsp.buf.signature_help, opts)
          map("n", "<leader>D", vim.lsp.buf.type_definition, opts)
          map("n", "<leader>rn", vim.lsp.buf.rename, opts)
          map({ "n", "v" }, "<leader>ca", vim.lsp.buf.code_action, opts)
          map("n", "gr", vim.lsp.buf.references, opts)
          map("n", "<leader>ld", vim.diagnostic.open_float, opts)
          map("n", "[d", vim.diagnostic.goto_prev, opts)
          map("n", "]d", vim.diagnostic.goto_next, opts)
          map("n", "<leader>q", vim.diagnostic.setloclist, opts)
          map("n", "<leader>lf", function() vim.lsp.buf.format({ async = true }) end, opts)
        end,
      })
    end,
  },
  {
    "hrsh7th/nvim-cmp",
    event = "InsertEnter",
    dependencies = {
      "hrsh7th/cmp-nvim-lsp",
      "hrsh7th/cmp-buffer",
      "hrsh7th/cmp-path",
      "hrsh7th/cmp-cmdline",
      "L3MON4D3/LuaSnip",
      "saadparwaiz1/cmp_luasnip",
      "rafamadriz/friendly-snippets",
    },
    config = function()
      local cmp = require("cmp")
      local luasnip = require("luasnip")
      require("luasnip.loaders.from_vscode").lazy_load()
      cmp.setup({
        snippet = { expand = function(args) luasnip.lsp_expand(args.body) end },
        mapping = cmp.mapping.preset.insert({
          ["<C-b>"] = cmp.mapping.scroll_docs(-4),
          ["<C-f>"] = cmp.mapping.scroll_docs(4),
          ["<C-Space>"] = cmp.mapping.complete(),
          ["<C-e>"] = cmp.mapping.abort(),
          ["<CR>"] = cmp.mapping.confirm({ select = true }),
          ["<Tab>"] = cmp.mapping(function(fallback)
            if cmp.visible() then cmp.select_next_item()
            elseif luasnip.expand_or_jumpable() then luasnip.expand_or_jump()
            else fallback() end
          end, { "i", "s" }),
          ["<S-Tab>"] = cmp.mapping(function(fallback)
            if cmp.visible() then cmp.select_prev_item()
            elseif luasnip.jumpable(-1) then luasnip.jump(-1)
            else fallback() end
          end, { "i", "s" }),
        }),
        sources = cmp.config.sources({
          { name = "nvim_lsp" },
          { name = "luasnip" },
          { name = "buffer" },
          { name = "path" },
        }),
      })
      cmp.setup.cmdline(":", {
        mapping = cmp.mapping.preset.cmdline(),
        sources = cmp.config.sources({ { name = "path" } }, { { name = "cmdline" } }),
      })
    end,
  },
}
EOF

# plugins/ui.lua
cat > ~/.config/nvim/lua/plugins/ui.lua << 'EOF'
return {
  {
    "nvim-tree/nvim-tree.lua",
    dependencies = { "nvim-tree/nvim-web-devicons" },
    keys = {
      { "<leader>n", "<cmd>NvimTreeToggle<cr>", desc = "Toggle file tree" },
      { "<leader>e", "<cmd>NvimTreeFocus<cr>", desc = "Focus file tree" },
      { "<leader>tc", "<cmd>NvimTreeToggle<cr>", desc = "Toggle file tree" },
    },
    config = function()
      vim.g.loaded_netrw = 1
      vim.g.loaded_netrwPlugin = 1
      require("nvim-tree").setup({
        view = { width = 30 },
        renderer = { group_empty = true },
        filters = { dotfiles = false, custom = { ".claude", "CLAUDE.md", ".claude-plugin" } },
        git = { enable = true, ignore = false },
      })
    end,
  },
  {
    "nvim-lualine/lualine.nvim",
    dependencies = { "nvim-tree/nvim-web-devicons" },
    event = "VeryLazy",
    config = function()
      require("lualine").setup({
        options = {
          theme = "gruvbox",
          component_separators = { left = "", right = "" },
          section_separators = { left = "", right = "" },
        },
        sections = {
          lualine_a = { "mode" },
          lualine_b = { "branch", "diff", "diagnostics" },
          lualine_c = { "filename" },
          lualine_x = { "encoding", "fileformat", "filetype" },
          lualine_y = { "progress" },
          lualine_z = { "location" },
        },
      })
    end,
  },
  { "folke/which-key.nvim", event = "VeryLazy", config = function() require("which-key").setup({}) end },
  {
    "lukas-reineke/indent-blankline.nvim",
    main = "ibl",
    event = { "BufReadPost", "BufNewFile" },
    config = function()
      require("ibl").setup({ indent = { char = "|" }, scope = { enabled = true } })
    end,
  },
  {
    "folke/zen-mode.nvim",
    cmd = "ZenMode",
    keys = { { "<leader>f", "<cmd>ZenMode<cr>", desc = "Toggle zen mode" } },
    config = function() require("zen-mode").setup({ window = { width = 80 } }) end,
  },
}
EOF

# plugins/telescope.lua
cat > ~/.config/nvim/lua/plugins/telescope.lua << 'EOF'
return {
  {
    "nvim-telescope/telescope.nvim",
    branch = "0.1.x",
    dependencies = {
      "nvim-lua/plenary.nvim",
      { "nvim-telescope/telescope-fzf-native.nvim", build = "make" },
    },
    cmd = "Telescope",
    keys = {
      { "<leader>ff", "<cmd>Telescope find_files<cr>", desc = "Find files" },
      { "<leader>fg", "<cmd>Telescope live_grep<cr>", desc = "Live grep" },
      { "<leader>fb", "<cmd>Telescope buffers<cr>", desc = "Buffers" },
      { "<leader>fh", "<cmd>Telescope help_tags<cr>", desc = "Help tags" },
      { "<leader>fr", "<cmd>Telescope oldfiles<cr>", desc = "Recent files" },
      { "<leader>fc", "<cmd>Telescope git_commits<cr>", desc = "Git commits" },
      { "<leader>fs", "<cmd>Telescope git_status<cr>", desc = "Git status" },
      { "<leader>fd", "<cmd>Telescope diagnostics<cr>", desc = "Diagnostics" },
      { "<leader><space>", "<cmd>Telescope buffers<cr>", desc = "Buffers" },
    },
    config = function()
      local telescope = require("telescope")
      local actions = require("telescope.actions")
      telescope.setup({
        defaults = {
          path_display = { "truncate" },
          mappings = {
            i = {
              ["<C-j>"] = actions.move_selection_next,
              ["<C-k>"] = actions.move_selection_previous,
              ["<C-q>"] = actions.send_selected_to_qflist + actions.open_qflist,
            },
          },
        },
        pickers = {
          find_files = { hidden = true, file_ignore_patterns = { ".git/", "node_modules/" } },
        },
      })
      telescope.load_extension("fzf")
    end,
  },
}
EOF

# plugins/treesitter.lua
cat > ~/.config/nvim/lua/plugins/treesitter.lua << 'EOF'
return {
  {
    "nvim-treesitter/nvim-treesitter",
    build = ":TSUpdate",
    event = { "BufReadPost", "BufNewFile" },
    dependencies = { "nvim-treesitter/nvim-treesitter-textobjects" },
    config = function()
      require("nvim-treesitter.configs").setup({
        ensure_installed = {
          "bash", "c", "css", "go", "html", "javascript", "json", "lua",
          "markdown", "markdown_inline", "python", "rust", "tsx", "typescript", "vim", "vimdoc", "yaml",
        },
        auto_install = true,
        highlight = { enable = true, additional_vim_regex_highlighting = false },
        indent = { enable = true },
        textobjects = {
          select = {
            enable = true,
            lookahead = true,
            keymaps = { ["af"] = "@function.outer", ["if"] = "@function.inner", ["ac"] = "@class.outer", ["ic"] = "@class.inner" },
          },
          move = {
            enable = true,
            set_jumps = true,
            goto_next_start = { ["]m"] = "@function.outer", ["]]"] = "@class.outer" },
            goto_prev_start = { ["[m"] = "@function.outer", ["[["] = "@class.outer" },
          },
        },
      })
    end,
  },
}
EOF

# plugins/git.lua
cat > ~/.config/nvim/lua/plugins/git.lua << 'EOF'
return {
  {
    "lewis6991/gitsigns.nvim",
    event = { "BufReadPre", "BufNewFile" },
    config = function()
      require("gitsigns").setup({
        signs = {
          add = { text = "+" },
          change = { text = "~" },
          delete = { text = "_" },
          topdelete = { text = "-" },
          changedelete = { text = "~" },
        },
        current_line_blame = false,
        on_attach = function(bufnr)
          local gs = package.loaded.gitsigns
          local map = vim.keymap.set
          local function opts(desc) return { buffer = bufnr, desc = desc } end
          map("n", "]c", function()
            if vim.wo.diff then return "]c" end
            vim.schedule(function() gs.next_hunk() end)
            return "<Ignore>"
          end, { expr = true, buffer = bufnr, desc = "Next hunk" })
          map("n", "[c", function()
            if vim.wo.diff then return "[c" end
            vim.schedule(function() gs.prev_hunk() end)
            return "<Ignore>"
          end, { expr = true, buffer = bufnr, desc = "Prev hunk" })
          map("n", "<leader>hs", gs.stage_hunk, opts("Stage hunk"))
          map("n", "<leader>hr", gs.reset_hunk, opts("Reset hunk"))
          map("v", "<leader>hs", function() gs.stage_hunk({ vim.fn.line("."), vim.fn.line("v") }) end, opts("Stage hunk"))
          map("v", "<leader>hr", function() gs.reset_hunk({ vim.fn.line("."), vim.fn.line("v") }) end, opts("Reset hunk"))
          map("n", "<leader>hS", gs.stage_buffer, opts("Stage buffer"))
          map("n", "<leader>hu", gs.undo_stage_hunk, opts("Undo stage hunk"))
          map("n", "<leader>hR", gs.reset_buffer, opts("Reset buffer"))
          map("n", "<leader>hp", gs.preview_hunk, opts("Preview hunk"))
          map("n", "<leader>hb", function() gs.blame_line({ full = true }) end, opts("Blame line"))
          map("n", "<leader>tb", gs.toggle_current_line_blame, opts("Toggle blame"))
          map("n", "<leader>hd", gs.diffthis, opts("Diff this"))
          map("n", "<leader>hD", function() gs.diffthis("~") end, opts("Diff this ~"))
          map("n", "<leader>td", gs.toggle_deleted, opts("Toggle deleted"))
        end,
      })
    end,
  },
  {
    "tpope/vim-fugitive",
    cmd = { "Git", "G", "Gdiffsplit", "Gread", "Gwrite", "Ggrep", "GMove", "GDelete", "GBrowse" },
    keys = {
      { "<leader>gs", "<cmd>Git<cr>", desc = "Git status" },
      { "<leader>gc", "<cmd>Git commit<cr>", desc = "Git commit" },
      { "<leader>gp", "<cmd>Git push<cr>", desc = "Git push" },
      { "<leader>gl", "<cmd>Git pull<cr>", desc = "Git pull" },
      { "<leader>gb", "<cmd>Git blame<cr>", desc = "Git blame" },
      { "<leader>gd", "<cmd>Gdiffsplit<cr>", desc = "Git diff" },
    },
  },
}
EOF

# plugins/editing.lua
cat > ~/.config/nvim/lua/plugins/editing.lua << 'EOF'
return {
  { "kylechui/nvim-surround", version = "*", event = "VeryLazy", config = function() require("nvim-surround").setup({}) end },
  { "numToStr/Comment.nvim", event = { "BufReadPost", "BufNewFile" }, config = function() require("Comment").setup() end },
  {
    "windwp/nvim-autopairs",
    event = "InsertEnter",
    config = function()
      require("nvim-autopairs").setup({})
      local cmp_autopairs = require("nvim-autopairs.completion.cmp")
      local cmp = require("cmp")
      cmp.event:on("confirm_done", cmp_autopairs.on_confirm_done())
    end,
  },
  {
    "NvChad/nvim-colorizer.lua",
    event = { "BufReadPost", "BufNewFile" },
    config = function()
      require("colorizer").setup({
        filetypes = { "*" },
        user_default_options = { css = true, css_fn = true, mode = "background", tailwind = false, virtualtext = "~" },
      })
    end,
  },
  { "chaoren/vim-wordmotion", event = { "BufReadPost", "BufNewFile" } },
}
EOF

# plugins/claudecode.lua
cat > ~/.config/nvim/lua/plugins/claudecode.lua << 'EOF'
return {
  {
    "coder/claudecode.nvim",
    dependencies = { "folke/snacks.nvim" },
    config = true,
    keys = {
      { "<leader>ac", "<cmd>ClaudeCode<cr>", desc = "Toggle Claude" },
      { "<leader>af", "<cmd>ClaudeCodeFocus<cr>", desc = "Focus Claude" },
      { "<leader>as", "<cmd>ClaudeCodeSend<cr>", mode = "v", desc = "Send to Claude" },
    },
  },
}
EOF

# ============================================================================
# PHASE 11: Set default shell to zsh
# ============================================================================
info "Setting zsh as default shell..."
if [ "$SHELL" != "/bin/zsh" ]; then
    chsh -s /bin/zsh
fi

# ============================================================================
# PHASE 12: Create dwm session for display managers
# ============================================================================
info "Creating dwm desktop session..."

sudo tee /usr/share/xsessions/dwm.desktop > /dev/null << 'EOF'
[Desktop Entry]
Encoding=UTF-8
Name=dwm
Comment=Dynamic window manager
Exec=/usr/local/bin/dwm
Icon=dwm
Type=XSession
EOF

# ============================================================================
# Done
# ============================================================================
echo ""
info "Setup complete!"
echo ""
echo "Next steps:"
echo "  1. Log out of GNOME"
echo "  2. At the login screen, click the gear icon and select 'dwm'"
echo "  3. Log in - you'll be in dwm"
echo ""
echo "Or, from a TTY (Ctrl+Alt+F2):"
echo "  1. Log in"
echo "  2. Run 'startx' to start dwm"
echo ""
echo "Key bindings in dwm (Mod key is Super/Windows key):"
echo "  Mod+Enter     - Open terminal (alacritty)"
echo "  Mod+d         - Open dmenu"
echo "  Mod+j/k       - Focus windows"
echo "  Mod+Shift+c   - Close window"
echo "  Mod+Shift+q   - Quit dwm"
echo "  Mod+1-9       - Switch workspaces"
echo ""
echo "Log file: $LOGFILE"
