#!/usr/bin/env bash
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
VERSION="$(tr -d '[:space:]' < "$PROJECT_ROOT/VERSION")"
FFMPEG_VERSION="9.0.1"
WEBP_VERSION="1.6.0"
FFMPEG_SHA256="cf38e0e28c7e5605942c4a77755349b0145804a397af37eb1fb4c77cb237f635"
WEBP_SOURCE_SHA256="e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564"
WEBP_ARM_SHA256="bc6bf84cc70f3f8574fba797d1e4a7dea4feebe9fa4be919f202413ea2b3b8f2"
WEBP_X86_SHA256="f112dd83b420ab2a4b27d46610d9827ddf4200216023281de378647ecca31c2a"
CACHE_DIR="$PROJECT_ROOT/.artifacts/source-cache"
WORK_ROOT="$PROJECT_ROOT/.artifacts/release-work"
DEFAULT_OUTPUT="$PROJECT_ROOT/.artifacts/release-tools/$VERSION"
OUTPUT_DIR="$DEFAULT_OUTPUT"

usage() {
  echo "Usage: scripts/prepare-release-tools.sh [--output PATH]"
}

while (($#)); do
  case "$1" in
    --output)
      [[ $# -ge 2 ]] || { usage >&2; exit 64; }
      OUTPUT_DIR="$2"
      shift 2
      ;;
    -h|--help)
      usage
      exit 0
      ;;
    *)
      usage >&2
      exit 64
      ;;
  esac
done

case "$OUTPUT_DIR" in
  /*) ;;
  *) OUTPUT_DIR="$PROJECT_ROOT/$OUTPUT_DIR" ;;
esac
OUTPUT_PARENT="$(dirname "$OUTPUT_DIR")"
OUTPUT_NAME="$(basename "$OUTPUT_DIR")"
[[ -n "$OUTPUT_NAME" && "$OUTPUT_NAME" != "." && "$OUTPUT_NAME" != ".." ]] || exit 64
mkdir -p "$OUTPUT_PARENT" "$CACHE_DIR" "$WORK_ROOT"
OUTPUT_PARENT="$(cd "$OUTPUT_PARENT" && pwd -P)"
OUTPUT_DIR="$OUTPUT_PARENT/$OUTPUT_NAME"
case "$OUTPUT_DIR" in
  "$PROJECT_ROOT/.artifacts/"*) ;;
  *) echo "Output must stay under $PROJECT_ROOT/.artifacts" >&2; exit 64 ;;
esac
[[ ! -e "$OUTPUT_DIR" && ! -L "$OUTPUT_DIR" ]] || {
  echo "Output already exists: $OUTPUT_DIR" >&2
  exit 73
}

WORK_DIR="$(mktemp -d "$WORK_ROOT/tools.XXXXXX")"
cleanup() {
  local resolved_parent name
  [[ -n "${WORK_DIR:-}" && -d "$WORK_DIR" && ! -L "$WORK_DIR" ]] || return
  resolved_parent="$(cd "$(dirname "$WORK_DIR")" && pwd -P)"
  name="$(basename "$WORK_DIR")"
  [[ "$resolved_parent" == "$WORK_ROOT" && "$name" == tools.* ]] || return
  /bin/rm -R -- "$WORK_DIR"
}
trap cleanup EXIT

fetch_verified() {
  local url="$1" destination="$2" expected="$3" actual
  if [[ ! -f "$destination" || -L "$destination" ]]; then
    curl --fail --location --retry 3 --output "$destination" "$url"
  fi
  actual="$(shasum -a 256 "$destination" | awk '{print $1}')"
  [[ "$actual" == "$expected" ]] || {
    echo "Checksum mismatch for $destination" >&2
    exit 65
  }
}

FFMPEG_ARCHIVE="$CACHE_DIR/ffmpeg-$FFMPEG_VERSION.tar.xz"
WEBP_SOURCE_ARCHIVE="$CACHE_DIR/libwebp-$WEBP_VERSION.tar.gz"
WEBP_ARM_ARCHIVE="$CACHE_DIR/libwebp-$WEBP_VERSION-mac-arm64.tar.gz"
WEBP_X86_ARCHIVE="$CACHE_DIR/libwebp-$WEBP_VERSION-mac-x86-64.tar.gz"
fetch_verified "https://ffmpeg.org/releases/ffmpeg-$FFMPEG_VERSION.tar.xz" "$FFMPEG_ARCHIVE" "$FFMPEG_SHA256"
fetch_verified "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-$WEBP_VERSION.tar.gz" "$WEBP_SOURCE_ARCHIVE" "$WEBP_SOURCE_SHA256"
fetch_verified "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-$WEBP_VERSION-mac-arm64.tar.gz" "$WEBP_ARM_ARCHIVE" "$WEBP_ARM_SHA256"
fetch_verified "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-$WEBP_VERSION-mac-x86-64.tar.gz" "$WEBP_X86_ARCHIVE" "$WEBP_X86_SHA256"

SDK_PATH="$(xcrun --sdk macosx --show-sdk-path)"
CLANG="$(xcrun --find clang)"
JOBS="$(sysctl -n hw.logicalcpu 2>/dev/null || echo 4)"
COMMON_CONFIG=(
  --target-os=darwin
  --cc="$CLANG"
  --host-cc="$CLANG"
  --pkg-config="$SCRIPT_DIR/libxml2-pkg-config.sh"
  --disable-autodetect
  --disable-doc
  --disable-debug
  --disable-ffplay
  --disable-avdevice
  --disable-decoders
  --disable-encoders
  --disable-filters
  --disable-hwaccels
  --disable-demuxers
  --disable-muxers
  --disable-protocols
  --disable-parsers
  --disable-bsfs
  --enable-demuxer=aac,ac3,dash,eac3,flac,flv,h264,hevc,hls,matroska,mov,mp3,mpegts,ogg,wav
  --enable-muxer=mov,mp4
  --enable-protocol=concat,crypto,data,file,http,https,httpproxy,subfile,tcp,tls
  --enable-parser=aac,aac_latm,ac3,av1,h264,hevc,mpegaudio,opus,vorbis,vp8,vp9
  --enable-bsf=aac_adtstoasc,h264_mp4toannexb,hevc_mp4toannexb,vp9_superframe
  --disable-shared
  --enable-static
  --enable-libxml2
  --enable-securetransport
  --enable-zlib
)

build_ffmpeg_arch() {
  local arch="$1"
  local source_dir="$WORK_DIR/ffmpeg-$arch"
  local configure_args=("${COMMON_CONFIG[@]}")
  mkdir -p "$source_dir"
  tar -xJf "$FFMPEG_ARCHIVE" -C "$source_dir" --strip-components=1
  if [[ "$(uname -m)" != "$arch" ]]; then
    configure_args+=(--enable-cross-compile --cpu=generic)
  fi
  if [[ "$arch" == "x86_64" ]] && ! command -v nasm >/dev/null 2>&1; then
    configure_args+=(--disable-x86asm)
  fi
  (
    cd "$source_dir"
    PATH="/usr/bin:/bin:/usr/sbin:/sbin" ZHUA_SDK_PATH="$SDK_PATH" ./configure \
      "${configure_args[@]}" \
      --arch="$arch" \
      --sysroot="$SDK_PATH" \
      --host-cflags="--sysroot=$SDK_PATH" \
      --host-ldflags="--sysroot=$SDK_PATH" \
      --extra-cflags="-I$SDK_PATH/usr/include/libxml2 -arch $arch -mmacosx-version-min=12.0" \
      --extra-ldflags="-lxml2 -arch $arch -mmacosx-version-min=12.0"
    PATH="/usr/bin:/bin:/usr/sbin:/sbin" make -j"$JOBS" ffmpeg ffprobe
  )
}

build_ffmpeg_arch arm64
build_ffmpeg_arch x86_64

mkdir -p "$WORK_DIR/webp-arm" "$WORK_DIR/webp-x86" "$WORK_DIR/result/Tools" \
  "$WORK_DIR/result/Licenses/FFmpeg" "$WORK_DIR/result/Licenses/libwebp" \
  "$WORK_DIR/result/Sources"
tar -xzf "$WEBP_ARM_ARCHIVE" -C "$WORK_DIR/webp-arm" --strip-components=1
tar -xzf "$WEBP_X86_ARCHIVE" -C "$WORK_DIR/webp-x86" --strip-components=1

for name in ffmpeg ffprobe; do
  lipo -create \
    "$WORK_DIR/ffmpeg-arm64/$name" \
    "$WORK_DIR/ffmpeg-x86_64/$name" \
    -output "$WORK_DIR/result/Tools/$name"
done
lipo -create \
  "$WORK_DIR/webp-arm/bin/cwebp" \
  "$WORK_DIR/webp-x86/bin/cwebp" \
  -output "$WORK_DIR/result/Tools/cwebp"
chmod 0755 "$WORK_DIR/result/Tools/ffmpeg" "$WORK_DIR/result/Tools/ffprobe" \
  "$WORK_DIR/result/Tools/cwebp"

tar -xOf "$FFMPEG_ARCHIVE" "ffmpeg-$FFMPEG_VERSION/LICENSE.md" > "$WORK_DIR/result/Licenses/FFmpeg/LICENSE.md"
tar -xOf "$FFMPEG_ARCHIVE" "ffmpeg-$FFMPEG_VERSION/COPYING.LGPLv2.1" > "$WORK_DIR/result/Licenses/FFmpeg/COPYING.LGPLv2.1"
tar -xOf "$FFMPEG_ARCHIVE" "ffmpeg-$FFMPEG_VERSION/COPYING.LGPLv3" > "$WORK_DIR/result/Licenses/FFmpeg/COPYING.LGPLv3"
tar -xOf "$WEBP_SOURCE_ARCHIVE" "libwebp-$WEBP_VERSION/COPYING" > "$WORK_DIR/result/Licenses/libwebp/COPYING"
tar -xOf "$WEBP_SOURCE_ARCHIVE" "libwebp-$WEBP_VERSION/PATENTS" > "$WORK_DIR/result/Licenses/libwebp/PATENTS"
cp "$FFMPEG_ARCHIVE" "$WEBP_SOURCE_ARCHIVE" "$WORK_DIR/result/Sources/"
cp "$SCRIPT_DIR/prepare-release-tools.sh" "$WORK_DIR/result/Sources/"

{
  echo "Zhua Helper $VERSION third-party build record"
  echo
  echo "FFmpeg $FFMPEG_VERSION: $FFMPEG_SHA256"
  echo "libwebp $WEBP_VERSION source: $WEBP_SOURCE_SHA256"
  echo "libwebp $WEBP_VERSION arm64 binary: $WEBP_ARM_SHA256"
  echo "libwebp $WEBP_VERSION x86_64 binary: $WEBP_X86_SHA256"
  echo
  printf 'FFmpeg configure options:'
  printf ' %q' "${COMMON_CONFIG[@]}"
  echo ' --arch=<arch> --sysroot=<macOS SDK> --extra-cflags="-arch <arch> -mmacosx-version-min=12.0" --extra-ldflags="-arch <arch> -mmacosx-version-min=12.0"'
  echo
  echo "No --enable-gpl or --enable-nonfree option is used."
} > "$WORK_DIR/result/BUILD-RECORD.txt"

for binary in "$WORK_DIR/result/Tools/"*; do
  architectures="$(lipo -archs "$binary")"
  [[ "$architectures" == *arm64* && "$architectures" == *x86_64* ]] || {
    echo "Missing universal architecture: $binary ($architectures)" >&2
    exit 70
  }
  if otool -L "$binary" | rg -q '/opt/homebrew|/usr/local|@rpath'; then
    echo "Non-system dependency found in $binary" >&2
    otool -L "$binary" >&2
    exit 70
  fi
done

mv "$WORK_DIR/result" "$OUTPUT_DIR"
echo "Prepared universal release tools: $OUTPUT_DIR"
