#!/bin/zsh -f
emulate -LR zsh
setopt ERR_EXIT NO_UNSET PIPE_FAIL EXTENDED_GLOB
sc_distribution=${0:A:h:h}
source "$sc_distribution/macos/common.zsh"
source "$sc_distribution/macos/claude-asar-bootstrap.zsh"
source "$sc_distribution/macos/claude-installation-state.zsh"
source "$sc_distribution/macos/claude-installer-presentation.zsh"
source "$sc_distribution/macos/claude-process.zsh"
source "$sc_distribution/macos/claude-recovery-extension.zsh"

sc_app='' sc_pid='' sc_user_data='' sc_channel=stable
sc_root=${SUPERCODE_CLAUDE_STORAGE_ROOT:-$HOME/.supercode/claude}
sc_bootstrap_namespace=${SUPERCODE_CLAUDE_BOOTSTRAP_NAMESPACE:-.s}
sc_telemetry_stage='invocation_validation'
sc_telemetry_reason='invalid_invocation'
sc_telemetry_terminal=false
sc_desktop_version=unknown
sc_bundle_version=unknown
sc_installation_attempt_initialize

sc_install_exit() {
	local exit_status=$?
	trap - EXIT
	if (( exit_status != 0 )) && [[ "$sc_telemetry_terminal" == false ]]; then
		sc_telemetry_track_and_flush 'extension.installation_failed' \
			"channel=$sc_channel" "failure_stage=$sc_telemetry_stage" "reason_code=$sc_telemetry_reason" \
			"desktop_version=$sc_desktop_version" "bundle_version=$sc_bundle_version"
		sc_telemetry_terminal=true
	fi
	sc_cleanup
	exit $exit_status
}

trap sc_install_exit EXIT
trap 'exit 130' INT
trap 'exit 143' TERM HUP

sc_publish_external_runtime() {
	local sc_shim="$HOME/$sc_bootstrap_namespace" sc_release="$sc_root/extension/seed/$sc_version"
	local sc_file sc_main_json
	local -a sc_names=()
	sc_telemetry_stage='runtime_publication'
	sc_telemetry_reason='runtime_publication_failed'
	if [[ -e "$sc_shim" || -L "$sc_shim" ]]; then
		[[ -d "$sc_shim" && ! -L "$sc_shim" ]] || sc_fail 'The bootstrap location is occupied.'
		sc_names=("$sc_shim"/*(DN:t))
		[[ ${(j:,:)${(on)sc_names}} == index.cjs,package.json ]] || sc_fail 'The bootstrap location is not owned by Supercode.'
		[[ -f "$sc_shim/index.cjs" && ! -L "$sc_shim/index.cjs" && -f "$sc_shim/package.json" && ! -L "$sc_shim/package.json" ]] ||
			sc_fail 'Invalid bootstrap file.'
		/usr/bin/cmp -s "$sc_shim/package.json" "$sc_distribution/assets/bootstrap/package.json" ||
			sc_fail 'Unrelated bootstrap files; refusing to overwrite.'
		if ! /usr/bin/cmp -s "$sc_shim/index.cjs" "$sc_distribution/assets/bootstrap/index.cjs"; then
			/usr/bin/cmp -s "$sc_shim/index.cjs" "$sc_distribution/assets/bootstrap/index-legacy.cjs" ||
				sc_fail 'Unrelated bootstrap files; refusing to overwrite.'
			sc_copy_atomic "$sc_distribution/assets/bootstrap/index.cjs" "$sc_shim/index.cjs"
		fi
	else
		/bin/mkdir -m 700 "$sc_shim"
		for sc_file in index.cjs package.json; do
			sc_copy_atomic "$sc_distribution/assets/bootstrap/$sc_file" "$sc_shim/$sc_file"
		done
	fi

	/bin/mkdir -p "$sc_root/extension/seed" "$sc_root/runtime" "$sc_root/logs"
	if [[ ! -e "$sc_release" ]]; then
		/bin/cp -R "$sc_distribution/assets/runtime" "$sc_stage/release"
		/bin/mv "$sc_stage/release" "$sc_release"
	else
		/usr/bin/diff -rq "$sc_distribution/assets/runtime" "$sc_release" >/dev/null ||
			sc_fail 'The installed Claude seed release does not match this installer.'
	fi
	sc_json_string "$sc_release/main.cjs"; sc_main_json=$REPLY
	print -r -- "module.exports=require($sc_main_json);" >"$sc_stage/active.cjs"
	sc_copy_atomic "$sc_stage/active.cjs" "$sc_root/runtime/main.cjs"
	print -r -- "$sc_channel" >"$sc_stage/channel-v1"
	sc_copy_atomic "$sc_stage/channel-v1" "$sc_root/extension/channel-v1"
	print -r -- '#!/bin/zsh -f' >"$sc_stage/recover-v1"
	print -r -- "exec /bin/zsh -f ${(q)sc_release}/recovery/macos/recover.zsh \"\$@\"" >>"$sc_stage/recover-v1"
	sc_copy_atomic "$sc_stage/recover-v1" "$sc_root/recover-v1" 700
	sc_telemetry_stage='recovery_extension_publication'
	sc_telemetry_reason='recovery_extension_publication_failed'
	sc_configure_recovery_extension "$sc_user_data" "$sc_root/recover-v1" "$sc_release/recovery/macos" "$sc_root" "$sc_version" \
		"$sc_bootstrap_namespace"
	print -rn -- '' >"$sc_stage/enabled"
	sc_copy_atomic "$sc_stage/enabled" "$sc_root/recovery-enabled-v1"
	# The active selector is the final atomic publication boundary.
	sc_copy_atomic "$sc_stage/active.cjs" "$sc_root/extension/active.cjs"
}

[[ "$sc_bootstrap_namespace" == .s || "$sc_bootstrap_namespace" == .d || "$sc_bootstrap_namespace" == .e ]] ||
	sc_fail 'Unsupported Claude bootstrap namespace.'
while (( $# )); do
	case "$1" in
		--help)
			print -r -- 'Run claude-install-mac [--app /path/to/Claude.app] [--pid PID] [--channel stable|staging].'
			print -r -- 'The installer and recovery lifecycle use only built-in macOS system tools.'
			exit 0 ;;
		--app|--pid|--storage-root|--user-data-dir|--channel)
			(( $# >= 2 )) || sc_fail "Missing value for $1"
			case "$1" in
				--app) sc_app=$2 ;;
				--pid) sc_pid=$2 ;;
				--storage-root) sc_root=$2 ;;
				--user-data-dir) sc_user_data=$2 ;;
				--channel) sc_channel=$2 ;;
			esac
			shift 2 ;;
		*) sc_fail "Unknown Claude installer argument: $1" ;;
	esac
done
[[ "$sc_channel" == stable || "$sc_channel" == staging ]] || sc_fail 'Claude extension channel must be stable or staging.'
sc_telemetry_stage='platform_validation'
sc_telemetry_reason='unsupported_platform'
[[ "$OSTYPE" == darwin* && "$EUID" != 0 ]] || sc_fail 'Run this installer as your normal macOS user, not sudo.'
sc_telemetry_stage='target_discovery'
sc_telemetry_reason='target_discovery_failed'
sc_assert_path "$sc_root"
sc_root=${sc_root:A}
if [[ ${SUPERCODE_CLAUDE_INSTALLATION_STARTED_REPORTED:-false} != true ]]; then
	sc_telemetry_track 'extension.installation_started' "channel=$sc_channel" 'entrypoint=npx'
fi
sc_select_app
sc_desktop_version=$(/usr/bin/plutil -extract CFBundleShortVersionString raw "$sc_app/Contents/Info.plist" 2>/dev/null || print -r -- unknown)
sc_bundle_version=$(/usr/bin/plutil -extract CFBundleVersion raw "$sc_app/Contents/Info.plist" 2>/dev/null || print -r -- unknown)
[[ "$sc_desktop_version" == [A-Za-z0-9._+-]## ]] || sc_desktop_version=unknown
[[ "$sc_bundle_version" == [A-Za-z0-9._+-]## ]] || sc_bundle_version=unknown
/bin/mkdir -p "$sc_root"
sc_installation_attempt_publish
sc_telemetry_stage='lifecycle_lock'
sc_telemetry_reason='lifecycle_lock_failed'
sc_acquire_lock
sc_identity=$(print -rn -- "$sc_app" | /usr/bin/openssl dgst -sha256 | /usr/bin/awk '{print $NF}')
sc_installation="$sc_root/installations/$sc_identity"
if [[ -z "$sc_user_data" ]]; then
	sc_user_data="$HOME/Library/Application Support/Claude"
fi
sc_assert_path "$sc_user_data"
sc_user_data=${sc_user_data:A}
sc_stage=$(/usr/bin/mktemp -d "$sc_root/install-stage.XXXXXXXX")
sc_version=$(<"$sc_distribution/version")
sc_telemetry_stage='installation_state'
sc_telemetry_reason='installation_state_failed'
sc_installation_state "$sc_app" "$sc_installation" "$sc_pid"
sc_state=$REPLY
if [[ "$sc_state" == admission-active || "$sc_state" == already-patched ]]; then
	sc_publish_external_runtime
	print -r -- "$sc_state"
	sc_telemetry_track 'extension.installation_completed' \
		"channel=$sc_channel" "extension_version=$sc_version" "result=$sc_state" \
		"desktop_version=$sc_desktop_version" "bundle_version=$sc_bundle_version"
	sc_telemetry_track_and_flush 'extension.installation_finished' \
		"channel=$sc_channel" "extension_version=$sc_version" 'mode=user-install' 'outcome=success' \
		"desktop_version=$sc_desktop_version" "bundle_version=$sc_bundle_version"
	sc_telemetry_terminal=true
	sc_present_installed
	exit 0
fi
sc_telemetry_stage='signature_verification'
sc_telemetry_reason='signature_verification_failed'
/usr/bin/codesign --verify --deep --strict "$sc_app"
sc_telemetry_stage='compatibility_validation'
sc_telemetry_reason='compatibility_validation_failed'
sc_asar_plan "$sc_app" "$sc_stage" "$sc_version" "$sc_bootstrap_namespace"

# The external installer only validates compatibility and publishes the recovery
# extension. Claude's own signed Plugin helper performs the in-place patch on
# the next launch, avoiding macOS App Management access for the user's terminal.
sc_publish_external_runtime
print -r -- 'recovery-configured'
sc_telemetry_track_and_flush 'extension.installation_completed' \
	"channel=$sc_channel" "extension_version=$sc_version" 'result=recovery-configured' \
	"desktop_version=$sc_desktop_version" "bundle_version=$sc_bundle_version"
sc_telemetry_terminal=true
sc_present_installed
