#!/usr/bin/env bash
set -Eeuo pipefail
umask 077
[[ $EUID -ne 0 ]] || { echo 'Launch AMC Secure SignX Setup as the desktop user.'; exit 1; }
ICON=/usr/share/icons/hicolor/512x512/apps/amc-secure-signx-setup.png
[[ -f "$ICON" ]] || ICON=/usr/share/pixmaps/amc-secure-signx-setup.png
[[ -f "$ICON" ]] || ICON=/usr/share/icons/hicolor/256x256/apps/amc-secure-signx-setup.png
# Prefer AMC shield for every setup window and the launcher taskbar entry.
export BAMF_DESKTOP_FILE_HINT=/usr/share/applications/amc-secure-signx-setup.desktop
# GTK class must match setup .desktop StartupWMClass so the dock shows AMC shield, not a generic mark.
zenity_amc(){ zenity --class=amc-secure-signx-setup --name=amc-secure-signx-setup --window-icon="$ICON" "$@"; }

# Friendly progress only — never stream apt/package/path/command lines into the UI.
friendly_setup_phase() {
  local line="${1:-}"
  local lower
  lower="$(printf '%s' "$line" | tr '[:upper:]' '[:lower:]')"
  if [[ "$lower" == *'installed amc secure'* || "$lower" == *'opening amc secure'* ]]; then
    printf '%s\n' 'Finalizing desktop branding…'
  elif [[ "$lower" == *'verifying'* || "$lower" == *'complete package'* ]]; then
    printf '%s\n' 'Verifying signed SignX package…'
  elif [[ "$lower" == *'administrator'* || "$lower" == *'approving ubuntu'* || "$lower" == *'requesting ubuntu'* ]]; then
    printf '%s\n' 'Waiting for Ubuntu administrator approval…'
  elif [[ "$lower" == *'preparing ubuntu'* || "$lower" == *'installing missing'* ]]; then
    printf '%s\n' 'Installing AMC Secure SignX…'
  elif [[ "$lower" == *'usb'* || "$lower" == *'token'* || "$lower" == *'driver'* ]]; then
    printf '%s\n' 'Configuring USB DSC access…'
  elif [[ "$lower" == *'removing superseded'* ]]; then
    printf '%s\n' 'Preparing update (registration retained)…'
  else
    printf '%s\n' 'Installing AMC Secure SignX…'
  fi
}

action=Install
if [[ -d /opt/amc-secure-signx ]]; then
  action="$(zenity_amc --list --radiolist --title='AMC Secure SignX — Setup' --width=520 --height=280 \
    --column=Select --column=Action TRUE 'Update / Repair' FALSE Uninstall \
    --text=$'Keep registration and documents on this PC.\nClose SignX before uninstalling.')" || exit 0
fi
if [[ "$action" == Uninstall ]]; then
  zenity_amc --question --title='Uninstall AMC Secure SignX?' --width=480 \
    --text=$'Remove the SignX application?\n\nDocuments, reports and registration stay on this PC.\nClose SignX first.' || exit 0
  if pkexec /usr/bin/bash /usr/share/amc-secure-signx-setup/uninstall.sh; then
    zenity_amc --info --title='AMC Secure SignX' --text='Application removed. Documents and user settings were retained.'
  else
    zenity_amc --error --title='AMC Secure SignX' --text='Uninstall did not complete. Close SignX and retry. Administrator approval is required.'
    exit 1
  fi
  exit 0
fi
zenity_amc --question --title='AMC Secure SignX Setup' --width=540 \
  --text=$'Install or repair AMC Secure SignX?\n\n• Offline-capable package included\n• First activation needs court HTTPS allowlist\n• Proxy is auto-detected\n• Existing registration and documents are retained\n\nUbuntu will ask for administrator approval once.' || exit 0

state="${XDG_STATE_HOME:-$HOME/.local/state}/amc-secure-signx"
mkdir -p "$state"
if [[ -f /usr/share/amc-secure-signx-setup/court-network.sh ]]; then
  # shellcheck disable=SC1091
  source /usr/share/amc-secure-signx-setup/court-network.sh
  amc_signx_apply_proxy_env || true
elif [[ -f "$(dirname "$0")/court-network.sh" ]]; then
  # shellcheck disable=SC1090
  source "$(dirname "$0")/court-network.sh"
  amc_signx_apply_proxy_env || true
fi

hyp2003_zip=""
existing_driver=""
auto_zip=""
for candidate in \
  "/opt/amc-secure-signx/current/driver/libcastle_v2.so.1.0.0" \
  "$HOME/.config/amc-secure-signx/driver/libcastle_v2.so.1.0.0"
do
  if [[ -f "$candidate" && -r "$candidate" ]]; then existing_driver="$candidate"; break; fi
done
for candidate in \
  "$HOME/Downloads/HYP2003-Linux-x86_64-FIPS140-3.zip" \
  "$HOME/Downloads/HYP2003-Linux-x86_64-FIPS140-3 (1).zip" \
  "$HOME/Downloads/HYP2003-Linux-x86_64-FIPS140-3 (2).zip" \
  "$HOME/Desktop/HYP2003-Linux-x86_64-FIPS140-3.zip" \
  "$HOME/Downloads/HYP2003-Linux-x86_64.zip" \
  "$HOME/Downloads/HYP2003-Linux-x86_64 (1).zip" \
  "$HOME/Downloads/HYP2003-Linux-x86_64 (2).zip" \
  "$HOME/Desktop/HYP2003-Linux-x86_64.zip"
do
  if [[ -f "$candidate" && -r "$candidate" ]]; then auto_zip="$candidate"; break; fi
done
bundled_driver_marker=/usr/share/amc-secure-signx-setup/driver-bundled
payload_has_driver=0
if [[ -f "$bundled_driver_marker" ]]; then
  payload_has_driver=1
elif [[ -f /usr/share/amc-secure-signx-setup/payload.tar.gz ]] && tar -tzf /usr/share/amc-secure-signx-setup/payload.tar.gz 2>/dev/null | grep -q 'signx/driver/libcastle_v2.so.1.0.0'; then
  payload_has_driver=1
fi
if ((payload_has_driver==1)) && [[ -z "$auto_zip" ]]; then
  zenity_amc --info --width=520 --title='USB DSC ready' \
    --text=$'USB DSC support is included.\nAccess is configured automatically — no separate driver setup is required.'
elif [[ -n "$existing_driver" && -z "$auto_zip" ]]; then
  zenity_amc --info --width=480 --title='USB DSC ready' --text='An existing USB DSC driver on this workstation will be kept.'
elif [[ -n "$auto_zip" ]]; then
  if zenity_amc --question --width=520 --title='USB DSC update' \
    --text=$'An optional driver update ZIP was found in Downloads.\n\nUse it to refresh USB DSC support?\n(Otherwise the included driver is used.)'; then
    cp -f -- "$auto_zip" "$state/hyp2003-incoming.zip"
    chmod 0600 "$state/hyp2003-incoming.zip"
    hyp2003_zip="$state/hyp2003-incoming.zip"
  fi
else
  driver_choice="$(zenity_amc --list --radiolist --title='USB DSC' --width=520 --height=260 \
    --column=Select --column=Action TRUE 'Choose driver ZIP' FALSE 'Skip for now' \
    --text=$'Select a driver ZIP from AMC Secure only if you need to update USB DSC support.')" || exit 0
  if [[ "$driver_choice" == 'Choose driver ZIP' ]]; then
    selected="$(zenity_amc --file-selection --title='Select USB DSC driver ZIP' --file-filter='Driver ZIP | *.zip' --file-filter='All files | *')" || selected=""
    [[ -n "$selected" && -f "$selected" && -r "$selected" ]] || { zenity_amc --error --text='No readable driver ZIP selected.'; exit 1; }
    cp -f -- "$selected" "$state/hyp2003-incoming.zip"; chmod 0600 "$state/hyp2003-incoming.zip"; hyp2003_zip="$state/hyp2003-incoming.zip"
  fi
fi

exec 9>"$state/setup.lock"
flock -n 9 || { zenity_amc --error --text='Another SignX setup is already running.'; exit 1; }
log="$(mktemp "$state/setup-XXXXXX.log")"
status="$log.status"
: >"$log"
: >"$status"
bundle=/usr/share/amc-secure-signx-setup/payload.tar.gz
work=""

launch_branded_progress() {
  local java_bin="" jar=""
  if [[ -n "${work:-}" && -x "$work/signx/runtime/bin/java" && -r "$work/signx/signx.jar" ]]; then
    java_bin="$work/signx/runtime/bin/java"
    jar="$work/signx/signx.jar"
  elif [[ -x /opt/amc-secure-signx/current/runtime/bin/java && -r /opt/amc-secure-signx/current/signx.jar ]]; then
    java_bin=/opt/amc-secure-signx/current/runtime/bin/java
    jar=/opt/amc-secure-signx/current/signx.jar
  fi
  if [[ -n "$java_bin" && -n "$jar" ]]; then
    BAMF_DESKTOP_FILE_HINT=/usr/share/applications/amc-secure-signx-setup.desktop \
      "$java_bin" \
      --add-opens java.desktop/sun.awt.X11=ALL-UNNAMED \
      -Dsun.awt.X11.XWMClass=amc-secure-signx-setup \
      -DawtAppClassName=amc-secure-signx-setup \
      -Dawt.appClassName=amc-secure-signx-setup \
      -jar "$jar" --setup-ui "$log" "$status" >/dev/null 2>&1 &
    return 0
  fi
  return 1
}

(
  set +e
  if [[ -r "$bundle" && -r "$bundle.sha256" ]]; then
    echo 'Verifying complete signed SignX package...' >>"$log"
    (cd "$(dirname "$bundle")" && sha256sum -c payload.tar.gz.sha256) >>"$log" 2>&1 || exit $?
    work="$(mktemp -d -t amc-signx-gui-XXXXXX)"
    # shellcheck disable=SC2064
    trap 'rm -rf -- "$work"' EXIT
    python3 - "$bundle" "$work" <<'PY' >>"$log" 2>&1
import pathlib,sys,tarfile
root=pathlib.Path(sys.argv[2]).resolve()
with tarfile.open(sys.argv[1],'r:gz') as archive:
    members=archive.getmembers()
    if sum(member.size for member in members)>2*1024**3:raise SystemExit('Unexpected package size')
    for member in members:
        target=(root/member.name).resolve()
        if root not in target.parents or not (member.isfile() or member.isdir()):raise SystemExit('Unsafe installer archive')
    archive.extractall(root)
PY
    extraction_result=$?
    if ((extraction_result!=0)); then
      printf '%s\n' "$extraction_result" > "$status"
      exit "$extraction_result"
    fi
    # Publish work dir for the progress UI launcher in the parent shell via a marker file.
    printf '%s\n' "$work" >"$state/setup-work.dir"
    if [[ -f /usr/share/amc-secure-signx-setup/extract-hyp2003-zip.py ]]; then
      install -m 0755 /usr/share/amc-secure-signx-setup/extract-hyp2003-zip.py "$work/signx/extract-hyp2003-zip.py"
    elif [[ -f "$(dirname "$0")/extract-hyp2003-zip.py" ]]; then
      install -m 0755 "$(dirname "$0")/extract-hyp2003-zip.py" "$work/signx/extract-hyp2003-zip.py"
    fi
    echo 'Complete package verified. Requesting Ubuntu administrator approval...' >>"$log"
    if [[ -n "$hyp2003_zip" ]]; then
      echo 'Using local USB DSC driver ZIP staged for installation.' >>"$log"
      bash "$work/signx/install-local.sh" --hyp2003-zip="$hyp2003_zip" >>"$log" 2>&1
    else
      bash "$work/signx/install-local.sh" >>"$log" 2>&1
    fi
  else
    if [[ -n "$hyp2003_zip" ]]; then
      bash /usr/share/amc-secure-signx-setup/install-signx.sh --allow-candidate --hyp2003-zip="$hyp2003_zip" >>"$log" 2>&1
    else
      bash /usr/share/amc-secure-signx-setup/install-signx.sh --allow-candidate >>"$log" 2>&1
    fi
  fi
  code=$?
  printf '%s\n' "$code" > "$status"
  exit "$code"
) &
worker=$!

# Prefer branded Swing progress (no commands / package lists). Fall back to sanitized zenity.
set +e
for _ in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15; do
  if [[ -f "$state/setup-work.dir" ]]; then
    work="$(cat "$state/setup-work.dir" 2>/dev/null || true)"
  fi
  if launch_branded_progress; then
    break
  fi
  # Also try existing install jar immediately.
  if [[ -x /opt/amc-secure-signx/current/runtime/bin/java ]]; then
    work=""
    launch_branded_progress && break
  fi
  sleep 0.4
done

# If Swing UI did not start, show sanitized zenity progress (never raw log lines).
if ! pgrep -f 'signx.jar --setup-ui' >/dev/null 2>&1; then
  while kill -0 "$worker" 2>/dev/null; do
    message="$(tail -n 1 "$log" 2>/dev/null || true)"
    printf '# %s\n' "$(friendly_setup_phase "$message")"
    sleep .4
  done | zenity_amc --progress --pulsate --auto-close --no-cancel --title='AMC Secure SignX Setup' --width=560 --text='Installing AMC Secure SignX…'
fi

wait "$worker"
worker_result=$?
result="$(cat "$status" 2>/dev/null || printf '%s' "$worker_result")"
rm -f -- "$state/setup-work.dir" 2>/dev/null || true
set -e
if ((result!=0)); then
  zenity_amc --error --width=520 --title='AMC Secure SignX Setup' \
    --text=$'Setup did not complete.\n\nClose SignX if it is open, approve the Ubuntu prompt, then retry.\nContact AMC Secure: 9425941000'
  exit "$result"
fi
# Trust Desktop launcher in THIS user session (fixes GNOME red-X / ".desktop" label).
if [[ -x /opt/amc-secure-signx/current/install-desktop-shortcut.sh ]]; then
  bash /opt/amc-secure-signx/current/install-desktop-shortcut.sh "$(id -un)" >/dev/null 2>&1 || true
elif [[ -f /usr/share/applications/amc-secure-signx.desktop ]]; then
  desktop_dir="$(xdg-user-dir DESKTOP 2>/dev/null || echo "$HOME/Desktop")"
  mkdir -p "$desktop_dir"
  rm -f "$desktop_dir/AMC Secure SignX.desktop" 2>/dev/null || true
  install -m 0755 /usr/share/applications/amc-secure-signx.desktop "$desktop_dir/amc-secure-signx.desktop"
  if command -v gio >/dev/null 2>&1; then
    gio set "$desktop_dir/amc-secure-signx.desktop" metadata::trusted true 2>/dev/null || true
  fi
fi
detection_file="$state/last-token-detection.txt"
detection_text="$([[ -f "$detection_file" ]] && cat "$detection_file" || true)"
nohup /usr/local/bin/amc-secure-signx </dev/null >/dev/null 2>&1 &
if [[ "$detection_text" == SUCCESS:* ]]; then
  zenity_amc --info --width=520 --title='AMC Secure SignX' \
    --text=$'Installation completed.\n\nUSB DSC is ready.\nSignX is opening for registration or licence validation.'
elif [[ "$detection_text" == ERROR:* ]]; then
  zenity_amc --warning --width=520 --title='AMC Secure SignX' \
    --text=$'Installation completed.\n\nUSB DSC readiness needs a check — insert the token in SignX.\nRegistration and documents were retained.'
elif [[ -n "$detection_text" ]]; then
  zenity_amc --warning --width=520 --title='AMC Secure SignX' \
    --text=$'Installation completed.\n\nInsert the DSC USB token and open SignX.\nRegistration and documents were retained.'
else
  zenity_amc --info --width=520 --title='AMC Secure SignX' \
    --text=$'Installation completed.\n\nSignX is opening. Insert the DSC USB token when ready to register certificates.'
fi
