#!/usr/bin/env bash

LPATH=( /usr/lib/le "$HOME/.local/lib/le" "lib/le" "lib" )
for l in "${LPATH[@]}"; do
	[[ -f "$l/util" ]] && source "$l/util"
done

gen_san_string() {
	declare d
	declare -a argv

	argv=( "$@" )

	printf '[SAN]\nsubjectAltName='

	for d in "${argv[@]}"; do
		printf 'DNS:%s' "$d"
		if ! [[ "$d" == "${argv[-1]}" ]]; then
			printf ','
		fi
	done
}

gen_renew_config() {
	declare d

	printf 'domains=(\n'
	for d in "$@"; do
		printf "	%s\n" "$d"
	done
	printf ')\n'
}

usage() {
	while read -r line; do printf '%s\n' "$line"; done <<- EOF
		Usage: le-issue [options] <domain> [domain ...]
		   Options:
		      -c <dir>        # Configuration directory. Default: \$HOME/.acme
		      -a <dir>        # A dir to put challenges in. Default: /var/www/acme
		      -h              # Show this message.
	EOF
}

main() {
	declare cfg_dir
	declare -a domains

	while (( $# )); do
		case $1 in
			-c)
				cfg_dir=$2
				shift;;

			-a)
				challenge_dir=$2
				shift;;

			-h)
				usage
				return 0;;

			--)
				shift
				break;;

			*) break;;
		esac

		shift
	done

	domains=( "$@" )

	(( ${#domains[@]} )) || {
		usage; return 1
	}

	set_default cfg_dir "$HOME/.acme"
	set_default challenge_dir '/var/www/acme'

	if ! [[ -d "$cfg_dir" ]]; then
		err "Config dir ($cfg_dir) not found, creating."
		if ! mkdir -m700 "$cfg_dir"; then
			err "Can't create config dir: $cfg_dir"
			return 1
		fi
	fi

	if ! [[ -f "$cfg_dir/account.key" ]]; then
		err "Account key not found, generating a new one."
		openssl genrsa 4096 > "$cfg_dir/account.key"
	fi

	if ! [[ -d "$cfg_dir/domains/${domains[0]}" ]]; then
		mkdir -p "$cfg_dir/domains/${domains[0]}"
	fi

	if ! [[ -f "$cfg_dir/domains/${domains[0]}/privkey.pem" ]]; then
		err "Generating a new key for ${domains[0]}."
		openssl genrsa 4096 > "$cfg_dir/domains/${domains[0]}/privkey.pem"
	fi

	if ! [[ -d "$challenge_dir" ]]; then
		err "Challenge dir does not exist: $challenge_dir"
		return 1
	fi

	err "Generating a certificate request for: ${domains[@]}."
	if (( ${#domains[@]} > 1 )); then
		openssl req -new -sha256 \
			-key "$cfg_dir/domains/${domains[0]}/privkey.pem" \
			-subj "/" \
			-reqexts SAN \
			-config <(cat /etc/ssl/openssl.cnf <(gen_san_string "${domains[@]}")) > "$cfg_dir/domains/${domains[0]}/request.csr"
	else
		openssl req -new -sha256 \
			-key "$cfg_dir/domains/${domains[0]}/privkey.pem" \
			-subj "/CN=${domains[0]}" > "$cfg_dir/domains/${domains[0]}/request.csr"
	fi

	err "Getting a signed certificate."
	acme-tiny \
		--account-key "$cfg_dir/account.key" \
		--csr "$cfg_dir/domains/${domains[0]}/request.csr" \
		--acme-dir "$challenge_dir" | grep -vE '^$' > "$cfg_dir/domains/${domains[0]}/certificate.pem"

	if (( $? )); then
		return 1
	fi

	gen_renew_config "${domains[@]}" > "$cfg_dir/domains/${domains[0]}/renew.cfg"

	ln -fs "$cfg_dir/domains/${domains[0]}/certificate.pem" "$cfg_dir/domains/${domains[0]}/fullchain.pem"

	err "Your certificate is available at $cfg_dir/domains/${domains[0]}/fullchain.pem"
}

main "$@"
