#!/bin/bash

set -euo pipefail

# Default values
PACKAGE_NAME="${PACKAGE_NAME:-mise}"
# TODO(epel-9): drop centos-stream+epel-next-9-* and switch back to epel-9-*
# once RHEL 9 AppStream ships rust >= mise's MSRV (currently EL9 = 1.88).
DEFAULT_CHROOTS="fedora-rawhide-aarch64 fedora-rawhide-x86_64 fedora-44-aarch64 fedora-44-x86_64 fedora-43-aarch64 fedora-43-x86_64 epel-10-aarch64 epel-10-x86_64 centos-stream+epel-next-9-aarch64 centos-stream+epel-next-9-x86_64"
CHROOTS="${CHROOTS:-$DEFAULT_CHROOTS}"
BUILD_PROFILE="${BUILD_PROFILE:-release}"
MAINTAINER_NAME="${MAINTAINER_NAME:-mise Release Bot}"
MAINTAINER_EMAIL="${MAINTAINER_EMAIL:-noreply@mise.jdx.dev}"
COPR_OWNER="${COPR_OWNER:-jdxcode}"
COPR_PROJECT="${COPR_PROJECT:-mise}"
COPR_BUILD_TIMEOUT="${COPR_BUILD_TIMEOUT:-180000}"
DRY_RUN="${DRY_RUN:-false}"
WAIT_FOR_BUILD="${WAIT_FOR_BUILD:-true}"

# Store the repository root directory
REPO_ROOT="$(pwd)"

# Function to show usage
usage() {
	echo "Usage: $0 [options]"
	echo ""
	echo "Options:"
	echo "  -v, --version VERSION        Package version (required)"
	echo "  -p, --profile PROFILE        Build profile (default: release)"
	echo "  -c, --chroots CHROOTS        COPR chroots (default: $DEFAULT_CHROOTS)"
	echo "  -o, --owner OWNER            COPR owner (default: jdxcode)"
	echo "  -j, --project PROJECT        COPR project (default: mise)"
	echo "  -n, --name NAME              Package name (default: mise)"
	echo "  -m, --maintainer-name NAME   Maintainer name (default: mise Release Bot)"
	echo "  -e, --maintainer-email EMAIL Maintainer email (default: noreply@mise.jdx.dev)"
	echo "      --nowait                 Return after COPR accepts the build"
	echo "  -d, --dry-run                Build SRPM only, don't submit to COPR"
	echo "  -h, --help                   Show this help"
	echo ""
	echo "Environment variables:"
	echo "  COPR_API_LOGIN               COPR API login (required for submission)"
	echo "  COPR_API_TOKEN               COPR API token (required for submission)"
	echo ""
	echo "Example:"
	echo "  $0 -v 2025.7.22 -p serious -d"
	exit 0
}

# Parse command line arguments
while [[ $# -gt 0 ]]; do
	case $1 in
	-v | --version)
		VERSION="$2"
		shift 2
		;;
	-p | --profile)
		BUILD_PROFILE="$2"
		shift 2
		;;
	-c | --chroots)
		CHROOTS="$2"
		shift 2
		;;
	-o | --owner)
		COPR_OWNER="$2"
		shift 2
		;;
	-j | --project)
		COPR_PROJECT="$2"
		shift 2
		;;
	-n | --name)
		PACKAGE_NAME="$2"
		shift 2
		;;
	-m | --maintainer-name)
		MAINTAINER_NAME="$2"
		shift 2
		;;
	-e | --maintainer-email)
		MAINTAINER_EMAIL="$2"
		shift 2
		;;
	--nowait)
		WAIT_FOR_BUILD="false"
		shift
		;;
	-d | --dry-run)
		DRY_RUN="true"
		shift
		;;
	-h | --help)
		usage
		;;
	*)
		echo "Unknown option: $1"
		usage
		;;
	esac
done

# Check required parameters
if [ -z "${VERSION:-}" ]; then
	echo "Error: VERSION is required"
	echo "Use --version to specify the version or set VERSION environment variable"
	exit 1
fi

echo "=== COPR Build Configuration ==="
echo "Package Name: $PACKAGE_NAME"
echo "Version: $VERSION"
echo "Build Profile: $BUILD_PROFILE"
echo "Chroots: $CHROOTS"
echo "COPR Owner: $COPR_OWNER"
echo "COPR Project: $COPR_PROJECT"
echo "COPR Build Timeout: $COPR_BUILD_TIMEOUT"
echo "Maintainer: $MAINTAINER_NAME <$MAINTAINER_EMAIL>"
echo "Wait for build: $WAIT_FOR_BUILD"
echo "Dry Run: $DRY_RUN"
echo ""

# Configure Git (needed for git archive)
git config --global user.name "$MAINTAINER_NAME"
git config --global user.email "$MAINTAINER_EMAIL"
git config --global --add safe.directory "$REPO_ROOT"

# Set up COPR configuration if not in dry-run mode
if [ "$DRY_RUN" != "true" ]; then
	if [ -z "${COPR_API_LOGIN:-}" ] || [ -z "${COPR_API_TOKEN:-}" ]; then
		echo "Error: COPR_API_LOGIN and COPR_API_TOKEN environment variables are required for submission"
		exit 1
	fi

	mkdir -p ~/.config
	cat >~/.config/copr <<EOF
[copr-cli]
login = $COPR_API_LOGIN
username = $COPR_OWNER
token = $COPR_API_TOKEN
copr_url = https://copr.fedorainfracloud.org
EOF
fi

# Create build directory structure
BUILD_DIR="/tmp/rpm-build"
mkdir -p "$BUILD_DIR"/{BUILD,RPMS,SOURCES,SPECS,SRPMS}

# Set up RPM build environment
echo "%_topdir $BUILD_DIR" >~/.rpmmacros
echo "%_tmppath %{_topdir}/tmp" >>~/.rpmmacros

cd "$BUILD_DIR"

echo "=== Creating Source Tarball ==="
# Create original source tarball
git -C "$REPO_ROOT" archive --format=tar --prefix="${PACKAGE_NAME}-${VERSION}/" HEAD >"SOURCES/${PACKAGE_NAME}-${VERSION}.tar"

# Compress the tarball
gzip "SOURCES/${PACKAGE_NAME}-${VERSION}.tar"

echo "=== Vendoring Rust Dependencies ==="
# Extract source for vendoring
cd SOURCES
tar -xzf "${PACKAGE_NAME}-${VERSION}.tar.gz"
cd "${PACKAGE_NAME}-${VERSION}"

# Vendor dependencies
mkdir -p .cargo
cat >.cargo/config.toml <<'EOF'
[source.crates-io]
replace-with = "vendored-sources"

[source.vendored-sources]
directory = "vendor"
EOF

cargo vendor vendor/
tar -czf "../${PACKAGE_NAME}-vendor-${VERSION}.tar.gz" vendor/ .cargo/

# Clean up extracted source
cd ../..
rm -rf "SOURCES/${PACKAGE_NAME}-${VERSION}"

echo "=== Creating RPM Spec File ==="
# Create spec file from template
cat >"SPECS/${PACKAGE_NAME}.spec" <<'EOF'
%global debug_package %{nil}
%global _missing_build_ids_terminate_build 0

Name:           __PACKAGE_NAME__
Version:        __VERSION__
Release:        1%{?dist}
Summary:        Dev tools, env vars, and tasks in one CLI

License:        MIT
URL:            https://mise.jdx.dev
Source0:        https://github.com/jdx/mise/archive/v%{version}/mise-%{version}.tar.gz
Source1:        mise-vendor-%{version}.tar.gz

BuildRequires:  rust >= 1.93
BuildRequires:  cargo
BuildRequires:  gcc
BuildRequires:  git
BuildRequires:  openssl-devel
BuildRequires:  cmake
# nasm is required by aws-lc-sys on x86_64 to compile ASM crypto routines.
# Available in standard Fedora repos; on RHEL/EPEL it lives in CRB (not
# enabled in COPR by default) so we use prebuilt NASM objects there instead
# (see AWS_LC_SYS_PREBUILT_NASM in the %%build section).
%if 0%{?fedora}
%ifarch x86_64
BuildRequires:  nasm
%endif
%endif

%description
mise prepares your development environment before each command runs. It installs
and switches between project tools, loads environment variables, and runs tasks
from the same configuration.

%prep
%autosetup -n %{name}-%{version}
%setup -q -T -D -a 1

%build
# Set up vendored dependencies
mkdir -p .cargo
cp .cargo/config.toml .cargo/config.toml.bak 2>/dev/null || true
cat > .cargo/config.toml << 'CARGO_EOF'
[source.crates-io]
replace-with = "vendored-sources"

[source.vendored-sources]
directory = "vendor"
CARGO_EOF

# aws-lc-sys compiles and links its memcmp compiler probe in one command. It
# intentionally ignores CFLAGS, but still applies Fedora's LDFLAGS, whose
# hardened linker specs produce a PIE executable. Add the matching compiler
# flag so the probe's object file is position-independent as well.
%if 0%{?fedora}
%ifarch x86_64
export LDFLAGS="${LDFLAGS:-} -fPIE"
%endif
%endif

# On RHEL/EPEL x86_64, nasm lives in CRB which is not enabled in COPR
# chroots. Use prebuilt NASM objects bundled inside the aws-lc-sys crate
# instead. This works at all Cargo profile/optimization levels including
# release (unlike AWS_LC_SYS_NO_ASM which is debug-only and panics at
# release profile).
%if 0%{?rhel}
%ifarch x86_64
export AWS_LC_SYS_PREBUILT_NASM=1
%endif
%endif

# CI verifies that the locked dependencies actually compile with mise's MSRV.
cargo build --profile __BUILD_PROFILE__ --frozen --bin mise --ignore-rust-version

%install
mkdir -p %{buildroot}%{_bindir}
cp target/__BUILD_PROFILE__/mise %{buildroot}%{_bindir}/

# Install man page if available
mkdir -p %{buildroot}%{_mandir}/man1
cp man/man1/mise.1 %{buildroot}%{_mandir}/man1/

# Install shell completions
mkdir -p %{buildroot}%{_datadir}/bash-completion/completions
cp completions/mise.bash %{buildroot}%{_datadir}/bash-completion/completions/mise

mkdir -p %{buildroot}%{_datadir}/zsh/site-functions
cp completions/_mise %{buildroot}%{_datadir}/zsh/site-functions/

mkdir -p %{buildroot}%{_datadir}/fish/vendor_completions.d
cp completions/mise.fish %{buildroot}%{_datadir}/fish/vendor_completions.d/

# Disable self-update for package manager installations
mkdir -p %{buildroot}%{_libdir}/mise
cat > %{buildroot}%{_libdir}/mise/mise-self-update-instructions.toml <<'TOML'
message = "To update mise from COPR, run:\n\n  sudo dnf upgrade mise\n"
TOML

%files
%license LICENSE
%doc README.md
%{_bindir}/mise
%{_mandir}/man1/mise.1*
%{_datadir}/bash-completion/completions/mise
%{_datadir}/zsh/site-functions/_mise
%{_datadir}/fish/vendor_completions.d/mise.fish
%{_libdir}/mise/mise-self-update-instructions.toml

%changelog
* __CHANGELOG_DATE__ __MAINTAINER_NAME__ <__MAINTAINER_EMAIL__> - %{version}-1
- New upstream release %{version}
EOF

# Replace placeholders in spec file
CHANGELOG_DATE=$(date +'%a %b %d %Y')
sed -i "s/__PACKAGE_NAME__/${PACKAGE_NAME}/g" "SPECS/${PACKAGE_NAME}.spec"
sed -i "s/__VERSION__/${VERSION}/g" "SPECS/${PACKAGE_NAME}.spec"
sed -i "s/__BUILD_PROFILE__/${BUILD_PROFILE}/g" "SPECS/${PACKAGE_NAME}.spec"
sed -i "s/__CHANGELOG_DATE__/${CHANGELOG_DATE}/g" "SPECS/${PACKAGE_NAME}.spec"
sed -i "s/__MAINTAINER_NAME__/${MAINTAINER_NAME}/g" "SPECS/${PACKAGE_NAME}.spec"
sed -i "s/__MAINTAINER_EMAIL__/${MAINTAINER_EMAIL}/g" "SPECS/${PACKAGE_NAME}.spec"

echo "=== Building Source RPM ==="
# Build source RPM
rpmbuild -bs "SPECS/${PACKAGE_NAME}.spec"

# Copy SRPM to accessible location
SRPM_FILE=$(find SRPMS -name "*.src.rpm" -type f | head -1)
if [ -n "$SRPM_FILE" ]; then
	cp "$SRPM_FILE" "$REPO_ROOT/"
	echo "SRPM created: $REPO_ROOT/$(basename "$SRPM_FILE")"
else
	echo "Error: No SRPM file found"
	exit 1
fi

# Submit to COPR if not in dry-run mode
if [ "$DRY_RUN" != "true" ]; then
	echo "=== Submitting to COPR ==="
	echo "Submitting $(basename "$SRPM_FILE") to COPR project $COPR_OWNER/$COPR_PROJECT"

	# Submit build to COPR. Build a real argv array so chroot values cannot
	# be interpreted as shell syntax, and validate each value against a
	# conservative chroot pattern before forwarding to copr-cli.
	IFS=' ' read -ra chroot_array <<<"$CHROOTS"
	copr_args=("build" "--timeout" "$COPR_BUILD_TIMEOUT")
	if [ "$WAIT_FOR_BUILD" != "true" ]; then
		copr_args+=("--nowait")
	fi
	for chroot in "${chroot_array[@]}"; do
		[ -z "$chroot" ] && continue
		if ! [[ "$chroot" =~ ^[A-Za-z0-9._+-]+$ ]]; then
			echo "Invalid COPR chroot value: $chroot" >&2
			exit 1
		fi
		copr_args+=("--chroot" "$chroot")
	done
	copr_args+=("$COPR_OWNER/$COPR_PROJECT" "$SRPM_FILE")

	copr-cli "${copr_args[@]}"

	echo "Build submitted successfully!"
else
	echo "=== Dry Run Complete ==="
	echo "SRPM built successfully but not submitted to COPR (dry-run mode)"
fi

# Create artifacts directory
mkdir -p "$REPO_ROOT/artifacts"
cp "$SRPM_FILE" "$REPO_ROOT/artifacts/" 2>/dev/null || true
cp "SPECS/${PACKAGE_NAME}.spec" "$REPO_ROOT/artifacts/" 2>/dev/null || true

echo "=== Build Complete ==="
echo "Artifacts available in $REPO_ROOT/artifacts/"
