#!/usr/bin/env bash
set -euo pipefail

log() { printf "\n==> %s\n" "$*"; }
have() { command -v "$1" >/dev/null 2>&1; }

OS="$(uname -s)"
PLATFORM=""

# -------- OS detection --------
if [[ "$OS" == "Darwin" ]]; then
	PLATFORM="macos"
elif [[ "$OS" == "FreeBSD" ]]; then
	PLATFORM="freebsd"
elif [[ "$OS" == "Linux" ]]; then
	if [[ -r /etc/os-release ]]; then
		# shellcheck disable=SC1091
		. /etc/os-release
	fi

	is_arch=0
	case "${ID:-}" in
	arch | endeavouros) is_arch=1 ;;
	esac
	if [[ $is_arch -eq 0 && -n "${ID_LIKE:-}" ]] && echo "$ID_LIKE" | grep -qi arch; then
		is_arch=1
	fi

	is_fedora=0
	case "${ID:-}" in
	fedora) is_fedora=1 ;;
	esac
	if [[ $is_fedora -eq 0 && -n "${ID_LIKE:-}" ]] && echo "$ID_LIKE" | grep -qiE 'fedora|rhel'; then
		is_fedora=1
	fi

	if [[ $is_arch -eq 1 ]]; then
		PLATFORM="arch"
	elif [[ $is_fedora -eq 1 ]]; then
		PLATFORM="fedora"
	else
		echo "Unsupported Linux distro (ID=${ID:-unknown}, ID_LIKE=${ID_LIKE:-unknown})."
		exit 1
	fi
else
	echo "Unsupported OS: $OS"
	exit 1
fi

# -------- Helpers --------
install_pacman() {
	local pkgs=("$@")
	log "pacman install: ${pkgs[*]}"
	sudo pacman -Sy --needed --noconfirm "${pkgs[@]}"
}

install_dnf() {
	local pkgs=("$@")
	log "dnf install: ${pkgs[*]}"
	sudo dnf install -y "${pkgs[@]}"
}

brew_install() {
	local pkgs=("$@")
	log "brew install: ${pkgs[*]}"
	brew install "${pkgs[@]}"
}

brew_cask() {
	local pkgs=("$@")
	log "brew install --cask: ${pkgs[*]}"
	brew install --cask "${pkgs[@]}"
}

install_pkg() {
	local pkgs=("$@")
	log "pkg install: ${pkgs[*]}"
	sudo pkg install -y "${pkgs[@]}"
}

# Best-effort install loops (skip missing packages cleanly)
dnf_install_best_effort() {
	local pkgs=("$@")
	for p in "${pkgs[@]}"; do
		if sudo dnf info "$p" >/dev/null 2>&1; then
			install_dnf "$p"
		else
			log "Skipping (dnf not found): $p"
		fi
	done
}

pacman_install_best_effort() {
	local pkgs=("$@")
	for p in "${pkgs[@]}"; do
		if pacman -Si "$p" >/dev/null 2>&1; then
			install_pacman "$p"
		else
			log "Skipping (pacman not found): $p"
		fi
	done
}

pkg_install_best_effort() {
	local pkgs=("$@")
	for p in "${pkgs[@]}"; do
		if pkg search -q "^${p}$" >/dev/null 2>&1; then
			install_pkg "$p"
		else
			log "Skipping (pkg not found): $p"
		fi
	done
}

aur_install_if_possible() {
	local pkgs=("$@")
	if have yay; then
		log "AUR install via yay: ${pkgs[*]}"
		yay -S --needed --noconfirm "${pkgs[@]}"
	else
		log "Skipping AUR packages (yay not found): ${pkgs[*]}"
	fi
}

install_opencode() {
	if have opencode; then
		log "opencode already installed"
		return 0
	fi
	if have npm; then
		log "Installing opencode via npm..."
		npm install -g opencode-ai
	else
		log "Skipping opencode (npm not found)"
	fi
}

ensure_brew() {
	if have brew; then return 0; fi
	log "Homebrew not found; installing Homebrew..."
	/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

	if [[ -x /opt/homebrew/bin/brew ]]; then
		eval "$(/opt/homebrew/bin/brew shellenv)"
	elif [[ -x /usr/local/bin/brew ]]; then
		eval "$(/usr/local/bin/brew shellenv)"
	fi
}

ensure_flathub() {
	if ! have flatpak; then
		log "flatpak not installed; skipping flathub apps."
		return 0
	fi
	log "Ensuring Flathub remote exists..."
	sudo flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
}

# -------- Package sets (portable intent) --------
EMACS_PKG="emacs"

# Required by you:
CORE_CLI=(fzf direnv stow pass just)

# Plus from your history / common tooling:
EXTRA_CLI=(fd git)

DEV_TOOLS_LINUX=(cmake libtool make gcc gcc-c++ emacs)
UTILS_LINUX=(gnuplot graphviz shfmt shellcheck pandoc)

DESKTOP_LINUX=(kitty alacritty dino syncthing)

FEDORA_EXTRAS=(
	gnome-extensions-app
	gnome-tweaks
	spice-vdagent
	kernel-modules-extra
	pinentry-tty
	NetworkManager-openvpn-gnome
	openvpn
	openvpn3-client
	libpq-devel
	postgresql
	pass-otp
	chromium
	google-chrome-stable
)

ARCH_EXTRAS=(
	gnome-extensions-app
	gnome-tweaks
	spice-vdagent
	linux-headers
	pinentry
	networkmanager-openvpn
	openvpn
	postgresql-libs
	postgresql
	pass-otp
	chromium
	snapcast
)

MAC_BREW_PKGS=(
	fzf direnv stow pass just
	fd editorconfig git
	cmake libtool
	gnuplot graphviz shfmt shellcheck pandoc
	postgresql
	syncthing
	pinentry-mac
	emacs
)

MAC_CASKS=(
	kitty
	alacritty
	slack
	google-chrome
	chromium
	emacs-app
)

# FreeBSD name mapping (best-effort)
# Notes:
# - "just" is typically "just" on FreeBSD pkg.
# - "stow" is "stow".
# - "pass" is often "password-store".
# - fd is "fd-find".
# - shellcheck/shfmt exist.
# - direnv exists.
FREEBSD_CORE=(fzf direnv stow just password-store)
FREEBSD_EXTRA=(fd-find editorconfig-core-c git)
FREEBSD_DEV=(cmake libtool gmake llvm emacs) # gmake instead of make; llvm as a sane default toolchain
FREEBSD_UTILS=(gnuplot graphviz shfmt shellcheck pandoc)
FREEBSD_SECURITY=(gnupg pinentry) # helpful for pass
FREEBSD_MISC=(postgresql16-client syncthing)

# -------- Install per-platform --------
case "$PLATFORM" in
fedora)
	log "Platform: Fedora. Refreshing + upgrading..."
	sudo dnf -y upgrade --refresh || true

	install_dnf "${CORE_CLI[@]}" "${EXTRA_CLI[@]}" || true
	dnf_install_best_effort "${DEV_TOOLS_LINUX[@]}"
	dnf_install_best_effort "${UTILS_LINUX[@]}"
	dnf_install_best_effort "${DESKTOP_LINUX[@]}"
	dnf_install_best_effort "${FEDORA_EXTRAS[@]}"

	ensure_flathub
	if have flatpak; then
		log "Optional: Slack via Flatpak"
		sudo flatpak install -y flathub com.slack.Slack || true
	fi

	install_opencode

	log "Final system upgrade..."
	sudo dnf -y upgrade
	;;

arch)
	log "Platform: EndeavourOS/Arch. Updating package databases..."
	sudo pacman -Sy --noconfirm

	install_pacman "${CORE_CLI[@]}" "${EXTRA_CLI[@]}"
	pacman_install_best_effort "${DEV_TOOLS_LINUX[@]}"
	pacman_install_best_effort "${UTILS_LINUX[@]}"
	pacman_install_best_effort "${DESKTOP_LINUX[@]}"
	pacman_install_best_effort "${ARCH_EXTRAS[@]}"

	aur_install_if_possible google-chrome slack-desktop || true

	log "Final system upgrade..."
	sudo pacman -Syu --noconfirm

	install_opencode
	;;

macos)
	log "Platform: macOS. Ensuring Homebrew..."
	ensure_brew

	log "Updating Homebrew..."
	brew update

	brew_install "${MAC_BREW_PKGS[@]}"
	brew_cask "${MAC_CASKS[@]}" || true

	if [[ -f "$(brew --prefix)/opt/fzf/install" ]]; then
		log "Tip: run fzf install helper if you want keybindings/completion:"
		echo "  $(brew --prefix)/opt/fzf/install"
	fi

	install_opencode

	log "Final system upgrade..."
	brew upgrade
	;;

freebsd)
	log "Platform: FreeBSD. Updating pkg metadata..."
	sudo pkg update -f

	# Ensure basic SSL certs exist for fetches/tools that need it
	pkg_install_best_effort ca_root_nss || true

	# Core CLI tools you asked for
	pkg_install_best_effort "${FREEBSD_CORE[@]}"

	# Extras + dev + utilities
	pkg_install_best_effort "${FREEBSD_EXTRA[@]}"
	pkg_install_best_effort "${FREEBSD_DEV[@]}"
	pkg_install_best_effort "${FREEBSD_UTILS[@]}"

	# pass needs gpg + pinentry
	pkg_install_best_effort "${FREEBSD_SECURITY[@]}"

	# Optional stuff from your history where it makes sense
	pkg_install_best_effort "${FREEBSD_MISC[@]}"

	log "Final system upgrade..."
	sudo pkg upgrade -y

	log "FreeBSD notes:"
	cat <<'EOF'
- 'pass' is installed as 'password-store' on FreeBSD; command is still: pass
- Build tools often use gmake (GNU make). If you compile from source, try gmake.
- GUI apps (kitty/alacritty/slack/chrome) are not installed here by default.
EOF
	;;
esac

# -------- Post-install notes --------
log "Post-install reminders"
cat <<'EOF'
- direnv (bash):
    eval "$(direnv hook bash)"
  (zsh uses: eval "$(direnv hook zsh)")

- pass needs a GPG key:
    gpg --full-generate-key
    pass init "<YOUR-GPG-KEY-ID>"

- stow for dotfiles:
    mkdir -p ~/dotfiles
    # stow <package>
EOF

log "Done."

# -------- Doom Emacs (requires emacs binary) --------
if ! have emacs; then
	log "WARNING: emacs binary not found in PATH — skipping Doom Emacs installation."
	log "Install emacs via your package manager and re-run this script, or run:"
	log "  ~/.emacs.d/bin/doom install"
else
	DOOM_DIR="${DOOM_DIR:-$HOME/.emacs.d}"
	if [[ -d "$DOOM_DIR/.git" ]]; then
		log "Doom Emacs already present at $DOOM_DIR (updating)..."
		git -C "$DOOM_DIR" pull --rebase || true
	elif [[ -e "$DOOM_DIR" ]]; then
		log "Skipping Doom Emacs clone because $DOOM_DIR exists but is not a git repo."
		log "Move it aside if you want to install Doom there."
	else
		log "Cloning Doom Emacs to $DOOM_DIR..."
		git clone --depth=1 https://github.com/doomemacs/doomemacs "$DOOM_DIR"
	fi

	if [[ -d "$DOOM_DIR" ]]; then
		log "Installing Doom Emacs..."
		"$DOOM_DIR/bin/doom" install
	fi
fi

# -------- asdf plugins --------
if have asdf; then
	log "Configuring asdf plugins..."
	asdf plugin add python || true
fi

# -------- Python tools --------
if have pip; then
	log "Installing Python tools..."
	pip install git-cu || true
fi

log "Done."
