#compdef sway-session

_sway_session_contexts() {
	local scope=$1 prefix=$2 output line uuid description
	local -a values descriptions

	output=$(command sway-session completion contexts "$scope" 2>/dev/null) || return 0
	while IFS= read -r line || [[ -n $line ]]; do
		[[ $line == *$'\t'* && $line != *$'\t'*$'\t'* ]] || continue
		uuid=${line%%$'\t'*}
		description=${line#*$'\t'}
		[[ -n $description ]] || continue
		[[ $uuid =~ '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$' ]] || continue
		[[ $uuid != 00000000-0000-0000-0000-000000000000 ]] || continue
		[[ $uuid == ${prefix}* ]] || continue
		values+=("$uuid")
		descriptions+=("$description")
	done <<< "$output"
	(( ${#values} )) && compadd -d descriptions -- "${values[@]}"
}

_sway_session_context_pending() {
	local skip_next=0 word
	shift
	for word in "$@"; do
		if (( skip_next )); then
			skip_next=0
			continue
		fi
		case $word in
			--socket|--desktop-id|--label) skip_next=1 ;;
			--json|-h|--help|--yes|--require-active) ;;
			--*) ;;
			*) return 1 ;;
		esac
	done
	return 0
}

_sway_session_restore_scope() {
	local skip_next=0 word
	for word in "$@"; do
		if (( skip_next )); then
			skip_next=0
			continue
		fi
		case $word in
			--socket) skip_next=1 ;;
			--require-active) print -r -- restore-active; return 0 ;;
		esac
	done
	print -r -- restore
}

_sway_session_add() {
	local value
	local -a candidates
	for value in "$@"; do
		if (( ${global_options_ended:-0} )) && [[ $value == --json || $value == -h || $value == --help ]]; then
			continue
		fi
		candidates+=("$value")
	done
	(( ${#candidates} )) && compadd -- "${candidates[@]}"
	return 0
}

_sway_session_marker_is_value() {
	local command=${arguments[1]-} app_command=${arguments[2]-} start=1 word pending=0 parsing=1
	local value_options=''
	case $command in
		terminal) value_options=' --project --context --cwd --label --socket --role ' ;;
		register) value_options=' --session --cwd --label --provider --id ' ;;
		restore|daemon|broker) value_options=' --socket ' ;;
		doctor) value_options=' --fix --socket --sway-config ' ;;
		request-start) value_options=' --session --cwd --label --provider --workspace ' ;;
		app)
			start=2
			case $app_command in
				register-focused|rebind-focused) value_options=' --socket --desktop-id ' ;;
				register-workspace|status|forget) value_options=' --socket ' ;;
			esac
			;;
	esac
	for word in "${arguments[@]:${start}}"; do
		if (( pending )); then
			pending=0
			continue
		fi
		(( parsing )) || return 1
		case $word in
			--)
				parsing=0
				;;
			--*=*)
				;;
			--*)
				[[ $value_options == *" $word "* ]] && pending=1
				;;
			*)
				parsing=0
				;;
		esac
	done
	(( pending ))
}

_sway_session_doctor_arguments_valid() {
	local pending=0 word
	doctor_has_fix=0 doctor_has_check=0
	for word in "${arguments[@]:1}"; do
		if (( pending )); then
			pending=0
			continue
		fi
		case $word in
			--fix) doctor_has_fix=1; pending=1 ;;
			--fix=*) doctor_has_fix=1 ;;
			--socket|--sway-config) pending=1 ;;
			--check|--check=true|--check=1) doctor_has_check=1 ;;
			--check=false|--check=0) doctor_has_check=0 ;;
			--yes|--json|-h|--help|--*=*) ;;
			--*) ;;
			*) return 1 ;;
		esac
	done
	return 0
}

_sway-session() {
	local cur=${words[CURRENT]} word command='' app_command='' context_scope='' index options_ended=0 terminator_arguments=0 global_options_ended=0 invalid_command_option=0 global_value_pending=0
	local -a arguments

	for (( index = 2; index < CURRENT; index++ )); do
		word=${words[index]}
		if (( global_value_pending )); then
			global_value_pending=0
			continue
		fi
		if (( options_ended )); then
			arguments+=("$word")
			(( terminator_arguments += 1 ))
			continue
		fi
		case $word in
			--config) global_value_pending=1; continue ;;
			--config=*) continue ;;
			--json|-h|--help)
				if (( global_options_ended )); then
					_sway_session_marker_is_value || invalid_command_option=1
					arguments+=("$word")
				fi
				continue
				;;
			--)
				global_options_ended=1
				if _sway_session_marker_is_value; then
					arguments+=("$word")
				else
					options_ended=1
				fi
				continue
				;;
		esac
		arguments+=("$word")
	done

	command=${arguments[1]-}
	if [[ ${words[CURRENT-1]-} == --config ]]; then
		_files
		return
	fi
	if [[ $command == --config ]]; then
		_files
		return
	fi
	(( invalid_command_option )) && return 0
	if [[ -z $command ]]; then
		(( options_ended )) && return 0
		_sway_session_add terminal register restore list archive activate purge app daemon broker request-start report-agent-session report-codex-session completion doctor --config --json -h --help
		return
	fi
	app_command=${arguments[2]-}
	if (( options_ended )); then
		(( terminator_arguments == 0 )) || return 0
		case $command in
			restore)
				if _sway_session_context_pending restore "${arguments[@]:1}"; then
					context_scope=$(_sway_session_restore_scope "${arguments[@]:1}")
					_sway_session_contexts "$context_scope" "$cur"
				fi
				;;
			purge)
				_sway_session_context_pending "$command" "${arguments[@]:1}" && _sway_session_contexts "$command" "$cur"
				;;
			app)
				if [[ $app_command == forget ]] && _sway_session_context_pending app-forget "${arguments[@]:2}"; then
					_sway_session_contexts app-forget "$cur"
				fi
				;;
		esac
		return 0
	fi

	case $command in
		terminal)
			case ${arguments[-1]-} in
				--cwd) _files; return ;;
				--context) _sway_session_contexts terminal-status "$cur"; return ;;
				--role) _sway_session_add shell agy amp claude cline codex copilot cursor devin droid gemini grok hermes kilo kimi kiro maki mastracode omp opencode pi qodercli qwen; return ;;
				--project|--label|--socket) return ;;
			esac
			if [[ ${arguments[2]-} == list ]]; then
				_sway_session_add --json -h --help
			elif [[ ${arguments[2]-} == manage ]]; then
				[[ ${arguments[-1]-} == --socket ]] && { _files; return; }
				_sway_session_add --socket -h --help
			elif [[ ${arguments[2]-} == status ]]; then
				_sway_session_add --project --json -h --help
				if [[ $cur != -* ]] && _sway_session_context_pending terminal-status "${arguments[@]:2}"; then
					_sway_session_contexts terminal-status "$cur"
				fi
			elif [[ ${arguments[2]-} == cleanup ]]; then
				[[ ${arguments[-1]-} == --archived-before ]] && return
				_sway_session_add --archived-before --json -h --help
			elif [[ ${arguments[2]-} == reconfigure ]]; then
				[[ ${arguments[-1]-} == --project || ${arguments[-1]-} == --socket ]] && return
				_sway_session_add --project --socket --json -h --help
			elif [[ ${arguments[2]-} == rename ]]; then
				[[ ${arguments[-1]-} == --label ]] && return
				_sway_session_add --label --json -h --help
				if [[ $cur != -* ]] && _sway_session_context_pending terminal-status "${arguments[@]:2}"; then
					_sway_session_contexts terminal-status "$cur"
				fi
			else
				_sway_session_add manage list status cleanup rename reconfigure --new --context --project --cwd --label --socket --role --ephemeral --json -h --help
			fi
			;;
		register)
			if [[ ${arguments[-1]-} == --cwd ]]; then
				_files
			elif [[ ${arguments[-1]-} == --session || ${arguments[-1]-} == --label || ${arguments[-1]-} == --provider || ${arguments[-1]-} == --id ]]; then
				return
			else
				_sway_session_add --session --cwd --label --provider --id --json -h --help
			fi
			;;
		restore)
			if [[ ${arguments[-1]-} == --socket ]]; then
				_files
			elif _sway_session_context_pending restore "${arguments[@]:1}"; then
				_sway_session_add --socket --require-active --json -h --help
				if [[ $cur != -* ]]; then
					context_scope=$(_sway_session_restore_scope "${arguments[@]:1}")
					_sway_session_contexts "$context_scope" "$cur"
				fi
			else
				_sway_session_add --json -h --help
			fi
			;;
		doctor)
			local doctor_has_fix=0 doctor_has_check=0
			_sway_session_doctor_arguments_valid || return 0
			case ${arguments[-1]-} in
				--socket|--sway-config) _files; return ;;
				--fix) _sway_session_add sway.integration; return ;;
			esac
			if (( doctor_has_fix )); then
				_sway_session_add --fix --yes --socket --sway-config --json -h --help
			elif (( doctor_has_check )); then
				_sway_session_add --check --socket --sway-config --json -h --help
			else
				_sway_session_add --check --fix --socket --sway-config --json -h --help
			fi
			;;
		list|report-agent-session|report-codex-session)
			_sway_session_add --json -h --help
			;;
		archive|activate|purge)
			if _sway_session_context_pending "$command" "${arguments[@]:1}"; then
				if [[ $command == purge ]]; then
					_sway_session_add --yes --json -h --help
				else
					_sway_session_add --json -h --help
				fi
				[[ $cur == -* ]] || _sway_session_contexts "$command" "$cur"
			else
				_sway_session_add --json -h --help
			fi
			;;
		daemon|broker)
			if [[ ${arguments[-1]-} == --socket ]]; then
				_files
			else
				_sway_session_add --socket --json -h --help
			fi
			;;
		request-start)
			if [[ ${arguments[-1]-} == --cwd ]]; then
				_files
			elif [[ ${arguments[-1]-} == --session || ${arguments[-1]-} == --label || ${arguments[-1]-} == --provider || ${arguments[-1]-} == --workspace ]]; then
				return
			else
				_sway_session_add --session --cwd --label --provider --workspace --json -h --help
			fi
			;;
		completion)
			case ${arguments[2]-} in
				'') _sway_session_add contexts --json -h --help ;;
				contexts)
					if [[ -z ${arguments[3]-} ]]; then
						_sway_session_add archive activate restore restore-active purge terminal-status app-forget
					elif [[ $cur == -* ]]; then
						_sway_session_add --json -h --help
					fi
					;;
			esac
			;;
		app)
			if [[ -z $app_command ]]; then
				_sway_session_add register-focused register-workspace confirm status list rebind-focused reapprove pin unpin archive activate forget --json -h --help
				return
			fi
			case $app_command in
				register-focused)
					[[ ${arguments[-1]-} == --socket ]] && { _files; return; }
					[[ ${arguments[-1]-} == --desktop-id ]] && return
					_sway_session_add --socket --desktop-id --yes --json -h --help
					;;
				register-workspace)
					[[ ${arguments[-1]-} == --socket ]] && { _files; return; }
					_sway_session_add --socket --yes --json -h --help
					;;
				confirm|pin|unpin|archive|activate)
					_sway_session_add --json -h --help
					;;
				status)
					[[ ${arguments[-1]-} == --socket ]] && { _files; return; }
					_sway_session_add --socket --json -h --help
					;;
				list)
					_sway_session_add --json -h --help
					;;
				rebind-focused)
					[[ ${arguments[-1]-} == --socket ]] && { _files; return; }
					[[ ${arguments[-1]-} == --desktop-id ]] && return
					if _sway_session_context_pending app-rebind "${arguments[@]:2}"; then
						_sway_session_add --socket --desktop-id --yes --json -h --help
					else
						_sway_session_add --json -h --help
					fi
					;;
				reapprove)
					if _sway_session_context_pending app-reapprove "${arguments[@]:2}"; then
						_sway_session_add --yes --json -h --help
					else
						_sway_session_add --json -h --help
					fi
					;;
				forget)
					[[ ${arguments[-1]-} == --socket ]] && { _files; return; }
					if _sway_session_context_pending app-forget "${arguments[@]:2}"; then
						_sway_session_add --socket --yes --json -h --help
						[[ $cur == -* ]] || _sway_session_contexts app-forget "$cur"
					else
						_sway_session_add --json -h --help
					fi
					;;
			esac
			;;
	esac
	return 0
}
