#!/usr/bin/env bash

set -euo pipefail

if [[ $# -ne 2 ]]; then
	echo "Usage: $0 <alpha|beta|stable> <android|ios>" >&2
	exit 1
fi

channel=$1
platform=$2
case "$channel" in
	alpha | beta | stable) ;;
	*) echo "Unsupported release channel: $channel" >&2; exit 1 ;;
esac
case "$platform" in
	android | ios) ;;
	*) echo "Unsupported mobile platform: $platform" >&2; exit 1 ;;
esac

repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
release_version="${HT_MOBILE_RELEASE_VERSION:-${CI_COMMIT_TAG:-}}"
release_version="${release_version#v}"
if [[ -z "$release_version" ]]; then
	echo "HT_MOBILE_RELEASE_VERSION or CI_COMMIT_TAG is required" >&2
	exit 1
fi

ftp_host="${O20010_RELEASE_FTP_HOST:-ftp.hivetechnology.net}"
ftp_port="${O20010_RELEASE_FTP_PORT:-21}"
ftp_user="${O20010_RELEASE_FTP_USER:-}"
ftp_password="${O20010_RELEASE_FTP_PASSWORD:-}"
remote_root="${O20010_MOBILE_RELEASE_REMOTE_ROOT:-/releases.hivetechnology.net/o20010/06}"
public_root="${O20010_MOBILE_RELEASE_PUBLIC_ROOT:-https://releases.hivetechnology.net/o20010/06}"
dry_run="${O20010_RELEASE_DRY_RUN:-0}"
publish_dir=$(mktemp -d)
trap 'rm -rf "$publish_dir"' EXIT

if [[ "$dry_run" != "1" && ( -z "$ftp_user" || -z "$ftp_password" ) ]]; then
	echo "O20010_RELEASE_FTP_USER and O20010_RELEASE_FTP_PASSWORD are required" >&2
	exit 1
fi
if ! [[ "$ftp_port" =~ ^[0-9]+$ ]]; then
	echo "O20010_RELEASE_FTP_PORT must be numeric" >&2
	exit 1
fi

extension=apk
source_path="$repo_root/dist/${release_version}-android-source.tar.gz"
if [[ "$platform" == "ios" ]]; then
	extension=ipa
	ios_version=$(sed -n 's/^[[:space:]]*MARKETING_VERSION:[[:space:]]*"\([^"]*\)"/\1/p' "$repo_root/project.yml" | head -1)
	ios_build=$(sed -n 's/^[[:space:]]*CURRENT_PROJECT_VERSION:[[:space:]]*\([0-9][0-9]*\)/\1/p' "$repo_root/project.yml" | head -1)
	if [[ -z "$ios_version" || -z "$ios_build" ]]; then
		echo "Unable to determine the iOS source archive version from project.yml" >&2
		exit 1
	fi
	source_path="$repo_root/dist/${ios_version}-build${ios_build}-source.tar.gz"
fi

binary_name="HT-Portal-VPN-${release_version}.${extension}"
binary_path="$repo_root/dist/$binary_name"
alias_name="HT-Portal-VPN.${extension}"
if [[ ! -f "$binary_path" ]]; then
	echo "Release binary not found: $binary_path" >&2
	exit 1
fi

if [[ ! -f "$source_path" ]]; then
	echo "Corresponding source archive not found: $source_path" >&2
	exit 1
fi

sha256=$(sha256sum "$binary_path" | awk '{print $1}')
size=$(stat -c '%s' "$binary_path")
mod_time=$(date -u -d "@$(stat -c '%Y' "$binary_path")" '+%Y-%m-%dT%H:%M:%SZ')
source_revision="${CI_COMMIT_SHA:-$(git -C "$repo_root" rev-parse HEAD)}"
remote_folder="$platform/$channel"
remote_releases="$publish_dir/releases.remote.json"

store_artifact=""
if [[ "$platform" == "android" && -f "$repo_root/dist/HT-Portal-VPN-${release_version}.aab" ]]; then
	store_artifact="HT-Portal-VPN-${release_version}.aab"
fi

jq -n \
	--arg platform "$platform" \
	--arg channel "$channel" \
	--arg version "$release_version" \
	--arg path "$binary_name" \
	--arg directPath "$alias_name" \
	--arg sha256 "$sha256" \
	--argjson size "$size" \
	--arg modTime "$mod_time" \
	--arg sourcePath "$(basename "$source_path")" \
	--arg sourceRevision "$source_revision" \
	--arg storeArtifactPath "$store_artifact" \
	'{
		schemaVersion: 1,
		platform: $platform,
		channel: $channel,
		version: $version,
		path: $path,
		directPath: $directPath,
		sha256: $sha256,
		size: $size,
		modTime: $modTime,
		sourcePath: $sourcePath,
		sourceRevision: $sourceRevision
	} + if $storeArtifactPath == "" then {} else {storeArtifactPath: $storeArtifactPath} end' \
	> "$publish_dir/latest.json"

remote_releases_url="${public_root%/}/$remote_folder/releases.json"
if curl -fsSL --max-time 20 "$remote_releases_url" -o "$remote_releases" 2>/dev/null; then
	jq -s '
		(.[0] // []) as $remote |
		(.[1]) as $latest |
		reduce ($remote + [$latest])[] as $release ({}; .[$release.version] = $release)
		| [.[]]
		| sort_by(.version | split(".") | map(tonumber? // 0))
		| reverse
	' "$remote_releases" "$publish_dir/latest.json" > "$publish_dir/releases.json"
else
	jq -s '.' "$publish_dir/latest.json" > "$publish_dir/releases.json"
fi

printf '%s  %s\n' "$sha256" "$binary_name" > "$publish_dir/$binary_name.sha256"
printf '%s  %s\n' "$sha256" "$alias_name" > "$publish_dir/$alias_name.sha256"

upload_file() {
	local local_path=$1
	local remote_name=$2
	local public_url="${public_root%/}/$remote_folder/$remote_name"
	if [[ "$dry_run" == "1" ]]; then
		echo "DRY RUN: $local_path -> $public_url"
		return
	fi
	echo "Uploading $(basename "$local_path") -> $public_url"
	curl --fail --silent --show-error --ftp-create-dirs \
		--user "$ftp_user:$ftp_password" \
		-T "$local_path" \
		"ftp://${ftp_host}:${ftp_port}${remote_root%/}/$remote_folder/$remote_name"
}

upload_file "$binary_path" "$binary_name"
upload_file "$binary_path" "$alias_name"
upload_file "$publish_dir/$binary_name.sha256" "$binary_name.sha256"
upload_file "$publish_dir/$alias_name.sha256" "$alias_name.sha256"
upload_file "$publish_dir/latest.json" latest.json
upload_file "$publish_dir/releases.json" releases.json
upload_file "$source_path" "$(basename "$source_path")"

if [[ -n "$store_artifact" ]]; then
	upload_file "$repo_root/dist/$store_artifact" "$store_artifact"
	if [[ -f "$repo_root/dist/$store_artifact.sha256" ]]; then
		upload_file "$repo_root/dist/$store_artifact.sha256" "$store_artifact.sha256"
	fi
fi

if [[ "$dry_run" == "1" ]]; then
	echo "DRY RUN complete for $platform $release_version ($channel)"
else
	echo "Published $platform $release_version to $channel"
fi
