#!/bin/sh
set -eu

SERVICE_NAME="mr-media-bot"
SERVICE_UNIT="$SERVICE_NAME.service"
APP_DIR="/opt/mr-media-bot"
APP_BIN="$APP_DIR/MR-media-bot"
DATA_DIR="${MR_MEDIA_BOT_DATA_DIR:-/var/lib/mr-media-bot}"
RUN_USER="${MR_MEDIA_BOT_RUN_USER:-mr-media-bot}"

need_systemctl() {
  if ! command -v systemctl >/dev/null 2>&1; then
    echo "systemctl não está disponível neste sistema." >&2
    exit 1
  fi
}

need_root() {
  if [ "$(id -u)" -ne 0 ]; then
    echo "Execute este comando com sudo: sudo mr-media-bot $*" >&2
    exit 1
  fi
}

run_as_bot_user() {
  if command -v runuser >/dev/null 2>&1; then
    runuser -u "$RUN_USER" -- "$@"
  else
    echo "Não foi possível alternar para o usuário $RUN_USER porque runuser não está disponível." >&2
    exit 1
  fi
}

ask_yes_no() {
  printf "%s [s/N]: " "$1"
  read -r answer || answer=""
  case "$answer" in
    s|S|sim|SIM|Sim|y|Y|yes|YES|Yes) return 0 ;;
    *) return 1 ;;
  esac
}

configured_web_port() {
  run_as_bot_user env MR_MEDIA_BOT_DATA_DIR="$DATA_DIR" "$APP_BIN" --data-dir "$DATA_DIR" --print-web-port 2>/dev/null | tail -n 1
}

ufw_active() {
  command -v ufw >/dev/null 2>&1 && ufw status 2>/dev/null | grep -qi "Status: active"
}

firewalld_active() {
  command -v firewall-cmd >/dev/null 2>&1 && firewall-cmd --state >/dev/null 2>&1
}

nft_input_filter_active() {
  command -v nft >/dev/null 2>&1 && nft list ruleset 2>/dev/null | grep -Eq "hook input|policy drop|policy reject"
}

iptables_input_filter_active() {
  command -v iptables >/dev/null 2>&1 && iptables -S INPUT 2>/dev/null | grep -Eq "^-P INPUT DROP|^-A INPUT .* (DROP|REJECT)"
}

firewall_port_needs_opening() {
  CHECK_PORT="$1"
  FIREWALL_FOUND=0
  FIREWALL_NEEDS_OPENING=0
  if ufw_active; then
    FIREWALL_FOUND=1
    if ufw status 2>/dev/null | grep -Eq "(^|[[:space:]])${CHECK_PORT}/tcp[[:space:]]+ALLOW"; then
      echo "UFW: porta $CHECK_PORT/tcp já permitida."
    else
      echo "UFW: porta $CHECK_PORT/tcp ainda não está permitida."
      FIREWALL_NEEDS_OPENING=1
    fi
  fi
  if firewalld_active; then
    FIREWALL_FOUND=1
    if firewall-cmd --quiet --query-port="${CHECK_PORT}/tcp" >/dev/null 2>&1; then
      echo "firewalld: porta $CHECK_PORT/tcp já permitida."
    else
      echo "firewalld: porta $CHECK_PORT/tcp ainda não está permitida."
      FIREWALL_NEEDS_OPENING=1
    fi
  fi
  if nft_input_filter_active; then
    FIREWALL_FOUND=1
    if nft list ruleset 2>/dev/null | grep -Eq "tcp dport (${CHECK_PORT}|\\{[^}]*${CHECK_PORT}[^}]*\\}).*accept"; then
      echo "nftables: porta $CHECK_PORT/tcp parece já permitida."
    else
      echo "nftables: não encontrei regra explícita para a porta $CHECK_PORT/tcp."
      FIREWALL_NEEDS_OPENING=1
    fi
  fi
  if iptables_input_filter_active; then
    FIREWALL_FOUND=1
    if iptables -C INPUT -p tcp --dport "$CHECK_PORT" -j ACCEPT >/dev/null 2>&1; then
      echo "iptables: porta $CHECK_PORT/tcp já permitida."
    else
      echo "iptables: porta $CHECK_PORT/tcp ainda não está permitida."
      FIREWALL_NEEDS_OPENING=1
    fi
  fi
  if [ "$FIREWALL_FOUND" -eq 0 ]; then
    echo "Não encontrei um firewall local ativo conhecido nesta VPS."
    return 1
  fi
  [ "$FIREWALL_NEEDS_OPENING" -eq 1 ]
}

open_firewall_port() {
  OPEN_PORT="$1"
  OPENED_ANY=0
  if ufw_active; then
    if ufw allow "${OPEN_PORT}/tcp"; then
      OPENED_ANY=1
    else
      echo "UFW: não foi possível liberar a porta automaticamente."
    fi
  fi
  if firewalld_active; then
    if firewall-cmd --add-port="${OPEN_PORT}/tcp" >/dev/null 2>&1 && firewall-cmd --permanent --add-port="${OPEN_PORT}/tcp" >/dev/null 2>&1 && firewall-cmd --reload >/dev/null 2>&1; then
      OPENED_ANY=1
    else
      echo "firewalld: não foi possível liberar a porta automaticamente."
    fi
  fi
  if nft_input_filter_active; then
    nft add table inet mr_media_bot >/dev/null 2>&1 || true
    nft 'add chain inet mr_media_bot input { type filter hook input priority -100; policy accept; }' >/dev/null 2>&1 || true
    if ! nft list ruleset 2>/dev/null | grep -Eq "tcp dport (${OPEN_PORT}|\\{[^}]*${OPEN_PORT}[^}]*\\}).*accept"; then
      nft add rule inet mr_media_bot input tcp dport "$OPEN_PORT" accept >/dev/null 2>&1 || echo "nftables: não foi possível adicionar regra automática."
    fi
    echo "nftables: regra aplicada para esta sessão. A persistência depende da configuração nftables da distro."
    OPENED_ANY=1
  fi
  if iptables_input_filter_active; then
    if iptables -C INPUT -p tcp --dport "$OPEN_PORT" -j ACCEPT >/dev/null 2>&1 || iptables -I INPUT 1 -p tcp --dport "$OPEN_PORT" -j ACCEPT; then
      if command -v netfilter-persistent >/dev/null 2>&1; then
        netfilter-persistent save >/dev/null 2>&1 || true
      elif [ -d /etc/iptables ]; then
        iptables-save > /etc/iptables/rules.v4 2>/dev/null || true
      else
        echo "iptables: regra aplicada para esta sessão. Instale/configure persistência se sua distro exigir."
      fi
      OPENED_ANY=1
    else
      echo "iptables: não foi possível liberar a porta automaticamente."
    fi
  fi
  [ "$OPENED_ANY" -eq 1 ]
}

ensure_firewall_port() {
  WEB_PORT="$1"
  echo "Verificando firewall local para a porta $WEB_PORT/tcp..."
  if firewall_port_needs_opening "$WEB_PORT"; then
    if ask_yes_no "Deseja que o MR-media-bot tente liberar automaticamente a porta $WEB_PORT/tcp nos firewalls locais encontrados?"; then
      if open_firewall_port "$WEB_PORT"; then
        echo "Regras de firewall aplicadas. Verificando novamente..."
        firewall_port_needs_opening "$WEB_PORT" >/dev/null 2>&1 || echo "Firewall local verificado para a porta $WEB_PORT/tcp."
      else
        echo "Não foi possível aplicar regra automática em nenhum firewall local conhecido."
      fi
    else
      echo "A porta não foi aberta automaticamente. Se o painel não abrir externamente, libere a porta $WEB_PORT/tcp manualmente."
    fi
  else
    echo "Firewall local não indicou bloqueio para a porta $WEB_PORT/tcp."
  fi
}

http_available() {
  CHECK_URL="$1"
  if command -v curl >/dev/null 2>&1; then
    curl -fsSL --max-time 5 -o /dev/null "$CHECK_URL" >/dev/null 2>&1
    return $?
  fi
  if command -v wget >/dev/null 2>&1; then
    wget -q --timeout=5 -O /dev/null "$CHECK_URL" >/dev/null 2>&1
    return $?
  fi
  return 2
}

public_ip_address() {
  if command -v curl >/dev/null 2>&1; then
    curl -fsS --max-time 5 https://api.ipify.org 2>/dev/null || true
    return
  fi
  if command -v wget >/dev/null 2>&1; then
    wget -q --timeout=5 -O - https://api.ipify.org 2>/dev/null || true
    return
  fi
}

check_panel_access() {
  WEB_PORT="$1"
  echo "Verificando resposta local do painel web..."
  LOCAL_OK=0
  for attempt in 1 2 3 4 5; do
    if http_available "http://127.0.0.1:${WEB_PORT}/"; then
      LOCAL_OK=1
      break
    fi
    sleep 1
  done
  if [ "$LOCAL_OK" -eq 1 ]; then
    echo "Painel respondeu localmente em http://127.0.0.1:${WEB_PORT}/"
  else
    echo "Ainda não consegui confirmar resposta local do painel. Use 'mr-media-bot status' e 'mr-media-bot logs' para acompanhar a inicialização."
  fi
  PUBLIC_IP="$(public_ip_address)"
  if [ -n "$PUBLIC_IP" ]; then
    if http_available "http://${PUBLIC_IP}:${WEB_PORT}/"; then
      echo "Também consegui resposta usando o IP público: http://${PUBLIC_IP}:${WEB_PORT}/"
    else
      echo "Não consegui confirmar acesso usando o IP público http://${PUBLIC_IP}:${WEB_PORT}/ a partir desta VPS."
      echo "Se o acesso local funciona, o bloqueio restante pode estar no firewall do provedor, NAT, painel da hospedagem ou rota externa."
    fi
  else
    echo "Não foi possível descobrir o IP público automaticamente para testar acesso externo."
  fi
}

service_status() {
  need_systemctl
  systemctl status "$SERVICE_UNIT" --no-pager
}

show_help() {
  cat <<HELP
MR-media-bot Linux

Uso:
  mr-media-bot                 Mostra o status do serviço ou orienta a configuração inicial.
  sudo mr-media-bot configure  Reabre a configuração inicial do painel web e inicia o serviço.
  sudo mr-media-bot start      Inicia o serviço.
  sudo mr-media-bot stop       Para o serviço.
  sudo mr-media-bot restart    Reinicia o serviço.
  mr-media-bot status          Mostra o status do serviço.
  mr-media-bot logs            Mostra logs em tempo real pelo journalctl.
  sudo mr-media-bot run        Executa diretamente no terminal, somente para diagnóstico.
  mr-media-bot help            Mostra esta ajuda.

Dados, banco, cache e logs ficam em:
  $DATA_DIR
HELP
}

command="${1:-}"
case "$command" in
  "" )
    need_systemctl
    if systemctl is-active --quiet "$SERVICE_UNIT"; then
      service_status
    elif [ -f "$DATA_DIR/mr-media-bot.db" ]; then
      echo "O serviço $SERVICE_UNIT está instalado, mas não está em execução."
      echo "Use: sudo mr-media-bot start"
    else
      echo "MR-media-bot instalado. Faça a configuração inicial com:"
      echo "  sudo mr-media-bot configure"
    fi
    ;;
  configure|config|setup )
    need_root "$command"
    need_systemctl
    systemctl stop "$SERVICE_UNIT" >/dev/null 2>&1 || true
    install -d -o "$RUN_USER" -g "$RUN_USER" -m 0750 "$DATA_DIR"
    run_as_bot_user env MR_MEDIA_BOT_DATA_DIR="$DATA_DIR" "$APP_BIN" --data-dir "$DATA_DIR" --configure
    WEB_PORT="$(configured_web_port || true)"
    if [ -n "$WEB_PORT" ]; then
      ensure_firewall_port "$WEB_PORT"
    fi
    systemctl daemon-reload
    systemctl enable "$SERVICE_UNIT"
    systemctl restart "$SERVICE_UNIT"
    echo "MR-media-bot configurado e iniciado."
    if [ -n "${WEB_PORT:-}" ]; then
      check_panel_access "$WEB_PORT"
    fi
    echo "Use 'mr-media-bot status' para acompanhar o serviço."
    ;;
  start )
    need_root "$command"
    need_systemctl
    if [ ! -f "$DATA_DIR/mr-media-bot.db" ]; then
      echo "A configuração inicial ainda não foi feita. Use: sudo mr-media-bot configure" >&2
      exit 1
    fi
    systemctl start "$SERVICE_UNIT"
    ;;
  stop )
    need_root "$command"
    need_systemctl
    systemctl stop "$SERVICE_UNIT"
    ;;
  restart )
    need_root "$command"
    need_systemctl
    if [ ! -f "$DATA_DIR/mr-media-bot.db" ]; then
      echo "A configuração inicial ainda não foi feita. Use: sudo mr-media-bot configure" >&2
      exit 1
    fi
    systemctl restart "$SERVICE_UNIT"
    ;;
  status )
    service_status
    ;;
  logs|log )
    need_systemctl
    journalctl -u "$SERVICE_UNIT" -f
    ;;
  run )
    need_root "$command"
    need_systemctl
    if systemctl is-active --quiet "$SERVICE_UNIT"; then
      echo "O serviço $SERVICE_UNIT já está em execução. Pare com 'sudo mr-media-bot stop' antes de usar o modo diagnóstico." >&2
      exit 1
    fi
    if [ ! -f "$DATA_DIR/mr-media-bot.db" ]; then
      echo "A configuração inicial ainda não foi feita. Use: sudo mr-media-bot configure" >&2
      exit 1
    fi
    shift
    cd "$APP_DIR"
    run_as_bot_user env MR_MEDIA_BOT_DATA_DIR="$DATA_DIR" "$APP_BIN" --data-dir "$DATA_DIR" --run "$@"
    ;;
  help|-h|--help )
    show_help
    ;;
  * )
    echo "Comando desconhecido: $command" >&2
    show_help
    exit 2
    ;;
esac
