#!/bin/bash

## Copyright (C) 2025 - 2025 ENCRYPTED SUPPORT LLC <adrelanos@whonix.org>
## See the file COPYING for copying conditions.

set -o errexit
set -o nounset
set -o errtrace
set -o pipefail

# shellcheck source=../share/mediawiki-shell/common
source /usr/share/mediawiki-shell/common
# shellcheck source=../../../helper-scripts/usr/libexec/helper-scripts/strings.bsh
source /usr/libexec/helper-scripts/strings.bsh

log info "START"

# shellcheck disable=SC2317
exit_handler() {
  [[ -v retry_counter ]] || retry_counter=0
  is_whole_number "${retry_counter}" || retry_counter=0
  if (( retry_counter > 1 )); then
    log info "success after attempt $retry_counter"
  fi
}

trap exit_handler EXIT

usage() {
  printf '%s\n' "Usage: ${0##*/} WIKI PAGE OUTPUT
Example:
  ${0##*/} 'https://www.kicksecure.com/w' About /tmp/a" >&2
  exit 1
}

if [[ -z "${3-}" || "${1-}" =~ (-h|--help) ]]; then
  usage
fi

wiki_url="$1"
page="$2"
output="$3"

check_vars_exist page output

output_dir="$(dirname -- "${output}")"

temp_page_normalized="$(set_backup_filename_item "$(set_backup_page_item "$page")")"
temp_output_file="$TMPFOLDER/$temp_page_normalized"
assert_path_within_dir "$TMPFOLDER" "$temp_output_file"

log info "wiki_url        : $wiki_url"
log info "page            : $page"
log info "temp_output_file: $temp_output_file"
log info "output          : $output"

mkdir -p -- "$output_dir"
if ! test -d "$output_dir"; then
  die 1 "output_dir '$output_dir' does not exist! Run?: mkdir --parents -- '$output_dir'"
fi

if ! test -w "$output_dir"; then
  die 1 "output_dir '$output_dir' unwritable! Run?: chown --recursive -- '$USER:$USER' '$output_dir'"
fi

for retry_counter in {1..5}; do
  if ! mw-fetch "$wiki_url" "$page" "$temp_output_file"; then
    log warn "fetch attempt ${retry_counter} failed for page '$page'; retrying..."
    sleep 5
    continue
  fi

  ## time-of-check to time-of-use TOCTOU
  ## Check for pending edits only after page was fetched.
  ## Checking for pending edits before fetching page would leave room for
  ## making a pending edit after the page has been fetched.
  ## This ensures that the fetched edit was not pending, i.e. confirmed.
  ##
  ## mw-page-pending-check exits 10 specifically for "page has pending edits".
  ## Any other non-zero is a CHECK FAILURE (e.g. network error) and must NOT
  ## be silently treated as "pending" -- doing so would drop the page from the
  ## backup on a transient failure. Distinguish the two by exit code, mirroring
  ## mw-multi-wiki's handling.
  pending_exit_code=0
  mw-page-pending-check "$wiki_url" "$page" || pending_exit_code="$?"
  if [ "$pending_exit_code" = "10" ]; then
    log warn "SKIP: page '$page' has PENDING edits."
    exit 0
  fi
  if [ "$pending_exit_code" != "0" ]; then
    log warn "pending-check failed (rc=${pending_exit_code}) for page '$page'; retrying..."
    sleep 5
    continue
  fi

  mv -- "$temp_output_file" "$output"
  log info "SUCCESS: page '$page' | output: '$output'"

  exit 0
done

## Failed even after retry attempts. Therefore exit non-zero.
exit 1
