#!/usr/bin/env bash

# Author: Santhosh Siva
# Date Created: 03-08-2025

# Description:
# A script to checkout branches, optionally stash changes, and manage git workflow efficiently.

# Resolve script directory (works with symlinks for npm global install)
SOURCE="${BASH_SOURCE[0]}"
while [ -L "$SOURCE" ]; do
  DIR="$(cd -P "$(dirname "$SOURCE")" && pwd)"
  SOURCE="$(readlink "$SOURCE")"
  [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE"
done
SCRIPT_DIR="$(cd -P "$(dirname "$SOURCE")" && pwd)"
source "$SCRIPT_DIR/utils"

# Default Values
stash=false
target_branch=

set_flags() {
	while [ $# -gt 0 ]; do
		case "$1" in
		-h | --help)
			echo "g-co - attempt to checkout to branch"
			echo " "
			echo "g-co [options]"
			echo " "
			echo "options:"
			echo "-h, --help                                                          show brief help"
			echo "--target-branch BRANCH, --target-branch=BRANCH, -t=BRANCH, -t BRANCH   specify the target branch"
			echo "--stash-changes                                                     stash changes before proceeding"
			exit 0
			;;
		-t=* | --target-branch=*)
			target_branch="${1#*=}"
			if [ -z "$target_branch" ]; then
				echo ""
				echo "${RED}Error: No target branch specified.$NC"
				exit 1
			fi
			;;
		-t | --target-branch)
			shift
			if [ $# -gt 0 ]; then
				target_branch="$1"
			else
				echo ""
				echo "${RED}Error: No target branch specified.$NC"
				exit 1
			fi
			;;
		-s | --stash-changes)
			stash=true
			;;
		*)
			echo "${RED}Unknown option:${NC} $1"
			exit
			;;
		esac
		shift
	done
}

checkout_or_create_branch() {
	local step_number=2
	if [ "${stash}" = true ]; then
		step_number=3
	fi

	print_message "${BLUE}Checking-out to branch ${NC}origin/${target_branch}${BLUE}.${NC}" $step_number

	# Check if branch exists locally
	if branch_exists_locally "${target_branch}"; then
		fetch_changes "${target_branch}"
		checkout_branch "${target_branch}" $((step_number + 1))
		return
	fi

	print_message "${RED}Branch not found locally.${NC}"

	print_message "${BLUE}Checking if branch exists on remote...${NC}" $((step_number + 1))
	if branch_exists_on_remote "${target_branch}"; then
		print_message "${GREEN}Branch available on remote.${NC}"
		fetch_changes "${target_branch}"
		checkout_branch "${target_branch}"
		return
	fi

	print_message "${RED}Branch not found on remote.${NC}"

	create_new_branch=$(prompt_user true "Create new branch?" $((step_number + 2)))
	if [ "${create_new_branch}" = "y" ]; then
		checkout_branch "${target_branch}" true
		return
	fi

	print_message "" -1
	print_message "${RED}Aborted.${NC}" -1
	exit 1
}

main() {
	set_flags "$@"
	validate_dependencies git figlet lolcat
	print_banner
	check_if_target_branch_is_set $target_branch
	already_on_branch $target_branch
	stash_changes $stash
	checkout_or_create_branch
}

# Only run main if script is executed directly (not sourced)
if [ "${BASH_SOURCE[0]}" = "${0}" ]; then
	main "$@"
	exit 0
fi
