#!/usr/bin/env bash
# Duplicate guest sweep
# Finds contacts sharing an email address, and prints the merge command for each pair. Duplicates split a guest’s stay history in two, which is how a fifth-time visitor gets a first-time-guest email.
#
# Category : Data hygiene
# Safety   : read only
# Uses     : contacts list, contacts merge
# Returns  : Email addresses held by more than one contact, with a ready merge command.
#
# Requires the SendSquared CLI and jq:
#   curl -fsSL https://cli.sendsquared.com/install.sh | bash
#   sendsquared auth login
#
# Free to use and adapt. https://sendsquared.com/cli/scripts/#duplicate-guests

# Contacts sharing an email address.
#
# primaryEmail is an object ({id, contact_id, email_address, ...}), not a string.
# Email is the only axis worth sweeping. Phone numbers are unique per guest in
# SendSquared, so two contacts cannot collide on one and a phone pass would
# only ever return noise.
#
# Bounded by default: a large book runs to hundreds of thousands of contacts
# and an unbounded walk will not finish in a coffee break.
set -euo pipefail
PAGES=${1:-15}   # 15 pages x 1000 contacts; 0 = the whole book
TMP=$(mktemp)
BEFORE=""
SEEN=0
PAGENO=0

while :; do
  PAGENO=$((PAGENO+1))
  if [ "$PAGES" -ne 0 ] && [ "$PAGENO" -gt "$PAGES" ]; then break; fi
  PAGE=$(sendsquared contacts list --limit 1000 ${BEFORE:+--before "$BEFORE"})
  N=$(jq '.data | length' <<<"$PAGE")
  [ "$N" -eq 0 ] && break
  SEEN=$((SEEN+N))
  jq -r '.data[] | select(.primaryEmail != null) | select((.primaryEmail.email_address // "") != "") | [ (.primaryEmail.email_address | ascii_downcase), .id ] | @tsv' <<<"$PAGE" >> "$TMP"
  BEFORE=$(jq -r '[.data[].id] | min' <<<"$PAGE")
  [ "$N" -lt 1000 ] && break
done

echo "--- scanned $SEEN contacts"
sort "$TMP" | awk -F'\t' '
  { ids[$1] = ids[$1] " " $2; n[$1]++ }
  END {
    c = 0
    for (e in n) if (n[e] > 1) {
      c++
      list = ids[e]; sub(/^ +/, "", list)
      printf "  %-42s %s\n", e, list
      split(list, a, " ")
      printf "    merge: sendsquared contacts merge %s %s\n", a[1], a[2]
    }
    if (c == 0) print "  no duplicate email addresses found"
  }' | head -60
rm -f "$TMP"
