#!/usr/bin/env bash
# Push remapped shopping_* attributes + (optional) sample SKUs + gallery images to Magento.
#
# Use after manual taxonomy remaps (e.g. mouldings→moldings) so Magento products
# pick up corrected shopping_collection / shopping_l1 / shopping_l2 and images.
#
# This is intentionally narrower than launch_day_magento_push.sh:
#   - no RTA wipe / category prune / hierarchy invent
#   - focuses on shopping attrs, product force-PUT, and images
#
# ALWAYS dry-run first:
#   DRY_RUN=1 bash scripts/push_shopping_attrs_and_images.sh
#
# Live (primary then secondary, matches launch-day defaults):
#   bash scripts/push_shopping_attrs_and_images.sh
#   nohup bash scripts/push_shopping_attrs_and_images.sh \
#     >logs/push_shopping_attrs_and_images_nohup.out 2>&1 &
#
# Sample smoke only (10 SKUs, products+images, then stop):
#   SAMPLE_ONLY=1 SAMPLE_LIMIT=10 bash scripts/push_shopping_attrs_and_images.sh
#
# Env:
#   APP_ROOT / VENV_DIR / PYTHON / LOG_DIR
#   MAGENTO_CONNECTION_IDS   default: "4 1"
#   DRY_RUN                  1 = preview only (default: 0)
#   USE_LOCK                 1 = flock so daemon cannot double-run (default: 1)
#   WAIT_TIMEOUT             default: 21600
#   RUN_WORKER               1 = claim queue in-process (default: 1). Set 0 if
#                            magento_worker systemd unit is already running.
#   SAMPLE_ONLY              1 = only push_channel_sample then exit (default: 0)
#   SAMPLE_LIMIT             SKUs for sample / smoke (default: 25)
#   SAMPLE_SKUS              optional space-separated explicit SKUs (skips auto-select)
#   RUN_SAMPLE               1 = smoke sample before full attr/image push (default: 1)
#   RUN_ATTR_PUSH            1 = push shopping_* via push_magento_attributes (default: 1)
#   RUN_PRODUCTS_FORCE       1 = force products-only upsert for shopping fields (default: 1)
#   PRODUCT_PUSH_LIMIT       products-only SKU cap (default: 10000)
#   RUN_IMAGE_PUSH           1 = images-only force push (default: 1)
#   IMAGE_PUSH_LIMIT         default: 10000
#   ATTR_FIELDS              default: shopping_collection shopping_l1 shopping_l2

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
APP_ROOT="$(cd "${APP_ROOT:-$SCRIPT_DIR/..}" && pwd)"
VENV_DIR="${VENV_DIR:-$APP_ROOT/.venv}"
if [[ -z "${PYTHON:-}" ]]; then
  if [[ -x "$VENV_DIR/bin/python" ]]; then
    PYTHON="$VENV_DIR/bin/python"
  else
    PYTHON="python3"
  fi
fi

LOG_DIR="${LOG_DIR:-$APP_ROOT/logs}"
MAGENTO_CONNECTION_IDS="${MAGENTO_CONNECTION_IDS:-4 1}"
DRY_RUN="${DRY_RUN:-0}"
USE_LOCK="${USE_LOCK:-1}"
WAIT_TIMEOUT="${WAIT_TIMEOUT:-21600}"
RUN_WORKER="${RUN_WORKER:-1}"
SAMPLE_ONLY="${SAMPLE_ONLY:-0}"
SAMPLE_LIMIT="${SAMPLE_LIMIT:-25}"
SAMPLE_SKUS="${SAMPLE_SKUS:-}"
RUN_SAMPLE="${RUN_SAMPLE:-1}"
RUN_ATTR_PUSH="${RUN_ATTR_PUSH:-1}"
RUN_PRODUCTS_FORCE="${RUN_PRODUCTS_FORCE:-1}"
PRODUCT_PUSH_LIMIT="${PRODUCT_PUSH_LIMIT:-10000}"
RUN_IMAGE_PUSH="${RUN_IMAGE_PUSH:-1}"
IMAGE_PUSH_LIMIT="${IMAGE_PUSH_LIMIT:-10000}"
ATTR_FIELDS="${ATTR_FIELDS:-shopping_collection shopping_l1 shopping_l2}"

mkdir -p "$LOG_DIR"
STAMP="$(date -u +%Y%m%dT%H%M%SZ)"
LOG_FILE="$LOG_DIR/push_shopping_attrs_and_images_${STAMP}.log"
STATUS_FILE="$LOG_DIR/push_shopping_attrs_and_images_latest.status"
LOCK_FILE="$LOG_DIR/push_shopping_attrs_and_images.lock"

cd "$APP_ROOT"
export PYTHONUNBUFFERED=1

exec > >(tee -a "$LOG_FILE") 2>&1

echo "=== push shopping attrs + sample + images ==="
echo "started_utc=$STAMP"
echo "app_root=$APP_ROOT"
echo "python=$PYTHON ($("$PYTHON" --version 2>&1 || true))"
echo "connections=$MAGENTO_CONNECTION_IDS"
echo "dry_run=$DRY_RUN"
echo "sample_only=$SAMPLE_ONLY sample_limit=$SAMPLE_LIMIT"
echo "run_sample=$RUN_SAMPLE run_attr_push=$RUN_ATTR_PUSH run_products_force=$RUN_PRODUCTS_FORCE run_image_push=$RUN_IMAGE_PUSH"
echo "run_worker=$RUN_WORKER wait_timeout=$WAIT_TIMEOUT"
echo "attr_fields=$ATTR_FIELDS"
echo "log_file=$LOG_FILE"
echo

if [[ "$USE_LOCK" == "1" ]]; then
  exec 9>"$LOCK_FILE"
  if ! flock -n 9; then
    echo "Another push_shopping_attrs_and_images run holds $LOCK_FILE — exiting"
    echo "failed:lock:$(date -u +%Y%m%dT%H%M%SZ)" >"$STATUS_FILE"
    exit 75
  fi
fi

fail() {
  local step="$1"
  local code="$2"
  echo "FAILED step=$step exit=$code"
  echo "failed:$step:$code:$(date -u +%Y%m%dT%H%M%SZ)" >"$STATUS_FILE"
  exit "$code"
}

run_step() {
  local name="$1"
  shift
  echo
  echo "------------------------------------------------------------"
  echo "STEP: $name"
  echo "CMD: $*"
  echo "started: $(date -u +%Y-%m-%dT%H:%M:%SZ)"
  echo "------------------------------------------------------------"
  if "$@"; then
    echo "OK: $name ($(date -u +%Y-%m-%dT%H:%M:%SZ))"
  else
    local code=$?
    fail "$name" "$code"
  fi
}

append_wait_flags() {
  local -n _cmd=$1
  _cmd+=(--wait --wait-timeout "$WAIT_TIMEOUT")
  if [[ "$RUN_WORKER" == "1" ]]; then
    _cmd+=(--run-worker)
  fi
}

push_sample() {
  local magento_id="$1"
  local limit="$2"
  local force_products="${3:-0}"
  local SAMPLE_CMD=(
    "$PYTHON" -m app.jobs.push_channel_sample
    --channels magento
    --magento-connection-id "$magento_id"
    --limit "$limit"
  )
  if [[ -n "$SAMPLE_SKUS" ]]; then
    # shellcheck disable=SC2206
    SAMPLE_CMD+=(--skus $SAMPLE_SKUS)
  fi
  if [[ "$force_products" == "1" ]]; then
    SAMPLE_CMD+=(--force-products)
  fi
  append_wait_flags SAMPLE_CMD
  if [[ "$DRY_RUN" == "1" ]]; then
    :
  else
    SAMPLE_CMD+=(--no-dry-run)
  fi
  run_step "push_channel_sample_conn_${magento_id}" "${SAMPLE_CMD[@]}"
}

for magento_id in $MAGENTO_CONNECTION_IDS; do
  echo
  echo "######## Magento connection ${magento_id} ########"

  if [[ "$RUN_SAMPLE" == "1" || "$SAMPLE_ONLY" == "1" ]]; then
    push_sample "$magento_id" "$SAMPLE_LIMIT" 1
  fi

  if [[ "$SAMPLE_ONLY" == "1" ]]; then
    echo "SAMPLE_ONLY=1 — skipping full attr/product/image push for conn ${magento_id}"
    continue
  fi

  if [[ "$RUN_ATTR_PUSH" == "1" ]]; then
    ATTR_CMD=(
      "$PYTHON" -m app.jobs.push_magento_attributes
      --connection-id "$magento_id"
      --sync-options
    )
    for field in $ATTR_FIELDS; do
      ATTR_CMD+=(--field "$field")
    done
    append_wait_flags ATTR_CMD
    if [[ "$DRY_RUN" == "1" ]]; then
      ATTR_CMD+=(--dry-run)
    else
      ATTR_CMD+=(--apply)
    fi
    run_step "push_shopping_attrs_conn_${magento_id}" "${ATTR_CMD[@]}"
  fi

  if [[ "$RUN_PRODUCTS_FORCE" == "1" ]]; then
    # Full product PUT so category_links + shopping_* land together (hash-skip bypass).
    PROD_CMD=(
      "$PYTHON" -m app.jobs.push_channel_sample
      --channels magento
      --magento-connection-id "$magento_id"
      --products-only
      --force-products
      --limit "$PRODUCT_PUSH_LIMIT"
    )
    append_wait_flags PROD_CMD
    if [[ "$DRY_RUN" == "1" ]]; then
      :
    else
      PROD_CMD+=(--no-dry-run)
    fi
    run_step "force_products_conn_${magento_id}" "${PROD_CMD[@]}"
  fi

  if [[ "$RUN_IMAGE_PUSH" == "1" ]]; then
    IMG_CMD=(
      "$PYTHON" -m app.jobs.push_channel_sample
      --channels magento
      --magento-connection-id "$magento_id"
      --images-only
      --limit "$IMAGE_PUSH_LIMIT"
    )
    append_wait_flags IMG_CMD
    if [[ "$DRY_RUN" == "1" ]]; then
      :
    else
      IMG_CMD+=(--no-dry-run)
    fi
    run_step "push_images_conn_${magento_id}" "${IMG_CMD[@]}"
  fi
done

echo
echo "=== push shopping attrs + images completed $(date -u +%Y-%m-%dT%H:%M:%SZ) ==="
echo "ok:$(date -u +%Y%m%dT%H%M%SZ)" >"$STATUS_FILE"
echo "status_file=$STATUS_FILE"
echo "log_file=$LOG_FILE"
echo "Spot-check: shopping_* match moldings/tall-cabinets (not mouldings/tall); galleries look correct."
