#!/bin/sh

set -u

SCRIPT_DIR=$(CDPATH=; cd "$(dirname "$0")" && pwd) || exit 1
MANAGED_CONFIG_HELPERS=$SCRIPT_DIR/scripts/managed-config.sh
if [ ! -f "$MANAGED_CONFIG_HELPERS" ]; then
	printf '错误: 找不到受管配置辅助脚本：%s\n' "$MANAGED_CONFIG_HELPERS" >&2
	exit 1
fi
# shellcheck source=scripts/managed-config.sh
. "$MANAGED_CONFIG_HELPERS"

PACKAGE_SOURCE=${PI_PACKAGE_SOURCE:-git:git@bitbucket.org:siakitem/my-pi.git}
POWERLEVEL10K_PRESET_FILE=$SCRIPT_DIR/config/p10k.zsh
HIPPO_MEMORY_VERSION_FILE=$SCRIPT_DIR/config/hippo-memory-version
CODEGRAPH_INSTALL_URL=https://raw.githubusercontent.com/colbymchenry/codegraph/main/install.sh
CODEGRAPH_LATEST_RELEASE_URL=https://github.com/colbymchenry/codegraph/releases/latest
KITTY_INSTALL_URL=https://sw.kovidgoyal.net/kitty/installer.sh
KITTY_VERSION_URL=https://sw.kovidgoyal.net/kitty/current-version.txt
update_failed=0
brew_metadata_refreshed=0

say() {
	printf '%s\n' "$*"
}

warn() {
	printf '警告: %s\n' "$*" >&2
}

record_update_failure() {
	warn "$1 升级或配置同步失败；其余已安装组件仍会继续处理。"
	update_failed=1
}

select_updated_bundle_config() {
	updated_bundle_dir=
	case $PACKAGE_SOURCE in
		/*)
			updated_bundle_dir=$PACKAGE_SOURCE
			;;
		./*|../*)
			updated_bundle_dir=$(CDPATH=; cd "$PACKAGE_SOURCE" 2>/dev/null && pwd) || updated_bundle_dir=
			;;
		git:git@bitbucket.org:siakitem/my-pi.git)
			updated_bundle_dir=${PI_CODING_AGENT_DIR:-$HOME/.pi/agent}/git/bitbucket.org/siakitem/my-pi
			;;
	esac

	if [ -n "$updated_bundle_dir" ] && [ -f "$updated_bundle_dir/config/p10k.zsh" ]; then
		POWERLEVEL10K_PRESET_FILE=$updated_bundle_dir/config/p10k.zsh
		HIPPO_MEMORY_VERSION_FILE=$updated_bundle_dir/config/hippo-memory-version
	elif [ ! -f "$POWERLEVEL10K_PRESET_FILE" ]; then
		warn "无法定位升级后的组合包配置，找不到 ${POWERLEVEL10K_PRESET_FILE}。"
		return 1
	else
		warn "无法从当前 PI_PACKAGE_SOURCE 推导升级后的包目录，将使用脚本目录中的配置。"
	fi
}

resolve_zsh_paths() {
	oh_my_zsh_dir=${ZSH:-$HOME/.oh-my-zsh}
	zsh_custom_dir=${ZSH_CUSTOM:-$oh_my_zsh_dir/custom}
	zshrc_file=${ZDOTDIR:-$HOME}/.zshrc
	my_pi_config_dir=${XDG_CONFIG_HOME:-$HOME/.config}/my-pi
	p10k_managed_config_file=$my_pi_config_dir/p10k.zsh
}

replace_zsh_managed_block() {
	managed_id=$1
	managed_placement=$2
	managed_anchor=$3
	shift 3
	managed_content=$(mktemp "${TMPDIR:-/tmp}/my-pi-zsh-block.XXXXXX") || return 1
	printf '%s\n' "$@" > "$managed_content"
	my_pi_replace_managed_block "$zshrc_file" "$managed_id" "$managed_content" \
		"$managed_placement" "$managed_anchor"
	managed_status=$?
	rm -f "$managed_content"
	return "$managed_status"
}

update_git_checkout() {
	component=$1
	checkout=$2
	if [ ! -d "$checkout/.git" ]; then
		warn "$component 已安装，但不是脚本可安全升级的 Git checkout，已跳过版本升级。"
		return 0
	fi
	if ! command -v git >/dev/null 2>&1; then
		warn "升级 $component 需要 git。"
		return 1
	fi
	upstream=$(git -C "$checkout" rev-parse --abbrev-ref --symbolic-full-name '@{upstream}' 2>/dev/null) || {
		warn "$component 的 Git checkout 没有可识别的上游分支，已跳过版本升级。"
		return 1
	}
	git -C "$checkout" fetch --quiet || return 1
	local_revision=$(git -C "$checkout" rev-parse HEAD) || return 1
	remote_revision=$(git -C "$checkout" rev-parse "$upstream") || return 1
	if [ "$local_revision" = "$remote_revision" ]; then
		say "✓ $component 已是最新版本。"
		return 0
	fi
	say "发现 $component 有新版本，正在快进升级。"
	git -C "$checkout" merge --ff-only "$upstream"
}

refresh_brew_metadata() {
	if [ "$brew_metadata_refreshed" -eq 1 ]; then
		return 0
	fi
	say "正在刷新 Homebrew 版本信息。"
	brew update || return 1
	brew_metadata_refreshed=1
}

update_brew_formula_if_installed() {
	formula=$1
	description=$2
	command_name=$3
	if command -v brew >/dev/null 2>&1 && brew list --formula "$formula" >/dev/null 2>&1; then
		refresh_brew_metadata || {
			record_update_failure "$description"
			return 0
		}
		outdated_formula=$(brew outdated --formula --quiet "$formula") || {
			record_update_failure "$description"
			return 0
		}
		if [ -z "$outdated_formula" ]; then
			say "✓ $description 已是最新版本。"
		else
			say "发现 $description 有新版本，正在升级。"
			brew upgrade "$formula" || record_update_failure "$description"
		fi
	elif command -v "$command_name" >/dev/null 2>&1; then
		say "- $description 已安装，但不由 Homebrew 管理，已保留现有安装。"
	else
		say "- $description 未安装，升级流程跳过。"
	fi
}

detect_kitty() {
	kitty_bin=
	if command -v kitty >/dev/null 2>&1; then
		kitty_bin=$(command -v kitty)
		return 0
	fi
	case $(uname -s) in
		Darwin) kitty_candidates="/Applications/kitty.app/Contents/MacOS/kitty" ;;
		*) kitty_candidates="$HOME/.local/kitty.app/bin/kitty" ;;
	esac
	for candidate in $kitty_candidates; do
		if [ -x "$candidate" ]; then
			kitty_bin=$candidate
			return 0
		fi
	done
	return 1
}

resolve_kitty_config_dir() {
	kitty_config_dir=${KITTY_CONFIG_DIRECTORY:-${XDG_CONFIG_HOME:-$HOME/.config}/kitty}
}

kitty_uses_solarized_dark() {
	resolve_kitty_config_dir
	[ -f "$kitty_config_dir/current-theme.conf" ] &&
		grep -F "Solarized Dark" "$kitty_config_dir/current-theme.conf" >/dev/null 2>&1
}

update_kitty() {
	if ! detect_kitty; then
		say "- Kitty 未安装，升级流程跳过。"
		return 0
	fi

	if command -v brew >/dev/null 2>&1 && brew list --cask kitty >/dev/null 2>&1; then
		if refresh_brew_metadata; then
			if outdated_kitty=$(brew outdated --cask --quiet kitty); then
				if [ -z "$outdated_kitty" ]; then
					say "✓ Kitty 已是最新版本。"
				else
					say "发现 Kitty 有新版本，正在升级。"
					brew upgrade --cask kitty || record_update_failure "Kitty"
				fi
			else
				record_update_failure "Kitty"
			fi
		else
			record_update_failure "Kitty"
		fi
	elif [ "$kitty_bin" = "$HOME/.local/kitty.app/bin/kitty" ] || \
		[ "$kitty_bin" = "/Applications/kitty.app/Contents/MacOS/kitty" ]; then
		if ! command -v curl >/dev/null 2>&1; then
			record_update_failure "Kitty（检查版本需要 curl）"
		else
			kitty_version_output=$("$kitty_bin" --version 2>/dev/null) || kitty_version_output=
			case $kitty_version_output in
				kitty\ *)
					installed_kitty_version=${kitty_version_output#kitty }
					installed_kitty_version=${installed_kitty_version%% *}
					;;
				*) installed_kitty_version= ;;
			esac
			latest_kitty_version=$(curl -fsSL "$KITTY_VERSION_URL") || latest_kitty_version=
			if [ -z "$installed_kitty_version" ] || [ -z "$latest_kitty_version" ]; then
				record_update_failure "Kitty 版本检查"
			elif [ "$installed_kitty_version" = "$latest_kitty_version" ]; then
				say "✓ Kitty $installed_kitty_version 已是最新版本。"
			else
				say "发现 Kitty ${latest_kitty_version}（当前 ${installed_kitty_version}），正在升级。"
				installer_file=$(mktemp "${TMPDIR:-/tmp}/my-pi-kitty.XXXXXX") || return 1
				if ! curl -fsSL "$KITTY_INSTALL_URL" -o "$installer_file" || \
					! sh "$installer_file" launch=n "installer=version-$latest_kitty_version"; then
					record_update_failure "Kitty"
				fi
				rm -f "$installer_file"
			fi
		fi
	else
		say "- Kitty 已安装，但不由 Homebrew 或官方 ~/.local 安装管理，已保留现有安装。"
	fi

	if kitty_uses_solarized_dark; then
		"$kitty_bin" +kitten themes --reload-in=none "Solarized Dark" || \
			record_update_failure "Kitty Solarized Dark 主题"
	fi
}

update_codegraph() {
	if ! command -v codegraph >/dev/null 2>&1; then
		say "- CodeGraph 未安装，升级流程跳过。"
		return 0
	fi
	if ! command -v curl >/dev/null 2>&1; then
		warn "检查 CodeGraph 版本需要 curl。"
		return 1
	fi
	installed_codegraph_version=$(codegraph --version 2>/dev/null) || installed_codegraph_version=
	latest_release_url=$(curl -fsSLI -o /dev/null -w '%{url_effective}' \
		"$CODEGRAPH_LATEST_RELEASE_URL") || latest_release_url=
	case $latest_release_url in
		*/releases/tag/*) latest_codegraph_tag=${latest_release_url##*/} ;;
		*) latest_codegraph_tag= ;;
	esac
	latest_codegraph_version=${latest_codegraph_tag#v}
	installed_codegraph_version=${installed_codegraph_version#v}
	if [ -z "$installed_codegraph_version" ] || [ -z "$latest_codegraph_version" ]; then
		warn "无法比较 CodeGraph 的本地版本与最新发布版本，已跳过替换。"
		return 1
	fi
	if [ "$installed_codegraph_version" = "$latest_codegraph_version" ]; then
		say "✓ CodeGraph $installed_codegraph_version 已是最新版本。"
		return 0
	fi
	say "发现 CodeGraph ${latest_codegraph_version}（当前 ${installed_codegraph_version}），正在升级。"
	installer_file=$(mktemp "${TMPDIR:-/tmp}/my-pi-codegraph.XXXXXX") || return 1
	if ! curl -fsSL "$CODEGRAPH_INSTALL_URL" -o "$installer_file" || \
		! CODEGRAPH_VERSION="$latest_codegraph_tag" sh "$installer_file"; then
		rm -f "$installer_file"
		return 1
	fi
	rm -f "$installer_file"
}

read_hippo_memory_version() {
	if [ ! -f "$HIPPO_MEMORY_VERSION_FILE" ]; then
		warn "找不到 Hippo Memory 版本文件：$HIPPO_MEMORY_VERSION_FILE"
		return 1
	fi
	hippo_target_version=$(sed -n '1p' "$HIPPO_MEMORY_VERSION_FILE")
	case $hippo_target_version in
		''|*[!0-9.]*)
			warn "Hippo Memory 版本文件内容无效：$hippo_target_version"
			return 1
			;;
	esac
	printf '%s\n' "$hippo_target_version"
}

installed_hippo_memory_version() {
	hippo --version 2>/dev/null | sed -n 's/^[^0-9]*\([0-9][0-9.]*\).*$/\1/p' | sed -n '1p'
}

update_hippo_memory() {
	if ! command -v hippo >/dev/null 2>&1; then
		say "- Hippo Memory CLI 未安装，升级流程跳过。"
		return 0
	fi
	if ! command -v npm >/dev/null 2>&1; then
		warn "升级 Hippo Memory CLI 需要 npm。"
		return 1
	fi
	hippo_target_version=$(read_hippo_memory_version) || return 1
	hippo_published_version=$(npm view "hippo-memory@$hippo_target_version" version 2>/dev/null) || hippo_published_version=
	if [ "$hippo_published_version" != "$hippo_target_version" ]; then
		warn "无法确认 npm 上的 Hippo Memory 目标版本 $hippo_target_version，已保留现状。"
		return 1
	fi
	hippo_installed_version=$(installed_hippo_memory_version)
	if [ -z "$hippo_installed_version" ]; then
		warn "无法读取 Hippo Memory CLI 本地版本，已保留现状。"
		return 1
	fi
	if [ "$hippo_installed_version" = "$hippo_target_version" ]; then
		say "✓ Hippo Memory CLI $hippo_installed_version 已是组合包目标版本。"
		return 0
	fi
	if ! npm list -g --depth=0 hippo-memory >/dev/null 2>&1; then
		warn "检测到 hippo，但它不属于 npm 全局 hippo-memory 安装；已保留现状。"
		return 1
	fi
	say "发现 Hippo Memory CLI ${hippo_target_version}（当前 ${hippo_installed_version}），正在升级。"
	npm install -g "hippo-memory@$hippo_target_version" || return 1
	hippo_updated_version=$(installed_hippo_memory_version)
	if [ "$hippo_updated_version" != "$hippo_target_version" ]; then
		warn "Hippo Memory CLI 升级后版本校验失败：期望 $hippo_target_version，实际 ${hippo_updated_version:-未知}。"
		return 1
	fi
}

update_zsh_environment() {
	resolve_zsh_paths
	if [ ! -f "$oh_my_zsh_dir/oh-my-zsh.sh" ]; then
		say "- Oh My Zsh 未安装，Powerlevel10k 和 Zsh 插件升级均跳过。"
		return 0
	fi

	if [ -f "$oh_my_zsh_dir/tools/upgrade.sh" ] && command -v zsh >/dev/null 2>&1; then
		ZSH="$oh_my_zsh_dir" zsh "$oh_my_zsh_dir/tools/upgrade.sh" || record_update_failure "Oh My Zsh"
	else
		update_git_checkout "Oh My Zsh" "$oh_my_zsh_dir" || record_update_failure "Oh My Zsh"
	fi

	powerlevel10k_dir=$zsh_custom_dir/themes/powerlevel10k
	if [ -f "$powerlevel10k_dir/powerlevel10k.zsh-theme" ]; then
		update_git_checkout "Powerlevel10k" "$powerlevel10k_dir" || record_update_failure "Powerlevel10k"
	else
		say "- Powerlevel10k 未安装，升级流程跳过。"
	fi

	for plugin in zsh-autosuggestions zsh-syntax-highlighting; do
		plugin_dir=$zsh_custom_dir/plugins/$plugin
		if [ -d "$plugin_dir" ]; then
			update_git_checkout "$plugin" "$plugin_dir" || record_update_failure "$plugin"
		else
			say "- $plugin 未安装，升级流程跳过。"
		fi
	done

	[ -f "$zshrc_file" ] || return 0
	if my_pi_managed_block_exists "$zshrc_file" "oh-my-zsh-loader"; then
		replace_zsh_managed_block "oh-my-zsh-loader" "append" "" \
			"export ZSH=\"$oh_my_zsh_dir\"" \
			"source \"\$ZSH/oh-my-zsh.sh\"" || record_update_failure ".zshrc Oh My Zsh 受管块"
	fi
	if my_pi_managed_block_exists "$zshrc_file" "powerlevel10k-theme"; then
		replace_zsh_managed_block "powerlevel10k-theme" "before" \
			'^(# >>> my-pi:oh-my-zsh-loader >>>|[[:space:]]*(source|\.)[[:space:]].*oh-my-zsh\.sh)' \
			'ZSH_THEME="powerlevel10k/powerlevel10k"' || record_update_failure ".zshrc Powerlevel10k 主题受管块"
	fi
	for plugin in git zsh-autosuggestions zsh-syntax-highlighting; do
		if my_pi_managed_block_exists "$zshrc_file" "zsh-plugin-$plugin"; then
			replace_zsh_managed_block "zsh-plugin-$plugin" "before" \
				'^(# >>> my-pi:oh-my-zsh-loader >>>|[[:space:]]*(source|\.)[[:space:]].*oh-my-zsh\.sh)' \
				"plugins+=($plugin)" || record_update_failure ".zshrc $plugin 受管块"
		fi
	done

	if [ -f "$p10k_managed_config_file" ] || \
		my_pi_managed_block_exists "$zshrc_file" "powerlevel10k-config"; then
		if my_pi_sync_managed_file "$POWERLEVEL10K_PRESET_FILE" "$p10k_managed_config_file"; then
			replace_zsh_managed_block "powerlevel10k-config" "append" "" \
				"[[ ! -f \"$p10k_managed_config_file\" ]] || source \"$p10k_managed_config_file\"" || \
				record_update_failure ".zshrc Powerlevel10k 配置受管块"
		else
			record_update_failure "Powerlevel10k 受管配置"
		fi
	fi
}

if ! command -v pi >/dev/null 2>&1; then
	warn "找不到 pi，无法升级组合包。请确保 pi 位于 PATH。"
	exit 127
fi

say "正在升级 Pi 组合包：$PACKAGE_SOURCE"
if ! pi update "$PACKAGE_SOURCE"; then
	warn "pi update 执行失败，已停止后续升级。"
	exit 1
fi
select_updated_bundle_config || exit 1

say "组合包升级完成，开始升级已安装的终端环境和机器级 CLI；未安装项将直接跳过。"
update_kitty || record_update_failure "Kitty"
update_zsh_environment || record_update_failure "Zsh 环境"
update_codegraph || record_update_failure "CodeGraph"
update_hippo_memory || record_update_failure "Hippo Memory CLI"
update_brew_formula_if_installed "kotlin-lsp" "kotlin-lsp" "kotlin-lsp"
update_brew_formula_if_installed "openjdk@21" "Java 21" "java"
update_brew_formula_if_installed "jdtls" "jdtls" "jdtls"

say "已安装组件的升级与受管配置同步完成。"
exit "$update_failed"
