#!/usr/bin/env bash
# OmniVoice Studio — AppImage launcher
#
# Issue #56: AppImage shows a white screen on Fedora 44 / Ubuntu 24.04.
# Root cause: WebKitGTK 2.44.x / 2.46.x has a compositing-path regression on
# Wayland that blanks the surface on first paint. Setting
# WEBKIT_DISABLE_COMPOSITING_MODE=1 forces WebKit to use a software fallback
# that works correctly.
#
# We detect the WebKit version via pkg-config and ONLY set the env var on the
# known-broken ranges. Setting it unconditionally regresses healthy WebKit
# versions (2.48+) where the compositing path works fine.
#
# This file is copied into the AppImage staging directory by
# scripts/inject-apprun.sh (wired into Tauri's beforeBundleCommand). See
# .planning/decisions/apprun-strategy.md for the decision rationale.

set -euo pipefail

HERE="$(dirname -- "$(readlink -f -- "$0")")"

# Sourced by AppRun.test.sh — keep this function pure so unit tests can stub
# `pkg-config`, source the file, call _detect_webkit_workaround, and inspect
# the resulting environment without exec'ing the binary.
#
# Version source (#961 follow-up): the WebKitGTK that actually RUNS is the
# BUNDLED copy (LD_LIBRARY_PATH below puts $HERE/usr/lib first) — NOT the
# host's. Asking the host's pkg-config therefore reads the wrong number
# whenever host and bundle diverge (e.g. a user who builds from source has
# dev packages installed, so pkg-config answers with their system's healthy
# 2.48 while the bundle runs an older lib — skipping a workaround the running
# library needs). inject-apprun.sh stamps the bundled version into
# .bundled-webkitgtk-version at build time, where it is knowable by
# construction; the host pkg-config path survives only as a fallback for
# bundles predating the stamp. OMNIVOICE_APPRUN_WK_MARKER exists for the
# unit tests to point at a fixture marker.
_detect_webkit_workaround() {
  local wk_version="0.0"
  local marker="${OMNIVOICE_APPRUN_WK_MARKER:-$HERE/.bundled-webkitgtk-version}"
  if [ -r "$marker" ]; then
    # Empty/unreadable marker content → "0.0" (unknown) → fail-safe workaround,
    # same philosophy as the missing-pkg-config branch below.
    wk_version="$(cat "$marker" 2>/dev/null | tr -d '[:space:]')"
    [ -n "$wk_version" ] || wk_version="0.0"
  elif command -v pkg-config >/dev/null 2>&1; then
    wk_version="$(pkg-config --modversion webkit2gtk-4.1 2>/dev/null \
               || pkg-config --modversion webkit2gtk-4.0 2>/dev/null \
               || echo "0.0")"
  fi
  case "$wk_version" in
    2.44.*|2.46.*|0.0)
      export WEBKIT_DISABLE_COMPOSITING_MODE=1
      ;;
  esac
}

_detect_webkit_workaround

# ── Bundled-vs-system WebKit priority (#1258, #1244) ───────────────────────
#
# The bundled WebKitGTK links against the HOST's Mesa — the AppImage ships no
# libEGL of its own. That pairing is only tested for the Mesa of the build
# runner, and it breaks outright as hosts move ahead: on Mesa >= 26.1 the
# Ubuntu-built libwebkit2gtk calls eglGetPlatformDisplay() with parameters the
# newer driver rejects, and the app dies before it renders anything:
#
#     Could not create default EGL display: EGL_BAD_PARAMETER. Aborting...
#     blank window detected (#root children = -2); reload 1/3
#
# No env var helps, because the failure is in EGL display creation — it happens
# before WebKit consults any rendering-path flag. #1258 confirmed
# WEBKIT_DISABLE_DMABUF_RENDERER, WEBKIT_DMABUF_RENDERER_FORCE_SHM,
# WEBKIT_SKIA_ENABLE_CPU_RENDERING, EGL_PLATFORM=surfaceless and
# MESA_LOADER_DRIVER_OVERRIDE=swrast all fail identically.
#
# What DOES work on those machines is the host's own WebKitGTK, because the
# distro compiled it against the very Mesa it ships — which is why building
# from source works on the exact hardware where the AppImage does not.
#
# Chasing the build runner's WebKit version (#961 bumped 22.04 → 24.04) cannot
# fix this class: whatever we bundle is frozen, and host Mesa keeps moving. So
# when the host has a WebKitGTK at least as new as ours, let its copy win.
#
# Note it is NOT enough to merely stop prepending the bundle: LD_LIBRARY_PATH is
# searched ahead of the linker's default paths no matter where in that variable
# a directory sits, so on a normal launch (empty LD_LIBRARY_PATH) the bundle
# would still be the only explicit directory and still win. The host's WebKit
# libdir has to be named explicitly, ahead of ours (#1258 review).

#: Directory holding the host's libwebkit2gtk-4.1.so.0, or empty.
_system_webkit_libdir() {
  local dir
  # pkg-config is exact, but only present with the -dev package installed.
  dir="$(pkg-config --variable=libdir webkit2gtk-4.1 2>/dev/null || echo "")"
  if [ -n "$dir" ] && [ -e "$dir/libwebkit2gtk-4.1.so.0" ]; then
    printf '%s' "$dir"
    return 0
  fi
  # Runtime-only hosts (an end user who never installed -dev) have the library
  # but no .pc file. ldconfig knows where it is (#1258 review).
  if command -v ldconfig >/dev/null 2>&1; then
    dir="$(ldconfig -p 2>/dev/null \
           | awk '/libwebkit2gtk-4\.1\.so\.0 /{print $NF; exit}')"
    if [ -n "$dir" ] && [ -e "$dir" ]; then
      printf '%s' "$(dirname -- "$dir")"
      return 0
    fi
  fi
  return 1
}

#: Host WebKitGTK version, or empty when it can't be established.
_system_webkit_version() {
  pkg-config --modversion webkit2gtk-4.1 2>/dev/null || echo ""
}

_prefer_system_webkit() {
  # An explicit override for the case we cannot decide automatically: a host
  # with the runtime but no pkg-config metadata, where the version is unknowable
  # from here. Documented in docs/install/linux.md.
  if [ "${OMNIVOICE_PREFER_SYSTEM_WEBKIT:-}" = "1" ]; then
    return 0
  fi
  [ "${OMNIVOICE_PREFER_SYSTEM_WEBKIT:-}" = "0" ] && return 1

  # Only meaningful when we know what we bundled; an unstamped bundle keeps
  # the old ordering rather than guessing.
  local marker="${OMNIVOICE_APPRUN_WK_MARKER:-$HERE/.bundled-webkitgtk-version}"
  [ -r "$marker" ] || return 1
  local bundled
  bundled="$(cat "$marker" 2>/dev/null | tr -d '[:space:]')"
  [ -n "$bundled" ] && [ "$bundled" != "0.0" ] || return 1

  local system
  system="$(_system_webkit_version)"
  # Unknown host version → keep the bundle. Preferring an unverified copy could
  # hand the user an OLDER WebKit than we ship, which is the #961 regression;
  # OMNIVOICE_PREFER_SYSTEM_WEBKIT=1 is the escape hatch for that host.
  [ -n "$system" ] || return 1

  # `sort -V` puts the older version first; the host wins only on >=.
  [ "$(printf '%s\n%s\n' "$bundled" "$system" | sort -V | head -1)" = "$bundled" ]
}

_SYS_WK_LIBDIR=""
if _prefer_system_webkit; then
  _SYS_WK_LIBDIR="$(_system_webkit_libdir || echo "")"
fi

if [ -n "$_SYS_WK_LIBDIR" ]; then
  # The host's WebKit resolves first; ours fills only what the host lacks.
  export LD_LIBRARY_PATH="${_SYS_WK_LIBDIR}:${HERE}/usr/lib:${LD_LIBRARY_PATH:-}"
  # The workaround above was chosen for the BUNDLED version; re-decide it
  # against the copy that will actually run.
  unset WEBKIT_DISABLE_COMPOSITING_MODE
  case "$(_system_webkit_version)" in
    2.44.*|2.46.*|"") export WEBKIT_DISABLE_COMPOSITING_MODE=1 ;;
  esac
else
  # Standard AppImage env that Tauri's auto-generated AppRun would have set.
  export LD_LIBRARY_PATH="${HERE}/usr/lib:${LD_LIBRARY_PATH:-}"
fi
export XDG_DATA_DIRS="${HERE}/usr/share:${XDG_DATA_DIRS:-/usr/local/share:/usr/share}"

exec "${HERE}/usr/bin/omnivoice-studio" "$@"
