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

# Rebuilds VLCKit 3.6.0 from the exact VideoLAN commits behind the CocoaPods
# binaries, plus Zyryn's narrow iOS/tvOS filesystem-classification patch.
# Build products stay in an ignored local cache and are verified before the
# delivery scripts are allowed to stage them into Pods.

cd "$(dirname "$0")/../.."

requested_platform="${1:-all}"
case "$requested_platform" in
ios | tvos | all) ;;
*)
  echo "usage: $0 <ios|tvos|all>" >&2
  exit 64
  ;;
esac

readonly vlckit_commit="c73b779f2d1e3d3c1598a27811679ce2c1a005db"
readonly vlc_commit="dd8bfdbabe8ae3974ca3864ad3125879f523e3a2"
readonly patch_relative="scripts/appstore/patches/vlckit-3.6.0-no-fstatfs.patch"
readonly patch_path="$PWD/$patch_relative"
readonly patch_sha256="fb5c003923c20129b6210b63b942d8bcaa6a1fc8406169e1201676c42442393b"
readonly build_patch_relative="scripts/appstore/patches/vlckit-3.6.0-xcode26.patch"
readonly build_patch_path="$PWD/$build_patch_relative"
readonly build_patch_sha256="2617b97a024d445c614cfc8546db3f5996cb9df6c5116418d8819efd42e93eda"
readonly vlckit_build_patch_relative="scripts/appstore/patches/vlckit-3.6.0-build-script.patch"
readonly vlckit_build_patch_path="$PWD/$vlckit_build_patch_relative"
readonly vlckit_build_patch_sha256="9e5a814b0ef70994c84f305cc3117d26f328e5ae1b96e9b301e006e9eb9233f7"
readonly cache_root="${ZYRYN_CUSTOM_VLCKIT_DIR:-$PWD/.appstore-cache/vlckit-3.6.0-c73b779f-dd8bfdba}"
readonly source_root="${ZYRYN_VLCKIT_SOURCE_DIR:-$cache_root/source}"
readonly compatibility_bin="$cache_root/tool-compat"
readonly jobs="${MAKE_JOBS:-8}"
readonly package_only="${ZYRYN_VLCKIT_PACKAGE_ONLY:-0}"

if [ "$package_only" != "0" ] && [ "$package_only" != "1" ]; then
  echo "[appstore] ZYRYN_VLCKIT_PACKAGE_ONLY must be 0 or 1" >&2
  exit 64
fi

actual_patch_sha="$(shasum -a 256 "$patch_path" | awk '{print $1}')"
actual_build_patch_sha="$(shasum -a 256 "$build_patch_path" | awk '{print $1}')"
actual_vlckit_build_patch_sha="$(shasum -a 256 "$vlckit_build_patch_path" | awk '{print $1}')"
if [ "$actual_patch_sha" != "$patch_sha256" ] || \
  [ "$actual_build_patch_sha" != "$build_patch_sha256" ] || \
  [ "$actual_vlckit_build_patch_sha" != "$vlckit_build_patch_sha256" ]; then
  echo "[appstore] VLCKit patch checksum changed" >&2
  echo "[appstore] review the source change, then update both build and verification pins" >&2
  exit 1
fi

prepare_source() {
  if [ ! -d "$source_root/.git" ]; then
    if [ -e "$source_root" ]; then
      echo "[appstore] source path exists but is not a Git checkout: $source_root" >&2
      exit 1
    fi
    mkdir -p "$(dirname "$source_root")"
    git clone --depth 1 --branch 3.6.0 \
      https://code.videolan.org/videolan/VLCKit.git "$source_root"
    actual_vlckit_commit="$(git -C "$source_root" rev-parse HEAD)"
    if [ "$actual_vlckit_commit" != "$vlckit_commit" ]; then
      echo "[appstore] VLCKit tag resolved to $actual_vlckit_commit, expected $vlckit_commit" >&2
      exit 1
    fi
    git -C "$source_root" apply "$vlckit_build_patch_path"

    git clone --depth 1 --branch 3.0.21 \
      https://code.videolan.org/videolan/vlc.git "$source_root/libvlc/vlc"
    actual_vlc_commit="$(git -C "$source_root/libvlc/vlc" rev-parse HEAD)"
    if [ "$actual_vlc_commit" != "$vlc_commit" ]; then
      echo "[appstore] VLC tag resolved to $actual_vlc_commit, expected $vlc_commit" >&2
      exit 1
    fi

    git -C "$source_root/libvlc/vlc" am "$source_root"/libvlc/patches/*.patch
    git -C "$source_root/libvlc/vlc" apply "$patch_path"
    git -C "$source_root/libvlc/vlc" apply "$build_patch_path"
    printf '%s\n%s\n%s\n%s\n%s\n' \
      "$vlckit_commit" "$vlc_commit" "$patch_sha256" "$build_patch_sha256" \
      "$vlckit_build_patch_sha256" \
      >"$source_root/.zyryn-source-identity"
  fi

  expected_identity="$(printf '%s\n%s\n%s\n%s\n%s' \
    "$vlckit_commit" "$vlc_commit" "$patch_sha256" "$build_patch_sha256" \
    "$vlckit_build_patch_sha256")"
  actual_identity="$(cat "$source_root/.zyryn-source-identity" 2>/dev/null || true)"
  if [ "$actual_identity" != "$expected_identity" ]; then
    echo "[appstore] cached VLCKit source identity is missing or stale: $source_root" >&2
    exit 1
  fi
  actual_vlckit_commit="$(git -C "$source_root" rev-parse HEAD)"
  actual_vlc_base="$(git -C "$source_root/libvlc/vlc" rev-list --max-parents=0 HEAD)"
  if [ "$actual_vlckit_commit" != "$vlckit_commit" ] || [ "$actual_vlc_base" != "$vlc_commit" ]; then
    echo "[appstore] cached VLCKit/VLC Git identity does not match the reviewed commits" >&2
    exit 1
  fi
  if ! git -C "$source_root" apply --reverse --check "$vlckit_build_patch_path"; then
    echo "[appstore] cached VLCKit source does not contain the reviewed build-script patch" >&2
    exit 1
  fi
  if ! git -C "$source_root/libvlc/vlc" apply --reverse --check "$patch_path"; then
    echo "[appstore] cached VLC source does not contain the reviewed privacy patch" >&2
    exit 1
  fi
  if ! git -C "$source_root/libvlc/vlc" apply --reverse --check "$build_patch_path"; then
    echo "[appstore] cached VLC source does not contain the reviewed Xcode compatibility patch" >&2
    exit 1
  fi
}

prepare_checksum_wrapper() {
  mkdir -p "$compatibility_bin"
  printf '%s\n' '#!/bin/sh' 'exec /usr/bin/shasum -a 512 "$@"' \
    >"$compatibility_bin/sha512sum"
  chmod 755 "$compatibility_bin/sha512sum"
}

write_provenance() {
  local package_root="$1"
  local platform="$2"
  local xcode_version
  xcode_version="$(xcodebuild -version | tr '\n' ' ')"
  ruby -rjson -e '
    path, vlckit, vlc, patch, patch_sha, build_patch, build_patch_sha,
      vlckit_build_patch, vlckit_build_patch_sha, platform, xcode = ARGV
    data = {
      "vlckit_commit" => vlckit,
      "vlc_commit" => vlc,
      "patch" => patch,
      "patch_sha256" => patch_sha,
      "build_patch" => build_patch,
      "build_patch_sha256" => build_patch_sha,
      "vlckit_build_patch" => vlckit_build_patch,
      "vlckit_build_patch_sha256" => vlckit_build_patch_sha,
      "platform" => platform,
      "xcode" => xcode.strip,
      "source" => "https://code.videolan.org/videolan/VLCKit/-/tree/3.6.0",
      "license_notice" => "https://zyryn.com/open-source"
    }
    File.write(path, JSON.pretty_generate(data) + "\n")
  ' "$package_root/provenance.json" "$vlckit_commit" "$vlc_commit" \
    "$patch_relative" "$patch_sha256" \
    "$build_patch_relative" "$build_patch_sha256" \
    "$vlckit_build_patch_relative" "$vlckit_build_patch_sha256" \
    "$platform" "$xcode_version"
}

package_framework() {
  local platform="$1"
  local name="$2"
  local source_xcframework="$source_root/build/$name.xcframework"
  local package_root="$cache_root/$platform"
  local staging="$cache_root/.${platform}-stage-$$"

  if [ ! -d "$source_xcframework" ]; then
    echo "[appstore] build did not produce $source_xcframework" >&2
    exit 1
  fi
  if [ -e "$staging" ]; then
    echo "[appstore] refusing existing package staging path: $staging" >&2
    exit 1
  fi
  trap 'rm -rf "$staging"' EXIT
  mkdir -p "$staging"
  /usr/bin/ditto "$source_xcframework" "$staging/$name.xcframework"
  /usr/bin/ditto "$source_root/COPYING" "$staging/COPYING.txt"
  write_provenance "$staging" "$platform"
  ruby scripts/appstore/lib/verify_custom_vlckit.rb "$platform" "$staging"
  rm -rf "$package_root"
  mv "$staging" "$package_root"
  trap - EXIT
  ruby scripts/appstore/lib/verify_custom_vlckit.rb "$platform" "$package_root"
}

prepare_source
prepare_checksum_wrapper

if [ "$requested_platform" = "ios" ] || [ "$requested_platform" = "all" ]; then
  if [ "$package_only" = "0" ]; then
    echo "[appstore] building MobileVLCKit 3.6.0 from pinned source"
    (
      cd "$source_root"
      env -u DEBUG MAKE_JOBS="$jobs" VLC_PATH="$compatibility_bin" \
        ac_cv_func_pipe2=no ./buildMobileVLCKit.sh -nf
    )
  fi
  package_framework ios MobileVLCKit
fi

if [ "$requested_platform" = "tvos" ] || [ "$requested_platform" = "all" ]; then
  if [ "$package_only" = "0" ]; then
    echo "[appstore] building TVVLCKit 3.6.0 from pinned source"
    (
      cd "$source_root"
      env -u DEBUG MAKE_JOBS="$jobs" VLC_PATH="$compatibility_bin" \
        ac_cv_func_pipe2=no ./buildMobileVLCKit.sh -ntf
    )
  fi
  package_framework tvos TVVLCKit
fi

echo "[appstore] custom VLCKit cache is ready: $cache_root"
