#!/bin/bash

masterfile="/srv/system.yaml"; configfile="/srv/containers.yaml"; button_ok0="Criar"
labels=("nome_custom" "$CustmN2" "$CustmN3" "$CustmN4" "$CustmN5" "$CustmN6" "$CustmN7" "$CustmN8" "$CustmN9" "$CustmN10")
values=("$NOMECONTAINER" "$VALUE2" "$VALUE3" "$VALUE4" "$VALUE5" "$VALUE6" "$VALUE7" "$VALUE8" "$VALUE9" "$VALUE10")

##############################################################
# ESTE SCRIPT SÓ RODA SOB FUNÇÕES!
# NADA FORA DE FUNÇÕES SERÁ EXECUTADO.
##############################################################

# source /root/.index.sh AQUI NAO FUNCIONA!

# To run out of server:
# common_functions_url=HTTPS://LINK_TO_THIS_FILE/X-COMMON-BASE.sh"
# curl -sSL "$common_functions_url" -o /tmp/common-functions.sh
# bash /tmp/common-functions.sh

function debug_flux {
# COMMENT OR UNCOMMENT TURN ON OR OFF THE DEBUG FLUX
# NEVER use clear!
  echo . >/dev/null
  #echo $1; echo $2; echo $3; echo $4; echo $5; echo $6; echo $7; echo $8; echo $9; echo $10; echo $11; echo $12; echo $13; echo $14; echo $15; sleep 1
}

function check_root {
  debug_flux "func check_root"
  
  [ "$EUID" -ne 0 ] && {
    echo "Execute esse script como Root! Saindo..."
    exit 1
  }
  
  debug_flux "check_root OK"
}

function check_macvlan {
  debug_flux "func check_macvlan"
  
  if ! docker inspect macvlan 1>/dev/null 2>/dev/null; then
    echo "ERROR: A macvlan não existe! Saindo..."; sleep 3
    exit 0
  fi
  
  debug_flux "check_macvlan OK"
}

function lockfile0 {
  debug_flux "func lockfile0"
  
  if [ -f /srv/lockfile ]; then
    if ! [ -f "$configfile" ]; then
      echo ""; echo "ERRO CRITICO: NAO ENCONTREI O $configfile COM DADOS DESTE CONTAINER! Saindo."; sleep 5
      exit 1
    else
      echo "LOCKFILE DETECTADO!"
      sleep 1
      yq -r "to_entries[] | select(.value.img_base | test(\"$imagem\")) | .key" "$configfile" | while read -r container; do
        process_container "$container"
      done
    fi
  else
    main_menu
  fi
}

function process_container {
  debug_flux "func process_container"
  local container="$1"

  # Tenta YAML primeiro
  local yaml_repo=$(yq -r '.["'"$container"'"].docker_repo' "$configfile" 2>/dev/null)

  if [[ "$yaml_repo" == "null" || -z "$yaml_repo" ]]; then
    # Não tem no YAML, tenta variável exportada pelo script
    if [[ -z "$docker_repo" ]]; then
      # Não tem exportado, tenta extrair do Git pela img_base
      echo "⚠️  docker_repo não encontrado no YAML nem exportado"

      local img_base=$(yq -r '.["'"$container"'"].img_base' "$configfile" 2>/dev/null)
      echo "🔍 Tentando descobrir automaticamente pela img_base: $img_base"

      docker_repo=$(get_docker_repo_from_script "$img_base")

      if [[ -z "$docker_repo" ]]; then
        echo "❌ ERRO: docker_repo não encontrado para $container (img_base: $img_base)!"
        echo "Verifique se o script correspondente existe e tem docker_repo definido."
        sleep 3
        exit 1
      fi

      echo "✅ Descoberto: $docker_repo"
    fi
  else
    docker_repo="$yaml_repo"
    echo "📦 Usando docker_repo do YAML: $docker_repo"
  fi

  debug_flux "$container" "$docker_repo"

  # Carrega os outros valores do YAML
  for i in "${!labels[@]}"; do
    val="$(yq -r '.["'"$container"'"].["'"${labels[$i]}"'"]' "$configfile")"
    if [[ "$val" == "null" || -z "$val" ]]; then
      eval "VALUE$((i+1))=\"\""
      values[i]=""
    else
      eval "VALUE$((i+1))=\"$val\""
      values[i]="$val"
    fi
  done

  export NOMECONTAINER="$container"

  debug_flux "$NOMECONTAINER"

  signal0
  set_mkdir

  if ! docker_create; then
    echo "ERRO: Falha ao criar o container $NOMECONTAINER!"
    echo "Saindo..."
    sleep 3
    exit 1
  fi

  docker_extras
  save_config
}

function load_data {
  debug_flux "func load_data"

  if ! [ -f "$configfile" ]; then
    return
  fi

  # Verifica quantos containers existem com essa imagem
  containers_count=$(yq -r "to_entries[] | select(.value.img_base == \"$imagem\") | .key" "$configfile" | wc -l)
  
  if [ "$containers_count" -gt 1 ]; then
    # Múltiplos containers da mesma imagem
    LISTANOMES=$(yq -r 'to_entries[] | select(.value.img_base == "'"$imagem"'") | .value.nome_custom' "$configfile")
    NOMECONTAINER=$(dialog --title "Imagem detectada: $imagem" --backtitle "W A R N I N G" --ok-button "Carregar" --no-cancel --inputbox "Encontrei um ou mais de um container registrado com essa imagem! Qual deseja carregar?\nValores encontrados:\n$LISTANOMES" 0 0 "" 2>&1 > /dev/tty)
    
    # Carrega os dados do container selecionado
    load_container_data
    button_ok0="Recriar"
    
  elif [ "$containers_count" -eq 1 ]; then
    # Um container existe, pergunta o que fazer
    existing_container=$(yq -r 'to_entries[] | select(.value.img_base == "'"$imagem"'") | .key' "$configfile")
    
    if dialog --title "Container existente detectado" --yes-label "Recriar existente" --no-label "Criar novo" --yesno "Encontrei o container '$existing_container' com a mesma imagem.\n\nO que deseja fazer?" 10 60; then
      # Usuário escolheu recriar o existente
      NOMECONTAINER="$existing_container"
      load_container_data
      button_ok0="Recriar"
    else
      # Usuário escolheu criar um novo, mantém campos vazios
      return
    fi
  fi
}

function load_container_data {
  debug_flux "func load_container_data"

  for i in "${!labels[@]}"; do
    val="$(yq -r '.["'"$NOMECONTAINER"'"].["'"${labels[$i]}"'"]' "$configfile")"
    if [[ "$val" == "null" || -z "$val" ]]; then
      eval "VALUE$((i+1))=\"${values[$i]}\""
      values[i]="${values[$i]}"
    else
      eval "VALUE$((i+1))=\"$val\""
      values[i]="$val"
    fi
  done
}

function save_config {
  debug_flux "func save_config"

  sudo touch "$configfile"

  datetime0=$(date +"%d-%m-%Y_%H:%M")
  sudo yq -i ".\"${NOMECONTAINER}\".instalacao = \"${datetime0}\"" "$configfile"
  sudo yq -i ".\"${NOMECONTAINER}\".img_base = \"${imagem}\"" "$configfile"
  sudo yq -i ".\"${NOMECONTAINER}\".docker_repo = \"${docker_repo}\"" "$configfile"

  for i in "${!labels[@]}"; do
    sudo yq -i ".\"${NOMECONTAINER}\".\"${labels[$i]}\" = \"${values[$i]}\"" "$configfile"
  done
  
  debug_flux "CONFIG SAVED!"
}

function main_menu {
  debug_flux "func main_menu"
  
  load_data
  debug_flux "data loaded"
  
  form_args=()
  for idx in "${!labels[@]}"; do
    line=$((idx+1))
    form_args+=("${labels[$idx]}:" "$line" 1 "${values[$idx]}" "$line" 17 150 0)
  done

  if ! form=$(dialog --ok-label "$button_ok0" --title "Novo Container" --form "Imagem Base: $imagem" 17 80 0 \
    "${form_args[@]}" 3>&1 1>&2 2>&3 3>&- > /dev/tty); then
    return
  fi

  mapfile -t VALUES <<< "$form"
  for i in {1..10}; do
    eval "VALUE$i=\"\${VALUES[$((i-1))]}\""
    values[i-1]="${VALUES[$((i-1))]}"
  done

  export NOMECONTAINER="${VALUES[0]}"

  debug_flux "$NOMECONTAINER"

  check_IP
}

function check_IP {
  debug_flux "func check_IP and docker pull here"
  
  # Tenta carregar do configfile (se já existe)
  local saved_repo=$(yq -r '.["'"$NOMECONTAINER"'"].docker_repo' "$configfile" 2>/dev/null)
  
  # Se não encontrou no YAML, usa a variável exportada do script específico
  if [[ "$saved_repo" == "null" || -z "$saved_repo" ]]; then
    if [[ -z "$docker_repo" ]]; then
      echo "ERRO: docker_repo não definido!"
      exit 1
    fi
    # Usa o docker_repo do script específico
  else
    # Usa o docker_repo salvo no YAML
    docker_repo="$saved_repo"
  fi
  
  local ip_regex="^([0-9]{1,3}\.){3}[0-9]{1,3}$"

  # Se NAO for numerico, ignore a verificacao.
  if [[ ! "$VALUE2" =~ $ip_regex ]]; then
    save_config
    mkdir0
    
    # PULL DA IMAGEM ANTES DE CRIAR
    echo "Baixando imagem $docker_repo..."
    if ! docker pull "$docker_repo"; then
      echo "ERRO: Falha ao puxar $docker_repo do container $NOMECONTAINER!"
      exit 1
    fi
    
    if ! docker_create; then
      echo "ERRO: Falha ao criar o container $NOMECONTAINER!"
      exit 1
    fi
    
    docker_extras
    cleanup0
    return
  fi

  # Valor numerico exemplo 192.168.0.1? Verifique!
  if ip_conflict_check "$VALUE2" "$NOMECONTAINER" "$configfile"; then
    dialog --title "ERRO" --msgbox "Conflito de IP detectado no $configfile:\nMesmo IP de outro container!" 7 40
    main_menu
  elif grep -wq "$VALUE2" "$masterfile"; then
    dialog --title "ERRO" --msgbox "Conflito de IP detectado no $masterfile:\nMesmo IP do host!" 7 40
    main_menu
  else
    save_config
    mkdir0
    
    # PULL DA IMAGEM ANTES DE CRIAR
    echo "Baixando imagem $docker_repo..."
    if ! docker pull "$docker_repo"; then
      echo "ERRO: Falha ao puxar $docker_repo do container $NOMECONTAINER!"
      exit 1
    fi
    
    if ! docker_create; then
      echo "ERRO: Falha ao criar o container $NOMECONTAINER!"
      exit 1
    fi
    
    docker_extras
    cleanup0
  fi
}

function ip_conflict_check {
  debug_flux "func ip_conflict_check"
  
  local ip="$1"; local mycontainer="$2"; local configfile="$3"
  yq 'to_entries | map(select(.key != "'"$mycontainer"'")) | .[].value.local_ip' "$configfile" | grep -wq "$ip"
}

function mkdir0 {
  if [ -d "/srv/containers/$NOMECONTAINER" ]; then
    if ! dialog --title "WARNING" --yes-label "Prosseguir" --no-label "CANCELAR" --yesno "Foram identificados dados de volumes! \n\nParando e removendo container caso esteja rodando. \n\nSe precisar, apague o conteudo de /srv/containers/$NOMECONTAINER manualmente" 14 50; then
      exit 0
    fi
    signal0
  fi
  signal0
  set_mkdir
}

function signal0 {
  clear
  debug_flux "func signal0"
  
  # Verifica se o container existe (rodando ou parado)
  if ! docker ps -a --format '{{.Names}}' | grep -q "^${NOMECONTAINER}$"; then
    echo "Container $NOMECONTAINER removido. Continuando..."
    return 0
  fi
  
  # Verifica se tem volume correspondente
  if [ ! -d /srv/containers/"$NOMECONTAINER" ]; then
    echo "AVISO: Container $NOMECONTAINER executando SEM VOLUME correspondente!"
  fi
  
  # Verifica se está rodando e tenta parar graciosamente
  if docker ps --format '{{.Names}}' | grep -q "^${NOMECONTAINER}$"; then
    echo "Parando container $NOMECONTAINER graciosamente..."
    if ! docker stop "$NOMECONTAINER"; then
      echo "ERRO: Não consegui parar o container $NOMECONTAINER."
      exit 1
    fi
    echo "Container parado com sucesso."
  else
    echo "Container $NOMECONTAINER já está parado."
  fi
  
  # Remove o container (já parado)
  if ! docker rm "$NOMECONTAINER"; then
    echo "ERRO: Não consegui remover o container $NOMECONTAINER."
    exit 1
  fi
  
  echo "Container $NOMECONTAINER removido com sucesso."
  sleep 3
}

function get_docker_repo_from_script {
  local img_base="$1"
  local script_url=""

  # Mapeamento img_base → link do .index.sh
  case "$img_base" in
    "pihole") script_url="$link024" ;;
    "active-directory"|"domain") script_url="$link025" ;;
    "unifi") script_url="$link026" ;;
    "mysql") script_url="$link027" ;;
    "oraclexe21c") script_url="$link028" ;;
    "nut") script_url="$link029" ;;
    "swc") script_url="$link030" ;;
    "pentest") script_url="$link031" ;;
    "cups") script_url="$link032" ;;
    "nobreak-sms") script_url="$link033" ;;
    "luanti") script_url="$link034" ;;
    "tailscale") script_url="$link035" ;;
    "kasm") script_url="$link036" ;;
    "kuma") script_url="$link037" ;;
    "lan-speed-test"|"openspeedtest") script_url="$link038" ;;
    "chromium"|"chromium-browser") script_url="$link039" ;;
    "chrome-browser") script_url="$link040" ;;
    "jellyfin") script_url="$link041" ;;
    "wan-speed-test"|"myspeed") script_url="$link042" ;;
    "qbittorrent") script_url="$link043" ;;
    "aptcache") script_url="$link044" ;;
    "meshstatic") script_url="$link045" ;;
    "plocate") script_url="$link046" ;;
    "ferdium") script_url="$link047" ;;
    "nextcloud") script_url="$link048" ;;
    "openfire") script_url="$link049" ;;
    "filebrowser") script_url="$link050" ;;
    "mariadb") script_url="$link051" ;;
    "minecraft") script_url="$link053" ;;
    "docker-macos") script_url="$link054" ;;
    "reverse-proxy") script_url="$link055" ;;
    "onlyoffice") script_url="$link056" ;;
    "docker-windows") script_url="$link057" ;;
    "apache2") script_url="$link058" ;;
    "ftp") script_url="$link059" ;;
    "dwservice") script_url="$link060" ;;
    "syncthing") script_url="$link061" ;;
    "xpra") script_url="$link062" ;;
    "homarr-web-panel"|"homarr") script_url="$link064" ;;
    "dashdot") script_url="$link065" ;;
    "qdir") script_url="$link066" ;;
    "elasticsearch-db"|"elasticsearch") script_url="$link067" ;;
    "sist2"|"elastic-search-gui") script_url="$link068" ;;
    *) echo ""; return 1 ;;
  esac

  if [ -z "$script_url" ]; then
    return 1
  fi

  # Baixa o script e extrai docker_repo
  local repo=$(curl -sSL --connect-timeout 5 --max-time 10 "$script_url" 2>/dev/null | grep '^docker_repo=' | head -1 | cut -d'"' -f2)

  if [ -n "$repo" ]; then
    echo "$repo"
    return 0
  else
    return 1
  fi
}

function cleanup0 {
  debug_flux "func cleanup0"

  for i in {1..10}; do
    unset "VALUE$i"
  done

  for i in {1..10}; do
    unset "CustmN$i"
  done

  debug_flux "Limpando imagens e volumes desnecessarios..."
  docker image prune -a -f
  docker volume prune -a -f
  sleep 1
}

function execute_main {
  debug_flux "func execute_main"
  check_root
  check_macvlan
  lockfile0
}
