#!/usr/bin/env bash
# List Wise activities (incoming + outgoing) for a period.
#
# Usage:
#   wise-transactions.sh [--since YYYY-MM-DD] [--until YYYY-MM-DD]
#                        [--month YYYY-MM]
#                        [--type TRANSFER|CARD_ORDER|BALANCE_CASHBACK|FEATURE_CHARGE|BALANCE_DEPOSIT|...]
#                        [--status COMPLETED|CANCELLED|IN_PROGRESS|UPCOMING|REQUIRES_ATTENTION]
#                        [--enrich]                # also fetch /v1/transfers/{id} for the wire reference
#                        [--json]                  # raw list, no table
#
# Backed by GET /v1/profiles/{WISE_PROFILE_ID}/activities — does NOT require
# SCA and DOES expose incoming transfers (unlike /balance-statements which is
# region-restricted for EU personal tokens, see SKILL.md).
#
# Pagination is followed automatically via the cursor.

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
BANK_CURL="${SCRIPT_DIR}/bank-curl.sh"

SINCE=""; UNTIL=""; MONTH=""; TYPE=""; STATUS=""; ENRICH=0; FMT="table"
while [[ $# -gt 0 ]]; do
  case "$1" in
    --since)   SINCE="$2"; shift 2 ;;
    --until)   UNTIL="$2"; shift 2 ;;
    --month)   MONTH="$2"; shift 2 ;;
    --type)    TYPE="$2"; shift 2 ;;
    --status)  STATUS="$2"; shift 2 ;;
    --enrich)  ENRICH=1; shift ;;
    --json)    FMT="json"; shift ;;
    -h|--help) sed -n '2,15p' "$0" | sed 's/^# \{0,1\}//'; exit 0 ;;
    *) echo "wise-transactions.sh: unknown arg: $1" >&2; exit 2 ;;
  esac
done

set -a; source "${SCRIPT_DIR}/../../dolibarr/.env"; set +a
: "${WISE_PROFILE_ID:?wise-transactions.sh: WISE_PROFILE_ID not set in .env}"

# Date handling — Wise wants full ISO 8601 with millis + Z
if [[ -n "${MONTH}" ]]; then
  SINCE="${MONTH}-01"
  UNTIL="$(python3 -c "import calendar; y,m=map(int,'${MONTH}'.split('-')); print(f'{y:04d}-{m:02d}-{calendar.monthrange(y,m)[1]:02d}')")"
fi
[[ -z "${SINCE}" ]] && SINCE="$(python3 -c "import datetime; print((datetime.date.today()-datetime.timedelta(days=365)).strftime('%Y-%m-%d'))")"
[[ -z "${UNTIL}" ]] && UNTIL="$(python3 -c "import datetime; print(datetime.date.today().strftime('%Y-%m-%d'))")"

SINCE_ISO="${SINCE}T00:00:00.000Z"
UNTIL_ISO="${UNTIL}T23:59:59.999Z"

WORK="$(mktemp -d -t wiseact.XXXXXX)"
trap 'rm -rf "${WORK}"' EXIT

# Paginate
echo '[]' > "${WORK}/all.json"
CURSOR=""
PAGE=1
while :; do
  Q="size=100&since=${SINCE_ISO}&until=${UNTIL_ISO}"
  [[ -n "${TYPE}"   ]] && Q="${Q}&monetaryResourceType=${TYPE}"
  [[ -n "${STATUS}" ]] && Q="${Q}&status=${STATUS}"
  [[ -n "${CURSOR}" ]] && Q="${Q}&nextCursor=$(python3 -c "import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))" "${CURSOR}")"
  TMP_PAGE=$(mktemp -t wisepg.XXXXXX.json)
  "${BANK_CURL}" wise "/v1/profiles/${WISE_PROFILE_ID}/activities?${Q}" > "${TMP_PAGE}"
  python3 - "${WORK}/all.json" "${TMP_PAGE}" <<'PY'
import json, sys
all_arr = json.load(open(sys.argv[1]))
page    = json.load(open(sys.argv[2]))
all_arr.extend(page.get("activities") or [])
json.dump(all_arr, open(sys.argv[1], "w"))
PY
  CURSOR=$(python3 -c "import json,sys; d=json.load(open(sys.argv[1])); print(d.get('cursor') or '')" "${TMP_PAGE}")
  rm -f "${TMP_PAGE}"
  if [[ -z "${CURSOR}" || "${CURSOR}" == "None" ]]; then
    break
  fi
  PAGE=$((PAGE+1))
done

# Optional enrichment: for each TRANSFER, fetch /v1/transfers/{id} and merge `reference`
if [[ "${ENRICH}" == "1" ]]; then
  python3 - "${WORK}/all.json" <<'PY' > "${WORK}/ids.txt"
import json, sys
acts = json.load(open(sys.argv[1]))
for a in acts:
    r = a.get("resource") or {}
    if r.get("type") == "TRANSFER" and r.get("id"):
        print(r["id"])
PY
  > "${WORK}/refs.json"
  echo '{}' > "${WORK}/refs.json"
  while read -r tid; do
    [[ -z "${tid}" ]] && continue
    TMP_T=$(mktemp -t wiset.XXXXXX.json)
    if "${BANK_CURL}" wise "/v1/transfers/${tid}" > "${TMP_T}" 2>/dev/null; then
      python3 - "${WORK}/refs.json" "${TMP_T}" "${tid}" <<'PY'
import json, sys
refs = json.load(open(sys.argv[1]))
t    = json.load(open(sys.argv[2]))
refs[sys.argv[3]] = t.get("reference") or ""
json.dump(refs, open(sys.argv[1], "w"))
PY
    fi
    rm -f "${TMP_T}"
  done < "${WORK}/ids.txt"
fi

if [[ "${FMT}" == "json" ]]; then
  cat "${WORK}/all.json"
  exit 0
fi

python3 - "${WORK}/all.json" "${WORK}/refs.json" "${ENRICH}" "${SINCE}" "${UNTIL}" <<'PY'
import json, sys, re, os
acts_path, refs_path, enrich, since, until = sys.argv[1:6]
acts = json.load(open(acts_path))
refs = json.load(open(refs_path)) if os.path.exists(refs_path) else {}
def strip(s): return re.sub(r'<[^>]+>', '', s or '').strip()
def parse_amount(s):
    # "<positive>+ 5,100.00 EUR</positive>" -> (+, 5100.00, EUR)
    s = strip(s)
    sign = "+" if s.startswith("+") else "-"
    m = re.search(r'([\d,.]+)\s*([A-Z]{3})', s)
    if not m: return sign, 0.0, "?"
    return sign, float(m.group(1).replace(",", "")), m.group(2)

# Sort by date (ascending)
acts.sort(key=lambda a: a.get("createdOn") or "")

print(f"# Wise activities for profile (window {since} → {until})")
print()
header = f"{'date':<10}  {'type':<18} {'status':<10} {'sign':<4} {'amount':>10}  {'cur':<3} {'title':<28}"
if int(enrich): header += "  reference"
print(header)
print("-" * (len(header) + 30 if int(enrich) else len(header)))
total_credit = total_debit = 0.0
for a in acts:
    dt = (a.get("createdOn") or "")[:10]
    sign, amt, cur = parse_amount(a.get("primaryAmount") or "")
    typ = a.get("type", "-")
    st  = a.get("status", "-")
    title = strip(a.get("title") or "")[:28]
    line = f"{dt:<10}  {typ:<18} {st:<10} {sign:<4} {amt:>10.2f}  {cur:<3} {title:<28}"
    if int(enrich):
        r = a.get("resource") or {}
        ref = refs.get(str(r.get("id", "")), "") if r.get("type") == "TRANSFER" else ""
        line += f"  {ref}"
    print(line)
    if sign == "+": total_credit += amt
    if sign == "-": total_debit  += amt
print("-" * (len(header) + 30 if int(enrich) else len(header)))
print(f"# {len(acts)} activity(ies) — credit: +{total_credit:.2f}, debit: -{total_debit:.2f}, net: {total_credit - total_debit:+.2f}")
PY
