#!/usr/bin/env bash
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"
ENV_FILE="${SCRIPT_DIR}/.env_hourly_config"

if [[ ! -f "${ENV_FILE}" ]]; then
  echo "[error] missing env file: ${ENV_FILE}" >&2
  echo "[hint] cp ${SCRIPT_DIR}/.env_hourly_config.example ${ENV_FILE}" >&2
  exit 1
fi

# shellcheck disable=SC1090
source "${ENV_FILE}"

: "${SF_READONLY_CONFIG_PATH:?missing SF_READONLY_CONFIG_PATH}"
: "${SF_HOURLY_OUTPUT_ROOT:?missing SF_HOURLY_OUTPUT_ROOT}"
: "${SF_HOURLY_S3_BUCKET:?missing SF_HOURLY_S3_BUCKET}"
: "${SF_HOURLY_S3_PREFIX:?missing SF_HOURLY_S3_PREFIX}"
: "${SF_HOURLY_LOG_DIR:?missing SF_HOURLY_LOG_DIR}"
: "${SF_HOURLY_STATE_FILE:?missing SF_HOURLY_STATE_FILE}"
: "${SF_HOURLY_LOCK_FILE:?missing SF_HOURLY_LOCK_FILE}"

mkdir -p "${SF_HOURLY_OUTPUT_ROOT}" "${SF_HOURLY_LOG_DIR}" "$(dirname "${SF_HOURLY_STATE_FILE}")"

if [[ -n "${SF_HOURLY_SINCE:-}" ]]; then
  WINDOW_START="${SF_HOURLY_SINCE}"
else
  WINDOW_START="$(python3 - <<'PY'
from datetime import datetime, timedelta, timezone
now = datetime.now(timezone.utc).replace(minute=0, second=0, microsecond=0)
print((now - timedelta(hours=1)).isoformat().replace("+00:00", "Z"))
PY
)"
fi

if [[ -n "${SF_HOURLY_UNTIL:-}" ]]; then
  WINDOW_END="${SF_HOURLY_UNTIL}"
else
  WINDOW_END="$(python3 - <<'PY'
from datetime import datetime, timezone
now = datetime.now(timezone.utc).replace(minute=0, second=0, microsecond=0)
print(now.isoformat().replace("+00:00", "Z"))
PY
)"
fi

SNAPSHOT_DATE="${SNAPSHOT_DATE:-${WINDOW_START%%T*}}"
RUN_LABEL="${SF_HOURLY_RUN_LABEL:-hourly-delta-$(python3 - <<'PY' "${WINDOW_START}"
from datetime import datetime, timezone
import sys
value = sys.argv[1].strip().replace("Z", "+00:00")
dt = datetime.fromisoformat(value).astimezone(timezone.utc)
print(dt.strftime("%Y%m%dT%H00Z"))
PY
)}"

LOG_STAMP="$(python3 - <<'PY' "${WINDOW_START}"
from datetime import datetime, timezone
import sys
value = sys.argv[1].strip().replace("Z", "+00:00")
dt = datetime.fromisoformat(value).astimezone(timezone.utc)
print(dt.strftime("%Y%m%dT%H00Z"))
PY
)"
LOG_PATH="${SF_HOURLY_LOG_DIR}/hourly_delta_${LOG_STAMP}.log"

release_lock() {
  if [[ -n "${LOCK_DIR_PATH:-}" && -d "${LOCK_DIR_PATH}" ]]; then
    rmdir "${LOCK_DIR_PATH}" || true
  fi
}
trap release_lock EXIT

if command -v flock >/dev/null 2>&1; then
  exec 9>"${SF_HOURLY_LOCK_FILE}"
  if ! flock -n 9; then
    echo "[error] another hourly delta run is active: ${SF_HOURLY_LOCK_FILE}" >&2
    exit 1
  fi
else
  LOCK_DIR_PATH="${SF_HOURLY_LOCK_FILE}.d"
  if ! mkdir "${LOCK_DIR_PATH}" 2>/dev/null; then
    echo "[error] another hourly delta run is active: ${LOCK_DIR_PATH}" >&2
    exit 1
  fi
fi

cd "${REPO_ROOT}"

{
  echo "[start] $(date '+%Y-%m-%d %H:%M:%S %z')"
  echo "[info] repo_root=${REPO_ROOT}"
  echo "[info] snapshot_date=${SNAPSHOT_DATE}"
  echo "[info] run_label=${RUN_LABEL}"
  echo "[info] window_start=${WINDOW_START}"
  echo "[info] window_end=${WINDOW_END}"
  echo "[info] output_root=${SF_HOURLY_OUTPUT_ROOT}"
  echo "[info] s3_bucket=${SF_HOURLY_S3_BUCKET}"
  echo "[info] s3_prefix=${SF_HOURLY_S3_PREFIX}"
  echo "[info] state_file=${SF_HOURLY_STATE_FILE}"

  cmd=(
    python3
    "${SCRIPT_DIR}/run_hourly_delta_sync.py"
    --config "${SF_READONLY_CONFIG_PATH}"
    --output-root "${SF_HOURLY_OUTPUT_ROOT}"
    --snapshot-date "${SNAPSHOT_DATE}"
    --run-label "${RUN_LABEL}"
    --since "${WINDOW_START}"
    --until "${WINDOW_END}"
    --state-file "${SF_HOURLY_STATE_FILE}"
    --export-only
    --s3-bucket "${SF_HOURLY_S3_BUCKET}"
    --s3-prefix "${SF_HOURLY_S3_PREFIX}"
  )

  if [[ -n "${SF_HOURLY_SYNC_CONFIG:-}" ]]; then
    cmd+=(--sync-config "${SF_HOURLY_SYNC_CONFIG}")
  fi
  if [[ "${SF_HOURLY_SKIP_S3_UPLOAD:-0}" == "1" ]]; then
    cmd+=(--skip-s3-upload)
  fi

  printf '[exec]'
  printf ' %q' "${cmd[@]}"
  printf '\n'

  "${cmd[@]}"

  echo "[done] $(date '+%Y-%m-%d %H:%M:%S %z')"
} 2>&1 | tee -a "${LOG_PATH}"
