#!/usr/bin/env bash
# Smoke-test all scoped OLAP datasets against one logical region.
# Usage: bash skills/o11y-olap/scripts/smoke-test.sh [logical_region]
# Default: us-west-2-staging

set -euo pipefail

ROOT="$(cd "$(dirname "$0")/../../.." && pwd)"
cd "$ROOT"

LOGICAL="${1:-us-west-2-staging}"
# shellcheck disable=SC1091
source skills/o11y-olap/scripts/o11y-olap.sh
olap_auth

VENDOR=aws
PASS=0
FAIL=0
SKIP=0

log() { printf '%s\n' "$*" >&2; }

check() {
  local name="$1" ok="$2" detail="${3:-}"
  case "$ok" in
    ok) PASS=$((PASS + 1)); log "PASS  $name ${detail}" ;;
    skip) SKIP=$((SKIP + 1)); log "SKIP  $name ${detail}" ;;
    *) FAIL=$((FAIL + 1)); log "FAIL  $name ${detail}" ;;
  esac
}

run_q() {
  # stdout = results JSON; return 0 on rows-capable success (incl. 0 rows)
  local body="$1"
  local err=/tmp/olap-smoke-$$.err
  local out
  if out=$(olap_query "$LOGICAL" "$body" "$VENDOR" all "" "" 180 2>"$err"); then
    echo "$out"
    return 0
  fi
  cat "$err" >&2
  echo "$out"
  return 1
}

requires_tr() {
  local ds="$1"
  olap_tables "$LOGICAL" "$VENDOR" | jq -r --arg id "$ds" '
    (.data.datasets // [])[] | select(.id == $id) | .requires_time_range // false
  '
}

attach_time_range() {
  # stdin: body json; arg1: date for full-day range; prints body with time_range if needed
  local ds="$1" day="$2"
  local req
  req=$(requires_tr "$ds")
  if [ "$req" = "true" ]; then
    local tr
    tr=$(olap_day_time_range_json "$day")
    jq --argjson tr "$tr" '. + {time_range: $tr}'
  else
    cat
  fi
}

log "=== smoke $LOGICAL (x-region=$(olap_x_region "$LOGICAL")) ==="

TABLES=$(olap_tables "$LOGICAL" "$VENDOR")
if echo "$TABLES" | jq -e '.data.tables | length > 0' >/dev/null; then
  check "olap/tables" ok "$(echo "$TABLES" | jq -r '[.data.tables[].name] | join(",")')"
else
  check "olap/tables" fail "$(echo "$TABLES" | jq -c '{message,full_text}')"
  exit 1
fi

# ─── log-stats ───
DATE_LS=$(olap_scope_list "$LOGICAL" '{"dataset":"log-stats","field":"date","scope":{}}' | jq -r '.data.values[-1] // empty')
if [ -z "$DATE_LS" ]; then
  check "log-stats" skip "no dates"
else
  ORG=$(olap_scope_first "$LOGICAL" "$(jq -n --arg d "$DATE_LS" '{dataset:"log-stats",field:"org",scope:{date:$d}}')")
  CLUSTER=$(olap_scope_first "$LOGICAL" "$(jq -n --arg d "$DATE_LS" --arg o "$ORG" '{dataset:"log-stats",field:"cluster",scope:{date:$d,org:$o}}')")
  BODY=$(jq -n --arg d "$DATE_LS" --arg o "$ORG" --arg c "$CLUSTER" '{
    dataset:"log-stats",
    scope:{date:$d, org:$o, cluster:$c},
    sql:"SELECT component, level, CAST(count AS bigint) AS cnt FROM log_stats ORDER BY cnt DESC LIMIT 3",
    wait_seconds: 60
  }')
  if OUT=$(run_q "$BODY"); then
    check "log-stats" ok "date=$DATE_LS org=$ORG cluster=$CLUSTER rows=$(echo "$OUT" | jq '.data.rows|length')"
  else
    check "log-stats" fail "$(echo "$OUT" | jq -c '{message,full_text,error:.data.error_message}')"
  fi
fi

# ─── logs ───
ENV_V=$(olap_scope_first "$LOGICAL" '{"dataset":"logs","field":"env","scope":{}}')
if [ -z "$ENV_V" ]; then
  check "logs" skip "no env"
else
  DEPLOY=$(olap_scope_first "$LOGICAL" "$(jq -n --arg e "$ENV_V" '{dataset:"logs",field:"deploy_type",scope:{env:$e}}')")
  DATE_L=$(olap_scope_list "$LOGICAL" "$(jq -n --arg e "$ENV_V" --arg d "$DEPLOY" '{dataset:"logs",field:"date",scope:{env:$e,deploy_type:$d}}')" | jq -r '.data.values[-1]')
  DATE_L=$(olap_normalize_date "$DATE_L")
  COMP=$(olap_scope_first "$LOGICAL" "$(jq -n --arg e "$ENV_V" --arg d "$DEPLOY" --arg dt "$DATE_L" '{dataset:"logs",field:"components",scope:{env:$e,deploy_type:$d,date:$dt}}')")
  BODY=$(jq -n --arg e "$ENV_V" --arg d "$DEPLOY" --arg dt "$DATE_L" --arg c "$COMP" '{
    dataset:"logs",
    scope:{env:$e, deploy_type:$d, date:$dt, components:[$c]},
    sql:"SELECT event_time, level, substr(message,1,80) AS message FROM logs LIMIT 3",
    wait_seconds: 90
  }' | attach_time_range logs "$DATE_L")
  if OUT=$(run_q "$BODY"); then
    check "logs" ok "env=$ENV_V deploy=$DEPLOY date=$DATE_L component=$COMP rows=$(echo "$OUT" | jq '.data.rows|length')"
  else
    check "logs" fail "$(echo "$OUT" | jq -c '{message,full_text,error:.data.error_message}')"
  fi
fi

# Find first org/cluster[/component/instance]/date with data for org-rooted datasets.
find_scope_with_date() {
  local dataset="$1"
  local max_orgs="${2:-20}"
  local o c d component instance n=0
  local orgs
  orgs=$(olap_scope_list "$LOGICAL" "$(jq -n --arg ds "$dataset" '{dataset:$ds,field:"org",scope:{}}')" | jq -r --argjson m "$max_orgs" '.data.values[:$m][]')
  for o in $orgs; do
    for c in $(olap_scope_list "$LOGICAL" "$(jq -n --arg ds "$dataset" --arg o "$o" '{dataset:$ds,field:"cluster",scope:{org:$o}}')" | jq -r '.data.values[:8][]'); do
      if [ "$dataset" = "topsql" ]; then
        for component in $(olap_scope_list "$LOGICAL" "$(jq -n --arg o "$o" --arg c "$c" '{dataset:"topsql",field:"component",scope:{org:$o,cluster:$c}}')" | jq -r '.data.values[] | select(.=="tidb" or .=="tikv")'); do
          instance=$(olap_scope_first "$LOGICAL" "$(jq -n --arg o "$o" --arg c "$c" --arg p "$component" '{dataset:"topsql",field:"instance",scope:{org:$o,cluster:$c,component:$p}}')")
          [ -z "$instance" ] && continue
          d=$(olap_scope_list "$LOGICAL" "$(jq -n --arg o "$o" --arg c "$c" --arg p "$component" --arg i "$instance" '{dataset:"topsql",field:"date",scope:{org:$o,cluster:$c,component:$p,instance:$i}}')" | jq -r '.data.values[-1] // empty')
          if [ -n "$d" ]; then
            jq -nc --arg o "$o" --arg c "$c" --arg p "$component" --arg i "$instance" --arg d "$(olap_normalize_date "$d")" \
              '{org:$o,cluster:$c,component:$p,instance:$i,date:$d}'
            return 0
          fi
        done
      else
        d=$(olap_scope_list "$LOGICAL" "$(jq -n --arg ds "$dataset" --arg o "$o" --arg c "$c" '{dataset:$ds,field:"date",scope:{org:$o,cluster:$c}}')" | jq -r '.data.values[-1] // empty')
        if [ -n "$d" ]; then
          jq -nc --arg o "$o" --arg c "$c" --arg d "$(olap_normalize_date "$d")" '{org:$o,cluster:$c,date:$d}'
          return 0
        fi
      fi
    done
    n=$((n + 1))
  done
  return 1
}

# ─── topsql ───
if SCOPE=$(find_scope_with_date topsql 8); then
  BODY=$(echo "$SCOPE" | jq '{
    dataset:"topsql",
    scope:{org:.org, cluster:.cluster, component:.component, instance:.instance, date:.date},
    sql:"SELECT timestamps, sql_digest, topsql_cpu_time_ms FROM topsql ORDER BY topsql_cpu_time_ms DESC LIMIT 3",
    wait_seconds:90
  }' | attach_time_range topsql "$(echo "$SCOPE" | jq -r .date)")
  if OUT=$(run_q "$BODY"); then
    check "topsql" ok "$(echo "$SCOPE" | jq -c .) rows=$(echo "$OUT" | jq '.data.rows|length')"
  else
    check "topsql" fail "$(echo "$OUT" | jq -c '{message,full_text,error:.data.error_message}')"
  fi
else
  check "topsql" skip "no org/cluster/instance/date found"
fi

# ─── sqlstatement ───
if SCOPE=$(find_scope_with_date sqlstatement 15); then
  BODY=$(echo "$SCOPE" | jq '{
    dataset:"sqlstatement",
    scope:{org:.org, cluster:.cluster, date:.date},
    sql:"SELECT digest, stmt_type, exec_count FROM sqlstatement LIMIT 3",
    wait_seconds:90
  }' | attach_time_range sqlstatement "$(echo "$SCOPE" | jq -r .date)")
  if OUT=$(run_q "$BODY"); then
    check "sqlstatement" ok "$(echo "$SCOPE" | jq -c .) rows=$(echo "$OUT" | jq '.data.rows|length')"
  else
    check "sqlstatement" fail "$(echo "$OUT" | jq -c '{message,full_text,error:.data.error_message}')"
  fi
else
  check "sqlstatement" skip "no org/cluster/date found"
fi

# ─── slowlogs (legacy Delta: org + cluster + date=yyyyMMdd path partition) ───
ORG=$(olap_scope_first "$LOGICAL" '{"dataset":"slowlogs","field":"org","scope":{}}')
if [ -z "$ORG" ]; then
  check "slowlogs" skip "no org under deltalake/"
else
  CLUSTER=$(olap_scope_first "$LOGICAL" "$(jq -n --arg o "$ORG" '{dataset:"slowlogs",field:"cluster",scope:{org:$o}}')")
  if [ -z "$CLUSTER" ]; then
    check "slowlogs" skip "no cluster under org=$ORG"
  else
    DAY=$(olap_scope_first "$LOGICAL" "$(jq -n --arg o "$ORG" --arg c "$CLUSTER" '{dataset:"slowlogs",field:"date",scope:{org:$o,cluster:$c}}')")
    if [ -z "$DAY" ]; then
      DAY=$(date -u +%Y-%m-%d)
    else
      DAY=$(olap_normalize_date "$DAY" 2>/dev/null || echo "$DAY")
      # slowlogs partition is yyyyMMdd; normalize to yyyy-MM-dd for helpers if needed
      if [[ "$DAY" =~ ^[0-9]{8}$ ]]; then
        DAY="${DAY:0:4}-${DAY:4:2}-${DAY:6:2}"
      fi
    fi
    BODY=$(jq -n --arg o "$ORG" --arg c "$CLUSTER" --arg d "$DAY" '{
      dataset:"slowlogs",
      scope:{org:$o, cluster:$c, date:$d},
      sql:"SELECT time, query_time, substr(query,1,80) AS query FROM slowlogs ORDER BY query_time DESC LIMIT 3",
      wait_seconds:90
    }' | attach_time_range slowlogs "$DAY")
    if OUT=$(run_q "$BODY"); then
      check "slowlogs" ok "org=$ORG cluster=$CLUSTER date=$DAY rows=$(echo "$OUT" | jq '.data.rows|length')"
    else
      check "slowlogs" fail "$(echo "$OUT" | jq -c '{message,full_text,error:.data.error_message}')"
    fi
  fi
fi

log "=== summary: PASS=$PASS FAIL=$FAIL SKIP=$SKIP ==="
[ "$FAIL" -eq 0 ]
