#!/usr/bin/env bash

set -e

# ============================================================
# Nextcloud Docker Installer
# Debian / Ubuntu
# ============================================================

INSTALL_DIR="/opt/nextcloud"

echo "=========================================="
echo " Nextcloud Docker Installer"
echo " Debian / Ubuntu"
echo "=========================================="
echo

# ------------------------------------------------------------
# Verificar root
# ------------------------------------------------------------

if [ "$EUID" -ne 0 ]; then
    echo "[ERRO] Execute este script como root."
    echo
    echo "Exemplo:"
    echo "  curl -fsSL https://scripts.phcore.com.br/nextcloud-install.sh | sudo bash"
    exit 1
fi

# ------------------------------------------------------------
# Verificar terminal interativo
# ------------------------------------------------------------

if [ ! -e /dev/tty ]; then
    echo "[ERRO] Não foi possível acessar o terminal interativo (/dev/tty)."
    echo
    echo "Execute o script diretamente em um terminal."
    exit 1
fi

# ------------------------------------------------------------
# Verificar sistema operacional
# ------------------------------------------------------------

if [ ! -f /etc/os-release ]; then
    echo "[ERRO] Não foi possível identificar o sistema operacional."
    exit 1
fi

. /etc/os-release

OS="$ID"
VERSION_CODENAME="${VERSION_CODENAME:-}"

echo "[INFO] Sistema detectado: $PRETTY_NAME"
echo "[INFO] Codename: ${VERSION_CODENAME:-desconhecido}"
echo

case "$OS" in

    debian)
        DOCKER_REPO="https://download.docker.com/linux/debian"
        DOCKER_GPG="$DOCKER_REPO/gpg"
        ;;

    ubuntu)
        DOCKER_REPO="https://download.docker.com/linux/ubuntu"
        DOCKER_GPG="$DOCKER_REPO/gpg"

        VERSION_CODENAME="${UBUNTU_CODENAME:-$VERSION_CODENAME}"
        ;;

    *)
        echo "[ERRO] Sistema não suportado: $OS"
        echo
        echo "Este instalador suporta:"
        echo "  - Debian"
        echo "  - Ubuntu"
        exit 1
        ;;

esac

if [ -z "$VERSION_CODENAME" ]; then
    echo "[ERRO] Não foi possível determinar o codename da distribuição."
    exit 1
fi

# ------------------------------------------------------------
# Função para gerar senha aleatória
# ------------------------------------------------------------

generate_password() {
    openssl rand -base64 32 | tr -dc 'A-Za-z0-9' | head -c 24
}

# ------------------------------------------------------------
# Verificar OpenSSL
# ------------------------------------------------------------

if ! command -v openssl >/dev/null 2>&1; then

    echo "[INFO] Instalando OpenSSL para geração das senhas..."

    export DEBIAN_FRONTEND=noninteractive

    apt-get update
    apt-get install -y openssl

fi

# ------------------------------------------------------------
# Perguntas iniciais
# ------------------------------------------------------------

echo "=========================================="
echo " Configuração inicial"
echo "=========================================="
echo

# ------------------------------------------------------------
# Atualizar sistema
# ------------------------------------------------------------

read -r -p \
    "Deseja atualizar o sistema inteiro? [S/n]: " \
    UPDATE_SYSTEM </dev/tty

UPDATE_SYSTEM="${UPDATE_SYSTEM:-S}"

case "$UPDATE_SYSTEM" in

    S|s|SIM|sim|Sim)
        UPDATE_SYSTEM=true
        ;;

    N|n|NAO|nao|Não|não)
        UPDATE_SYSTEM=false
        ;;

    *)
        echo "[INFO] Opção inválida. Será utilizado o padrão: SIM"
        UPDATE_SYSTEM=true
        ;;

esac

echo

# ------------------------------------------------------------
# Timezone
# ------------------------------------------------------------

read -r -p \
    "Deseja configurar o timezone? [S/n]: " \
    CONFIGURE_TIMEZONE </dev/tty

CONFIGURE_TIMEZONE="${CONFIGURE_TIMEZONE:-S}"

case "$CONFIGURE_TIMEZONE" in

    S|s|SIM|sim|Sim)
        CONFIGURE_TIMEZONE=true
        ;;

    N|n|NAO|nao|Não|não)
        CONFIGURE_TIMEZONE=false
        ;;

    *)
        echo "[INFO] Opção inválida. Será utilizado o padrão: SIM"
        CONFIGURE_TIMEZONE=true
        ;;

esac

echo
echo "------------------------------------------"
echo " Configuração selecionada:"
echo "------------------------------------------"

if [ "$UPDATE_SYSTEM" = true ]; then
    echo " Atualizar sistema  : SIM"
else
    echo " Atualizar sistema  : NÃO"
fi

if [ "$CONFIGURE_TIMEZONE" = true ]; then
    echo " Configurar timezone: SIM"
else
    echo " Configurar timezone: NÃO"
fi

echo "------------------------------------------"
echo

# ------------------------------------------------------------
# Atualizar sistema
# ------------------------------------------------------------

if [ "$UPDATE_SYSTEM" = true ]; then

    echo
    echo "[1/8] Atualizando sistema..."
    echo

    export DEBIAN_FRONTEND=noninteractive

    apt-get update
    apt-get upgrade -y

else

    echo
    echo "[1/8] Atualização do sistema ignorada."
    echo

fi

# ------------------------------------------------------------
# Dependências
# ------------------------------------------------------------

echo
echo "[2/8] Instalando dependências..."
echo

export DEBIAN_FRONTEND=noninteractive

apt-get install -y \
    ca-certificates \
    curl \
    sudo \
    openssl

# ------------------------------------------------------------
# Configurar timezone
# ------------------------------------------------------------

if [ "$CONFIGURE_TIMEZONE" = true ]; then

    echo
    echo "[3/8] Configuração de timezone..."
    echo

    unset DEBIAN_FRONTEND

    dpkg-reconfigure tzdata </dev/tty >/dev/tty

else

    echo
    echo "[3/8] Configuração de timezone ignorada."
    echo

fi

# ------------------------------------------------------------
# Verificar Docker
# ------------------------------------------------------------

echo
echo "[4/8] Verificando Docker..."
echo

if command -v docker >/dev/null 2>&1 && \
   docker compose version >/dev/null 2>&1; then

    echo "[INFO] Docker já está instalado."
    docker --version
    docker compose version

else

    echo "[INFO] Docker não encontrado."
    echo "[INFO] Instalando Docker..."

    export DEBIAN_FRONTEND=noninteractive

    install -m 0755 -d /etc/apt/keyrings

    curl -fsSL "$DOCKER_GPG" \
        -o /etc/apt/keyrings/docker.asc

    chmod a+r /etc/apt/keyrings/docker.asc

    cat > /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: $DOCKER_REPO
Suites: $VERSION_CODENAME
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF

    apt-get update

    apt-get install -y \
        docker-ce \
        docker-ce-cli \
        containerd.io \
        docker-buildx-plugin \
        docker-compose-plugin

    systemctl enable docker
    systemctl enable containerd

    systemctl start docker

    echo
    echo "[INFO] Docker instalado:"
    docker --version
    docker compose version

fi

# ------------------------------------------------------------
# Gerar senhas padrão
# ------------------------------------------------------------

echo
echo "[5/8] Configuração do Nextcloud..."
echo

DB_ROOT_PASSWORD_DEFAULT="$(generate_password)"
DB_PASSWORD_DEFAULT="$(generate_password)"
REDIS_PASSWORD_DEFAULT="$(generate_password)"
NEXTCLOUD_ADMIN_PASSWORD_DEFAULT="$(generate_password)"

echo "As senhas abaixo serão geradas automaticamente."
echo "Pressione ENTER para utilizar a senha aleatória."
echo

# ------------------------------------------------------------
# MariaDB Root
# ------------------------------------------------------------

read -r -s -p \
    "Senha do MariaDB ROOT [ENTER = aleatória]: " \
    DB_ROOT_PASSWORD </dev/tty

echo

if [ -z "$DB_ROOT_PASSWORD" ]; then
    DB_ROOT_PASSWORD="$DB_ROOT_PASSWORD_DEFAULT"
    echo "[INFO] Senha do MariaDB ROOT gerada automaticamente."
fi

# ------------------------------------------------------------
# MariaDB Nextcloud
# ------------------------------------------------------------

read -r -s -p \
    "Senha do usuário do banco Nextcloud [ENTER = aleatória]: " \
    DB_PASSWORD </dev/tty

echo

if [ -z "$DB_PASSWORD" ]; then
    DB_PASSWORD="$DB_PASSWORD_DEFAULT"
    echo "[INFO] Senha do banco gerada automaticamente."
fi

# ------------------------------------------------------------
# Redis
# ------------------------------------------------------------

read -r -s -p \
    "Senha do Redis [ENTER = aleatória]: " \
    REDIS_PASSWORD </dev/tty

echo

if [ -z "$REDIS_PASSWORD" ]; then
    REDIS_PASSWORD="$REDIS_PASSWORD_DEFAULT"
    echo "[INFO] Senha do Redis gerada automaticamente."
fi

# ------------------------------------------------------------
# Usuário administrador
# ------------------------------------------------------------

echo

read -r -p \
    "Usuário administrador do Nextcloud [admin]: " \
    NEXTCLOUD_ADMIN_USER </dev/tty

if [ -z "$NEXTCLOUD_ADMIN_USER" ]; then
    NEXTCLOUD_ADMIN_USER="admin"
fi

# ------------------------------------------------------------
# Senha administrador
# ------------------------------------------------------------

read -r -s -p \
    "Senha do administrador do Nextcloud [ENTER = aleatória]: " \
    NEXTCLOUD_ADMIN_PASSWORD </dev/tty

echo

if [ -z "$NEXTCLOUD_ADMIN_PASSWORD" ]; then
    NEXTCLOUD_ADMIN_PASSWORD="$NEXTCLOUD_ADMIN_PASSWORD_DEFAULT"
    echo "[INFO] Senha do administrador gerada automaticamente."
fi

# ------------------------------------------------------------
# Diretório de instalação
# ------------------------------------------------------------

echo
echo "[INFO] Diretório de instalação:"
echo "       $INSTALL_DIR"
echo

mkdir -p "$INSTALL_DIR"

cd "$INSTALL_DIR"

# ------------------------------------------------------------
# Criar diretórios
# ------------------------------------------------------------

mkdir -p \
    "$INSTALL_DIR/db" \
    "$INSTALL_DIR/redis" \
    "$INSTALL_DIR/nextcloud"

# ------------------------------------------------------------
# Detectar IP do servidor
# ------------------------------------------------------------

SERVER_IP="$(hostname -I 2>/dev/null | awk '{print $1}')"

if [ -z "$SERVER_IP" ]; then
    SERVER_IP="127.0.0.1"
fi

echo "[INFO] IP detectado: $SERVER_IP"

# ------------------------------------------------------------
# Criar Docker Compose
# ------------------------------------------------------------

echo
echo "[6/8] Criando Docker Compose..."
echo

cat > "$INSTALL_DIR/compose.yml" <<EOF
services:

  db:
    image: mariadb:lts
    container_name: nextcloud-db
    restart: unless-stopped
    command: --transaction-isolation=READ-COMMITTED
    environment:
      MYSQL_ROOT_PASSWORD: "$DB_ROOT_PASSWORD"
      MYSQL_DATABASE: nextcloud
      MYSQL_USER: nextcloud
      MYSQL_PASSWORD: "$DB_PASSWORD"
      MARIADB_AUTO_UPGRADE: "1"
      MARIADB_DISABLE_UPGRADE_BACKUP: "1"
    volumes:
      - ./db:/var/lib/mysql
    networks:
      - nextcloud

  redis:
    image: redis:alpine
    container_name: nextcloud-redis
    restart: unless-stopped
    command:
      - redis-server
      - --requirepass
      - "$REDIS_PASSWORD"
    volumes:
      - ./redis:/data
    networks:
      - nextcloud

  app:
    image: nextcloud:apache
    container_name: nextcloud
    restart: unless-stopped
    depends_on:
      - db
      - redis
    environment:
      MYSQL_HOST: db
      MYSQL_DATABASE: nextcloud
      MYSQL_USER: nextcloud
      MYSQL_PASSWORD: "$DB_PASSWORD"
      REDIS_HOST: redis
      REDIS_HOST_PASSWORD: "$REDIS_PASSWORD"
      NEXTCLOUD_ADMIN_USER: "$NEXTCLOUD_ADMIN_USER"
      NEXTCLOUD_ADMIN_PASSWORD: "$NEXTCLOUD_ADMIN_PASSWORD"
      NEXTCLOUD_TRUSTED_DOMAINS: "localhost 127.0.0.1 $SERVER_IP"
      PHP_MEMORY_LIMIT: 1024M
      PHP_UPLOAD_LIMIT: 10G
    volumes:
      - ./nextcloud:/var/www/html
    networks:
      - nextcloud
    ports:
      - "0.0.0.0:8080:80"

  cron:
    image: nextcloud:apache
    container_name: nextcloud-cron
    restart: unless-stopped
    depends_on:
      - db
      - redis
    volumes:
      - ./nextcloud:/var/www/html
    entrypoint:
      - /cron.sh
    networks:
      - nextcloud

networks:
  nextcloud:
    driver: bridge
EOF

chmod 600 "$INSTALL_DIR/compose.yml"

# ------------------------------------------------------------
# Subir containers
# ------------------------------------------------------------

echo
echo "[7/8] Baixando imagens e iniciando Nextcloud..."
echo

cd "$INSTALL_DIR"

docker compose pull

docker compose up -d

# ------------------------------------------------------------
# Esperar Nextcloud inicializar
# ------------------------------------------------------------

echo
echo "[INFO] Aguardando o Nextcloud terminar a instalação..."
echo

MAX_ATTEMPTS=120
ATTEMPT=1
NEXTCLOUD_INSTALLED=false

while [ "$ATTEMPT" -le "$MAX_ATTEMPTS" ]; do

    STATUS="$(docker exec nextcloud php occ status 2>/dev/null || true)"

    if echo "$STATUS" | grep -q "installed: true"; then
        NEXTCLOUD_INSTALLED=true
        echo
        echo "[INFO] Nextcloud instalado com sucesso."
        break
    fi

    echo "[INFO] Aguardando instalação do Nextcloud... ($ATTEMPT/$MAX_ATTEMPTS)"

    # Mostra uma informação útil caso o banco ainda esteja inicializando
    if echo "$STATUS" | grep -q "Nextcloud is not installed"; then
        echo "[INFO] Aguardando a instalação automática..."
    fi

    sleep 5
    ATTEMPT=$((ATTEMPT + 1))
done

if [ "$NEXTCLOUD_INSTALLED" != true ]; then
    echo
    echo "[ERRO] O Nextcloud não terminou a instalação dentro do tempo esperado."
    echo
    echo "Status do Nextcloud:"
    docker exec nextcloud php occ status || true

    echo
    echo "Status dos containers:"
    docker compose ps

    echo
    echo "Logs do Nextcloud:"
    docker compose logs --tail=100 app

    echo
    echo "Logs do MariaDB:"
    docker compose logs --tail=100 db

    exit 1
fi

# ------------------------------------------------------------
# Configurações adicionais
# ------------------------------------------------------------

echo
echo "[INFO] Configurando parâmetros do Nextcloud..."
echo

docker exec nextcloud php occ config:system:set trusted_domains 0 \
    --value="localhost" >/dev/null

docker exec nextcloud php occ config:system:set trusted_domains 1 \
    --value="127.0.0.1" >/dev/null

docker exec nextcloud php occ config:system:set trusted_domains 2 \
    --value="$SERVER_IP" >/dev/null

# Redis
docker exec nextcloud php occ config:system:set redis host \
    --value="redis" >/dev/null

docker exec nextcloud php occ config:system:set redis port \
    --value="6379" >/dev/null

docker exec nextcloud php occ config:system:set redis password \
    --value="$REDIS_PASSWORD" >/dev/null

# Memcache
docker exec nextcloud php occ config:system:set memcache.local \
    --value='\OC\Memcache\APCu' >/dev/null

docker exec nextcloud php occ config:system:set memcache.locking \
    --value='\OC\Memcache\Redis' >/dev/null

# ------------------------------------------------------------
# Verificação
# ------------------------------------------------------------

echo
echo "[8/8] Verificando instalação..."
echo

echo "------------------------------------------"
echo " Containers"
echo "------------------------------------------"

docker compose ps

echo
echo "------------------------------------------"
echo " Nextcloud"
echo "------------------------------------------"

docker exec nextcloud php occ status

echo
echo "------------------------------------------"
echo " Acesso"
echo "------------------------------------------"

echo "http://$SERVER_IP:8080"

echo
echo "------------------------------------------"
echo " Credenciais"
echo "------------------------------------------"

echo "Usuário Nextcloud : $NEXTCLOUD_ADMIN_USER"
echo "Senha Nextcloud   : $NEXTCLOUD_ADMIN_PASSWORD"

echo
echo "MariaDB ROOT:"
echo "  Usuário: root"
echo "  Senha  : $DB_ROOT_PASSWORD"

echo
echo "MariaDB Nextcloud:"
echo "  Banco  : nextcloud"
echo "  Usuário: nextcloud"
echo "  Senha  : $DB_PASSWORD"

echo
echo "Redis:"
echo "  Senha: $REDIS_PASSWORD"

echo
echo "------------------------------------------"
echo " Arquivos"
echo "------------------------------------------"

echo "Compose:"
echo "  $INSTALL_DIR/compose.yml"

echo
echo "Dados:"
echo "  $INSTALL_DIR/nextcloud"

echo
echo "Banco:"
echo "  $INSTALL_DIR/db"

echo
echo "Redis:"
echo "  $INSTALL_DIR/redis"

echo
echo "=========================================="
echo " Nextcloud instalado com sucesso!"
echo "=========================================="
echo
