#!/bin/zsh
set -euo pipefail

usage() { echo "Usage: install-framecap.sh --manifest URL [--version VERSION] [--install-dir DIR] [--dry-run]"; }
MANIFEST="";VERSION="";INSTALL_DIR="$HOME/Applications";DRY_RUN=0
while (( $# )); do
  case "$1" in
    --manifest) MANIFEST="$2";shift 2;;
    --version) VERSION="$2";shift 2;;
    --install-dir) INSTALL_DIR="$2";shift 2;;
    --dry-run) DRY_RUN=1;shift;;
    -h|--help) usage;exit 0;;
    *) usage >&2;exit 64;;
  esac
done
[[ "$MANIFEST" == https://* || "$MANIFEST" == file://* ]] || { echo "Manifest must use HTTPS or file://" >&2;exit 64; }
WORK="$(mktemp -d "${TMPDIR:-/tmp}/framecap-install.XXXXXX")"
MOUNT="";TARGET="";BACKUP="";INSTALLED=0
cleanup(){
  STATUS=$?
  [[ -z "$MOUNT" ]] || hdiutil detach "$MOUNT" -quiet || true
  if (( STATUS != 0 && INSTALLED == 1 )) && [[ -n "$TARGET" ]]; then
    rm -rf "$TARGET"
    [[ -z "$BACKUP" ]] || mv "$BACKUP" "$TARGET"
    echo "Install failed; previous App restored." >&2
  fi
  rm -rf "$WORK"
};trap cleanup EXIT
curl --fail --location --proto '=https,file' --tlsv1.2 --output "$WORK/manifest.json" "$MANIFEST"
read_field(){ plutil -extract "$1" raw -o - "$WORK/manifest.json"; }
RELEASE_VERSION="$(read_field version)";[[ -z "$VERSION" || "$VERSION" == "$RELEASE_VERSION" ]] || { echo "Requested version does not match manifest" >&2;exit 65; }
DMG_URL="$(read_field download.url)";EXPECTED_SHA="$(read_field download.sha256)";MANIFEST_TEAM="$(read_field signing.teamId)";EXPECTED_TEAM="7D6ZA6VDJC"
[[ "$MANIFEST_TEAM" == "$EXPECTED_TEAM" ]] || { echo "Manifest is not for the trusted Framecap release team" >&2;exit 66; }
[[ "$DMG_URL" == https://* || "$DMG_URL" == file://* ]] || { echo "DMG URL must use HTTPS or file://" >&2;exit 65; }
if (( DRY_RUN )); then echo "Would install Framecap $RELEASE_VERSION to $INSTALL_DIR/Framecap.app";exit 0;fi
curl --fail --location --proto '=https,file' --tlsv1.2 --continue-at - --output "$WORK/Framecap.dmg" "$DMG_URL"
ACTUAL_SHA="$(shasum -a 256 "$WORK/Framecap.dmg" | awk '{print $1}')";[[ "$ACTUAL_SHA" == "$EXPECTED_SHA" ]] || { echo "SHA-256 mismatch" >&2;exit 66; }
MOUNT="$(hdiutil attach "$WORK/Framecap.dmg" -nobrowse -readonly | awk '/\/Volumes\// {$1=$2="";sub(/^  */,"");print;exit}')"
APP="$MOUNT/Framecap.app";[[ -d "$APP" ]] || { echo "DMG does not contain Framecap.app" >&2;exit 65; }
codesign --verify --deep --strict "$APP";spctl --assess --type execute "$APP"
TEAM="$(codesign -dv --verbose=4 "$APP" 2>&1 | awk -F= '/^TeamIdentifier=/{print $2}')";[[ "$TEAM" == "$EXPECTED_TEAM" ]] || { echo "Developer Team ID mismatch" >&2;exit 66; }
IDENTIFIER="$(plutil -extract CFBundleIdentifier raw -o - "$APP/Contents/Info.plist")";[[ "$IDENTIFIER" == "dev.framecap.app" ]] || { echo "Bundle ID mismatch" >&2;exit 66; }
pgrep -x Framecap >/dev/null && { echo "Quit Framecap before installing to protect open edits" >&2;exit 69; }
command -v python3 >/dev/null || echo "Warning: GUI installed, but CLI/MCP need Python 3.8+" >&2
mkdir -p "$INSTALL_DIR";TARGET="$INSTALL_DIR/Framecap.app"
LINK="$HOME/.local/bin/framecap";[[ ! -e "$LINK" || -L "$LINK" ]] || { echo "Refusing to replace non-symlink $LINK" >&2;exit 67; }
if [[ -d "$TARGET" ]]; then BACKUP="$INSTALL_DIR/Framecap.app.rollback-$(date +%Y%m%d%H%M%S)";ditto "$TARGET" "$BACKUP";fi
ditto "$APP" "$WORK/Framecap.app";rm -rf "$TARGET";mv "$WORK/Framecap.app" "$TARGET"
INSTALLED=1
mkdir -p "$HOME/.local/bin"
ln -sfn "$TARGET/Contents/Resources/Automation/framecap" "$LINK"
mkdir -p "$HOME/Library/Application Support/Framecap"
printf '%s\n' "{\"version\":\"$RELEASE_VERSION\",\"app\":\"$TARGET\",\"cli\":\"$LINK\",\"rollback\":\"$BACKUP\"}" > "$HOME/Library/Application Support/Framecap/install.json"
echo "Installed Framecap $RELEASE_VERSION at $TARGET"
INSTALLED=0
