#!/usr/bin/env bash

set -euo pipefail

SERVICE_NAME="${OPENCLAW_GATEWAY_SERVICE:-openclaw-gateway}"
QUEUE_NAME='["telegram","default"]'

DB_PATH="${OPENCLAW_DB_PATH:-}"
COMPOSE_PATH="${OPENCLAW_COMPOSE_PATH:-}"

print_header() {
  echo
  echo "================================================="
  echo " OpenClaw Telegram Queue Recovery"
  echo "================================================="
  echo
}

usage() {
  cat <<EOF
Uso:
  $0 status
  $0 inspect
  $0 recover

Opzionali:
  OPENCLAW_DB_PATH=/percorso/openclaw.sqlite
  OPENCLAW_COMPOSE_PATH=/percorso/cartella/docker-compose
  OPENCLAW_GATEWAY_SERVICE=openclaw-gateway

Esempi:
  $0 status
  $0 inspect
  $0 recover
EOF
}

require_command() {
  if ! command -v "$1" >/dev/null 2>&1; then
    echo "Errore: comando richiesto non trovato: $1"
    exit 1
  fi
}

unique_lines() {
  awk '!seen[$0]++'
}

choose_from_list() {
  local title="$1"
  shift
  local items=("$@")

  if [ "${#items[@]}" -eq 0 ]; then
    return 1
  fi

  if [ "${#items[@]}" -eq 1 ]; then
    echo "${items[0]}"
    return 0
  fi

  echo "$title" >&2
  echo >&2

  local i=1
  for item in "${items[@]}"; do
    echo "[$i] $item" >&2
    i=$((i + 1))
  done

  echo >&2

  while true; do
    read -r -p "Seleziona un numero: " choice

    if [[ "$choice" =~ ^[0-9]+$ ]] &&
       [ "$choice" -ge 1 ] &&
       [ "$choice" -le "${#items[@]}" ]; then
      echo "${items[$((choice - 1))]}"
      return 0
    fi

    echo "Scelta non valida."
  done
}

find_databases() {
  {
    [ -f "$HOME/.openclaw/state/openclaw.sqlite" ] && echo "$HOME/.openclaw/state/openclaw.sqlite"
    [ -f "$HOME/.config/openclaw/state/openclaw.sqlite" ] && echo "$HOME/.config/openclaw/state/openclaw.sqlite"

    find "$HOME" -type f -name "openclaw.sqlite" 2>/dev/null || true
    find /srv /opt /var/lib -type f -name "openclaw.sqlite" 2>/dev/null || true
  } | unique_lines
}

find_compose_dirs() {
  {
    find "$HOME" /srv /opt -type f \( -name "docker-compose.yml" -o -name "compose.yml" \) 2>/dev/null || true
  } | while read -r file; do
    dirname "$file"
  done | unique_lines
}

select_database() {
  if [ -n "$DB_PATH" ]; then
    if [ ! -f "$DB_PATH" ]; then
      echo "Errore: database indicato non trovato:"
      echo "  $DB_PATH"
      exit 1
    fi

    echo "$DB_PATH"
    return 0
  fi

  mapfile -t dbs < <(find_databases)

  if [ "${#dbs[@]}" -eq 0 ]; then
    echo "Non ho trovato automaticamente il database OpenClaw."
    echo "Puoi indicarlo manualmente con:"
    echo
    echo "  OPENCLAW_DB_PATH=/percorso/openclaw.sqlite $0 status"
    exit 1
  fi

  choose_from_list "Database OpenClaw trovati:" "${dbs[@]}"
}

select_compose_path() {
  if [ -n "$COMPOSE_PATH" ]; then
    if [ ! -d "$COMPOSE_PATH" ]; then
      echo "Errore: cartella Docker Compose indicata non trovata:"
      echo "  $COMPOSE_PATH"
      exit 1
    fi

    echo "$COMPOSE_PATH"
    return 0
  fi

  mapfile -t dirs < <(find_compose_dirs)

  if [ "${#dirs[@]}" -eq 0 ]; then
    echo "Non ho trovato automaticamente una cartella Docker Compose."
    echo "Puoi indicarla manualmente con:"
    echo
    echo "  OPENCLAW_COMPOSE_PATH=/percorso/cartella $0 recover"
    exit 1
  fi

  choose_from_list "Cartelle Docker Compose trovate:" "${dirs[@]}"
}

status_queue() {
  local db="$1"

  sqlite3 "$db" "
SELECT queue_name, status, COUNT(*) AS total
FROM channel_ingress_events
GROUP BY queue_name, status
ORDER BY queue_name, status;
"
}

inspect_queue() {
  local db="$1"

  sqlite3 -header -column "$db" "
SELECT event_id,
       status,
       attempts,
       received_at,
       updated_at,
       claimed_at,
       claim_owner,
       last_error,
       failed_reason
FROM channel_ingress_events
WHERE queue_name='[\"telegram\",\"default\"]'
ORDER BY updated_at DESC
LIMIT 20;
"
}

recover_queue() {
  local db="$1"
  local compose_dir="$2"

  echo "Database selezionato:"
  echo "  $db"
  echo
  echo "Cartella Docker Compose selezionata:"
  echo "  $compose_dir"
  echo
  echo "Servizio gateway:"
  echo "  $SERVICE_NAME"
  echo
  echo "Stato attuale della coda Telegram:"
  echo

  sqlite3 "$db" "
SELECT queue_name, status, COUNT(*) AS total
FROM channel_ingress_events
WHERE queue_name='[\"telegram\",\"default\"]'
GROUP BY queue_name, status;
"

  echo
  echo "Questa procedura farà:"
  echo "  1. fermerà temporaneamente il gateway OpenClaw"
  echo "  2. creerà un backup del database SQLite"
  echo "  3. marcherà come failed gli eventi Telegram in pending o claimed"
  echo "  4. riavvierà il gateway"
  echo
  echo "Non modifica token, configurazioni o pairing."
  echo "Scarta però gli update Telegram attualmente bloccati nella coda."
  echo

  read -r -p "Vuoi continuare? Scrivi SI per confermare: " confirm

  if [ "$confirm" != "SI" ]; then
    echo "Operazione annullata."
    exit 0
  fi

  cd "$compose_dir"

  echo
  echo "Fermo il gateway..."
  docker compose stop "$SERVICE_NAME"

  backup="${db}.bak-before-telegram-recovery-$(date +%Y%m%d-%H%M%S)"

  echo
  echo "Creo backup:"
  echo "  $backup"
  cp "$db" "$backup"

  echo
  echo "Marco come failed gli eventi Telegram bloccati..."
  sqlite3 "$db" "
UPDATE channel_ingress_events
SET status='failed',
    claim_owner=NULL,
    claim_token=NULL,
    claimed_at=NULL,
    failed_at=strftime('%s','now')*1000,
    failed_reason='manual skip stale telegram queue after gateway restart',
    last_error='manual recovery: stale claimed/pending telegram update',
    updated_at=strftime('%s','now')*1000
WHERE queue_name='[\"telegram\",\"default\"]'
  AND status IN ('pending','claimed');
"

  echo
  echo "Riavvio il gateway..."
  docker compose start "$SERVICE_NAME"

  echo
  echo "Stato finale:"
  echo

  status_queue "$db"

  echo
  echo "Recovery completata."
  echo "Ora apri Telegram, invia /new e poi manda un messaggio normale."
}

main() {
  require_command sqlite3

  action="${1:-}"

  case "$action" in
    status)
      print_header
      db="$(select_database)"
      echo
      echo "Database selezionato:"
      echo "  $db"
      echo
      status_queue "$db"
      ;;

    inspect)
      print_header
      db="$(select_database)"
      echo
      echo "Database selezionato:"
      echo "  $db"
      echo
      inspect_queue "$db"
      ;;

    recover)
      require_command docker
      print_header
      db="$(select_database)"
      compose_dir="$(select_compose_path)"
      echo
      recover_queue "$db" "$compose_dir"
      ;;

    -h|--help|"")
      usage
      ;;

    *)
      echo "Comando non riconosciuto: $action"
      echo
      usage
      exit 1
      ;;
  esac
}

main "$@"