#!/usr/bin/env bash
set -u

export LANG="${LANG:-C.UTF-8}"
export LC_ALL="${LC_ALL:-C.UTF-8}"
export TERM="${TERM:-linux}"

NVR_INSTALL_ROOT="${NVR_INSTALL_ROOT:-/opt/nvr}"
NVR_REFRESH_SECONDS="${NVR_REFRESH_SECONDS:-5}"
NVR_RECORDINGS_ROOT="${NVR_RECORDINGS_ROOT:-/var/lib/nvr/recordings}"

hide_cursor() {
  printf '\033[?25l'
}

show_cursor() {
  printf '\033[?25h'
}

clear_screen() {
  printf '\033[H\033[2J\033[3J'
}

on_exit() {
  show_cursor
  printf '\033[0m\n'
}
trap on_exit EXIT
trap 'on_exit; exit 0' INT TERM

color() {
  case "$1" in
    green) printf '\033[1;32m' ;;
    yellow) printf '\033[1;33m' ;;
    red) printf '\033[1;31m' ;;
    blue) printf '\033[1;34m' ;;
    cyan) printf '\033[1;36m' ;;
    dim) printf '\033[2m' ;;
    bold) printf '\033[1m' ;;
    reset|*) printf '\033[0m' ;;
  esac
}

primary_ip() {
  local ip_value
  ip_value="$(ip -o -4 route get 1.1.1.1 2>/dev/null | awk '{for (i=1; i<=NF; i++) if ($i == "src") {print $(i+1); exit}}')"
  if [ -z "$ip_value" ]; then
    ip_value="$(hostname -I 2>/dev/null | awk '{print $1}')"
  fi
  printf '%s' "${ip_value:-}"
}

network_state() {
  local ip_value="$1"
  if [ -n "$ip_value" ] && ip -4 route show default >/dev/null 2>&1; then
    printf 'Conectada'
    return
  fi

  if [ -n "$ip_value" ]; then
    printf 'Rede local detectada'
    return
  fi

  printf 'Sem conexão de rede'
}

wifi_summary() {
  if ! command -v nmcli >/dev/null 2>&1; then
    printf 'Ferramentas ausentes'
    return
  fi

  local line state connection
  line="$(nmcli -t -f DEVICE,TYPE,STATE,CONNECTION device status 2>/dev/null | awk -F: '$2 == "wifi" {print; exit}')"
  if [ -z "$line" ]; then
    printf 'Nao detectado'
    return
  fi

  state="$(printf '%s' "$line" | awk -F: '{print $3}')"
  connection="$(printf '%s' "$line" | awk -F: '{print $4}')"
  case "$state" in
    connected)
      printf 'Conectado'
      [ -n "$connection" ] && printf ' - %s' "$connection"
      ;;
    disconnected)
      printf 'Disponivel'
      ;;
    unavailable|unmanaged)
      printf 'Indisponivel'
      ;;
    *)
      printf '%s' "${state:-Detectando}"
      ;;
  esac
}

service_state() {
  local unit="$1"
  if systemctl is-active --quiet "$unit" 2>/dev/null; then
    printf 'ativo'
  else
    printf 'aguardando'
  fi
}

json_value() {
  local path="$1"
  local key_path="$2"

  [ -s "$path" ] || return 0
  if command -v php >/dev/null 2>&1; then
    php -r '
      $path = $argv[1] ?? "";
      $keyPath = explode(".", $argv[2] ?? "");
      $data = is_file($path) ? json_decode((string) file_get_contents($path), true) : null;
      if (!is_array($data)) {
          exit(0);
      }
      $value = $data;
      foreach ($keyPath as $key) {
          if (!is_array($value) || !array_key_exists($key, $value)) {
              exit(0);
          }
          $value = $value[$key];
      }
      if (is_bool($value)) {
          echo $value ? "true" : "false";
          exit(0);
      }
      if (is_scalar($value)) {
          echo (string) $value;
      }
    ' "$path" "$key_path" 2>/dev/null || true
    return
  fi

  case "$key_path" in
    registered)
      grep -Eq '"registered"[[:space:]]*:[[:space:]]*true' "$path" && printf 'true' || true
      ;;
    gateway_token)
      sed -n 's/.*"gateway_token"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' "$path" | head -1
      ;;
    license.status)
      sed -n 's/.*"status"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' "$path" | head -1
      ;;
  esac
}

gateway_state_file() {
  local candidate
  for candidate in \
    "$NVR_INSTALL_ROOT/gateway/storage/cache/gateway-state.json" \
    "$NVR_INSTALL_ROOT/gateway/storage/gateway-state.json" \
    "$NVR_INSTALL_ROOT/storage/gateway-state.json" \
    /var/lib/nvr/gateway-state.json \
    /var/lib/nvr/state/gateway-state.json; do
    if [ -s "$candidate" ]; then
      printf '%s' "$candidate"
      return
    fi
  done
}

platform_activation_state() {
  if ! command -v curl >/dev/null 2>&1; then
    return 1
  fi

  local url body
  for url in \
    "http://127.0.0.1/nvr/ativacao" \
    "http://localhost/nvr/ativacao"; do
    body="$(curl -fsS --max-time 3 "$url" 2>/dev/null || true)"
    [ -n "$body" ] || continue

    if printf '%s' "$body" | grep -Eiq 'nvr-activation-success|Appliance pronto|Ativa..o conclu.da'; then
      printf 'Ativado'
      return 0
    fi
  done

  return 1
}

activation_state() {
  local state_file registered token license_status platform_status
  if systemctl is-active --quiet nvr-first-boot-install.service 2>/dev/null; then
    printf 'Instalação em andamento'
    return
  fi

  if [ ! -f /var/lib/nvr/FIRST_BOOT_DONE ] && [ ! -d "$NVR_INSTALL_ROOT/gateway" ]; then
    printf 'Preparando primeiro boot'
    return
  fi

  state_file="$(gateway_state_file)"
  registered="$(json_value "$state_file" registered)"
  token="$(json_value "$state_file" gateway_token)"
  license_status="$(json_value "$state_file" license.status)"

  if [ "$registered" = "true" ] && [ -n "$token" ]; then
    if [ -n "$license_status" ]; then
      printf 'Ativado - licença %s' "$license_status"
    else
      printf 'Ativado'
    fi
    return
  fi

  if platform_status="$(platform_activation_state)"; then
    printf '%s' "$platform_status"
    return
  fi

  printf 'Pendente'
}

system_summary() {
  if systemctl is-active --quiet nvr-first-boot-install.service 2>/dev/null; then
    printf 'Instalando e configurando'
    return
  fi

  if systemctl is-active --quiet nvr-stack.target 2>/dev/null \
    && systemctl is-active --quiet gateway-local-web.service 2>/dev/null; then
    printf 'Funcionando'
    return
  fi

  if [ -f /var/lib/nvr/PARTIAL_INSTALL ]; then
    printf 'Atenção necessária'
    return
  fi

  printf 'Inicializando serviços'
}

camera_summary() {
  local status_file online offline total
  for status_file in \
    /var/lib/nvr/cameras-status.json \
    "$NVR_INSTALL_ROOT/gateway/storage/cache/cameras-status.json" \
    "$NVR_INSTALL_ROOT/platform/storage/app/nvr/cameras-status.json"; do
    if [ -s "$status_file" ] && command -v php >/dev/null 2>&1; then
      php -r '
        $data = json_decode((string) file_get_contents($argv[1]), true);
        $items = is_array($data["cameras"] ?? null) ? $data["cameras"] : (is_array($data) ? $data : []);
        $online = 0;
        $offline = 0;
        foreach ($items as $item) {
            if (!is_array($item)) {
                continue;
            }
            $status = strtolower((string) ($item["status"] ?? ""));
            if (in_array($status, ["online", "ok", "active", "ativa"], true)) {
                $online++;
            } else {
                $offline++;
            }
        }
        echo $online . " online / " . $offline . " offline";
      ' "$status_file" 2>/dev/null || true
      return
    fi
  done

  online=0
  offline=0
  total=0
  printf '%s online / %s offline' "$online" "$offline"
  [ "$total" -gt 0 ] 2>/dev/null || true
}

recording_summary() {
  local activation="$1"
  if printf '%s' "$activation" | grep -qi 'pendente\|primeiro boot\|instalação'; then
    printf 'Aguardando ativação'
    return
  fi

  if [ -d "$NVR_RECORDINGS_ROOT" ]; then
    printf 'Aguardando configuração'
    return
  fi

  printf 'Aguardando disco de gravações'
}

storage_summary() {
  local target used pct
  target="$NVR_RECORDINGS_ROOT"
  [ -d "$target" ] || target="/"
  used="$(df -hP "$target" 2>/dev/null | awk 'NR==2 {print $3 " de " $2}')"
  pct="$(df -hP "$target" 2>/dev/null | awk 'NR==2 {print $5}')"
  if [ -n "$used" ]; then
    printf 'OK - %s usado (%s)' "$used" "$pct"
  else
    printf 'Aguardando leitura'
  fi
}

status_color() {
  case "$1" in
    *Funcionando*|*Conectada*|*Conectado*|*Ativado*|OK*) color green ;;
    *Pendente*|*Aguardando*|*Preparando*|*Inicializando*|*Instalando*) color yellow ;;
    *Sem*|*Atenção*) color red ;;
    *Indisponivel*|*ausentes*) color red ;;
    *) color reset ;;
  esac
}

line() {
  printf '%*s\n' 78 '' | tr ' ' '-'
}

draw_panel() {
  local ip_value network wifi activation system_status cameras recording storage now access_url
  ip_value="$(primary_ip)"
  network="$(network_state "$ip_value")"
  wifi="$(wifi_summary)"
  activation="$(activation_state)"
  system_status="$(system_summary)"
  cameras="$(camera_summary)"
  recording="$(recording_summary "$activation")"
  storage="$(storage_summary)"
  now="$(date '+%d/%m/%Y %H:%M:%S')"

  if [ -n "$ip_value" ]; then
    access_url="http://${ip_value}/nvr/"
  else
    access_url="Aguardando IP da rede"
  fi

  clear_screen
  hide_cursor
  color blue; printf 'NVR APPLIANCE\n'; color reset
  color bold; printf 'Sistema local iniciado\n'; color reset
  printf 'Atualizado em %s\n' "$now"
  line
  printf '\n'

  printf '  %-24s ' 'Status do sistema:'
  status_color "$system_status"; printf '%s\n' "$system_status"; color reset

  printf '  %-24s ' 'Rede:'
  status_color "$network"; printf '%s\n' "$network"; color reset

  printf '  %-24s ' 'Wi-Fi:'
  status_color "$wifi"; printf '%s\n' "$wifi"; color reset

  printf '  %-24s ' 'Endereço de acesso:'
  color cyan; printf '%s\n' "$access_url"; color reset

  printf '  %-24s ' 'Ativação:'
  status_color "$activation"; printf '%s\n' "$activation"; color reset

  printf '  %-24s %s\n' 'Câmeras:' "$cameras"
  printf '  %-24s %s\n' 'Gravação:' "$recording"
  printf '  %-24s %s\n' 'Armazenamento:' "$storage"
  printf '\n'
  line
  printf '\n'
  color bold; printf 'Acesse pelo navegador\n'; color reset
  printf '  %s\n' "$access_url"
  printf '\n'
  printf 'Para gerar ou consultar o serial de ativação, acesse o Portal Principal:\n'
  color cyan; printf '  https://simplavende.com.br\n'; color reset
  printf '\n'

  if [ -z "$ip_value" ]; then
    color yellow
    printf 'Sem conexão de rede. Verifique o cabo ou configure a rede no modo técnico.\n'
    color reset
  elif printf '%s' "$activation" | grep -qi 'pendente'; then
    printf 'A primeira ativação exige internet para validar o serial no Portal Principal.\n'
  fi

  printf '\n'
  color dim
  printf 'Modo técnico: pressione T para abrir o console técnico em outra tela, ou use SSH autorizado.\n'
  printf 'Wi-Fi: pressione W para configurar.\n'
  printf 'Suporte remoto: libere pelo Portal Principal quando solicitado.\n'
  color reset
}

open_wifi_config() {
  show_cursor
  printf '\033[0m'
  clear_screen
  if command -v nvr-wifi-configure >/dev/null 2>&1; then
    nvr-wifi-configure || true
  else
    printf 'nvr-wifi-configure nao encontrado. Instale network-manager, wpasupplicant, iw e rfkill.\n'
  fi
  printf '\nPressione Enter para voltar ao painel...'
  IFS= read -r _ || true
  hide_cursor
}

while true; do
  draw_panel
  key=''
  IFS= read -rsn1 -t "$NVR_REFRESH_SECONDS" key || true
  case "$key" in
    w|W)
      open_wifi_config
      ;;
    t|T)
      chvt 2 >/dev/null 2>&1 || true
      ;;
  esac
done
