#!/usr/bin/env bash
#
# Deja un VPS de Ubuntu listo para servir el portal de reportes de INCIDE.
#
#   sudo bash install.sh
#
# Es idempotente: se puede volver a correr sin romper nada. Al final imprime
# el resumen con lo que falta hacer a mano (DNS, certificado, .env).

set -euo pipefail

# --- Datos que se pueden cambiar por variables de entorno -------------------
DOMINIO="${DOMINIO:-reportes.incide.com.co}"
USUARIO="${USUARIO:-incide}"
PHP_VER="${PHP_VER:-8.3}"
RAIZ="${RAIZ:-/var/www/incide}"
CORREO_CERT="${CORREO_CERT:-}"

log()  { printf '\n\033[1;36m==> %s\033[0m\n' "$1"; }
ok()   { printf '    \033[32mOK\033[0m  %s\n' "$1"; }
aviso(){ printf '    \033[33m!!\033[0m  %s\n' "$1"; }

[[ $EUID -eq 0 ]] || { echo "Este script se corre como root: sudo bash install.sh"; exit 1; }

# ---------------------------------------------------------------------------
log "1/9  Actualizando el sistema"
export DEBIAN_FRONTEND=noninteractive
apt-get update -qq
apt-get -y -qq upgrade
apt-get -y -qq autoremove
ok "Sistema actualizado"

# ---------------------------------------------------------------------------
log "2/9  Zona horaria y locales"
timedatectl set-timezone America/Bogota
apt-get install -y -qq locales
sed -i 's/^# *\(es_CO.UTF-8\)/\1/' /etc/locale.gen
locale-gen es_CO.UTF-8 >/dev/null
update-locale LANG=es_CO.UTF-8
ok "America/Bogota · es_CO.UTF-8"

# ---------------------------------------------------------------------------
log "3/9  Paquetes base"
apt-get install -y -qq \
    nginx curl git unzip rsync \
    fail2ban ufw chrony \
    software-properties-common ca-certificates apt-transport-https
ok "nginx, git, rsync, fail2ban, ufw"

# ---------------------------------------------------------------------------
log "4/9  PHP $PHP_VER con las extensiones que necesita el proyecto"
# sqlite3 es obligatorio: el portal guarda los enlaces de un solo uso en una
# base SQLite propia, no en MySQL.
add-apt-repository -y ppa:ondrej/php >/dev/null 2>&1 || true
apt-get update -qq

apt-get install -y -qq \
    "php$PHP_VER-fpm" "php$PHP_VER-cli" \
    "php$PHP_VER-mysql" "php$PHP_VER-sqlite3" \
    "php$PHP_VER-curl" "php$PHP_VER-mbstring" \
    "php$PHP_VER-xml" "php$PHP_VER-gd" \
    "php$PHP_VER-zip" "php$PHP_VER-bcmath" "php$PHP_VER-intl"

ok "PHP $PHP_VER instalado"

# El limite de tiempo importa: un reporte en frio tarda 70 s porque baja las
# imagenes de Sihos. Con el 30 s de abajo se corta a mitad y el paciente ve un
# error en vez del PDF.
cat > "/etc/php/$PHP_VER/fpm/conf.d/99-incide.ini" <<INI
; Ajustes para el portal de reportes de INCIDE.
memory_limit = 512M

; Un reporte recien generado se lleva unos 70 s: tiene que descargar las
; imagenes del servidor de Sihos. Con menos, la peticion se muere a mitad.
max_execution_time = 300
max_input_time = 300

post_max_size = 16M
upload_max_filesize = 16M
max_file_uploads = 20

; Laravel resuelve muchas rutas en cada peticion.
realpath_cache_size = 4096K
realpath_cache_ttl = 600

; Con debug off, los errores no deben imprimirse en pantalla.
display_errors = Off
log_errors = On
error_log = /var/log/php/incide-error.log

opcache.enable = 1
opcache.enable_cli = 0
opcache.memory_consumption = 192
opcache.interned_strings_buffer = 16
opcache.max_accelerated_files = 20000
opcache.validate_timestamps = 1
opcache.revalidate_freq = 0
INI

# La CLI necesita limite de tiempo aparte: genera PDFs desde artisan.
cat > "/etc/php/$PHP_VER/cli/conf.d/99-incide.ini" <<'INI'
memory_limit = 512M
max_execution_time = 300
opcache.enable_cli = 0
INI

# Registro propio: asi los errores se revisan sin pelearse con el del sistema.
mkdir -p /var/log/php
chown www-data:www-data /var/log/php
touch /var/log/php/incide-error.log
chown www-data:www-data /var/log/php/incide-error.log

systemctl restart "php$PHP_VER-fpm"
ok "PHP configurado (300 s, 512 MB, opcache)"

# ---------------------------------------------------------------------------
log "5/9  Composer"
if ! command -v composer >/dev/null 2>&1; then
    curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
fi
ok "$(composer --version --no-ansi 2>/dev/null | head -1)"

# ---------------------------------------------------------------------------
log "6/9  Espacio de intercambio"
# Con 1 GB de RAM, dompdf armando un PDF con 9 fotos puede quedarse sin
# memoria a mitad y el worker muere sin dejar rastro.
if ! swapon --show | grep -q .; then
    fallocate -l 2G /swapfile
    chmod 600 /swapfile
    mkswap /swapfile >/dev/null
    swapon /swapfile
    echo '/swapfile none swap sw 0 0' >> /etc/fstab
    ok "swap de 2 GB activado"
else
    ok "ya habia swap"
fi

# ---------------------------------------------------------------------------
log "7/9  Usuario de despliegue"
if ! id -u "$USUARIO" >/dev/null 2>&1; then
    adduser --disabled-password --gecos "Deploy INCIDE" "$USUARIO"
    usermod -aG sudo "$USUARIO"
fi
ok "$USUARIO creado (con sudo para reiniciar servicios)"

mkdir -p "$RAIZ"
chown -R "$USUARIO:$USUARIO" "$RAIZ"

# Laravel ni siquiera arranca si estas carpetas no existen: se quejaria de que
# storage/framework/views no esta. El paquete de subida las deja vacias a
# proposito (los PDF y las imagenes en cache son del servidor), asi que se
# crean aqui.
mkdir -p "$RAIZ"/storage/app/Admision \
         "$RAIZ"/storage/app/sihos-cache \
         "$RAIZ"/storage/app/public \
         "$RAIZ"/storage/framework/cache/data \
         "$RAIZ"/storage/framework/sessions \
         "$RAIZ"/storage/framework/views \
         "$RAIZ"/storage/logs \
         "$RAIZ"/bootstrap/cache \
         "$RAIZ"/database/sqlite
ok "$RAIZ"

# El paquete de subida no lleva la carpeta vendor: pesa 29 MB y por scp tarda
# una eternidad. Se instala aqui, donde hay red rapida y Composer.
if [[ -f "$RAIZ/composer.json" ]]; then
    log "4b/9  Dependencias de Composer"
    cd "$RAIZ"
    COMPOSER_ALLOW_SUPERUSER=1 composer install \
        --no-dev --no-interaction --prefer-dist --optimize-autoloader --no-progress
    ok "vendor instalado"
    cd /
else
    aviso "No hay composer.json en $RAIZ: se saltan las dependencias"
fi

# ---------------------------------------------------------------------------
log "8/9  Cortafuegos"
ufw --force reset >/dev/null
ufw default deny incoming   >/dev/null
ufw default allow outgoing  >/dev/null
ufw allow OpenSSH  >/dev/null
ufw allow 80/tcp    >/dev/null
ufw allow 443/tcp   >/dev/null
ufw --force enable  >/dev/null
ok "Entradas permitidas: 22, 80, 443 (salidas libres: necesita Sihos)"

fail2ban-client start fail2ban >/dev/null 2>&1 || true
ok "fail2ban activo"

# ---------------------------------------------------------------------------
log "9/9  nginx"

# Se instala la version solo HTTP: la de HTTPS apunta a un certificado que
# todavia no existe, y nginx no arranca si el archivo falta. Una vez emitido
# el certificado, activar-https.sh deja la version completa.
# El dominio y la version de PHP se ajustan solos para no editar a mano.
ORIGEN="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/nginx-http.conf"

if [[ -f "$ORIGEN" ]]; then
    sed -e "s/reportes\.incide\.com\.co/$DOMINIO/g" \
        -e "s/php$PHP_VER-fpm\.sock/php$PHP_VER-fpm.sock/" \
        "$ORIGEN" > /etc/nginx/sites-available/incide.conf
    ok "configuracion copiada a /etc/nginx/sites-available/incide.conf"
else
    aviso "No se encontro nginx-incide.conf junto a este script"
fi

ln -sf /etc/nginx/sites-available/incide.conf /etc/nginx/sites-enabled/incide.conf
rm -f /etc/nginx/sites-enabled/default

if nginx -t 2>/dev/null; then
    systemctl reload nginx
    ok "nginx configurado para $DOMINIO"
else
    aviso "La configuracion de nginx tiene errores. Revisa: nginx -t"
fi

# En este punto nginx solo escucha en el puerto 80: es lo unico que funciona
# sin certificado. HTTPS se activa con activar-https.sh.

# nginx debe poder leer los archivos del proyecto. www-data es el usuario de
# PHP-FPM.
usermod -aG "$USUARIO" www-data
chown -R "$USUARIO:www-data" "$RAIZ"
find "$RAIZ" -type d -exec chmod 755 {} \;
find "$RAIZ" -type f -exec chmod 644 {} \;
ok "lectura de nginx sobre $RAIZ"

systemctl enable --now nginx "php$PHP_VER-fpm" >/dev/null
ok "nginx y PHP arrancan solos tras un reinicio"

# ---------------------------------------------------------------------------
printf '\n\033[1;32m========================================\033[0m\n'
printf '\033[1;32m  Servidor listo\033[0m\n'
printf '\033[1;32m========================================\033[0m\n\n'

echo "  Dominio configurado: $DOMINIO"
echo
echo "  FALTA HACER A MANO:"
echo
echo "  1. En el panel DNS de incide.com.co, crear un registro A:"
echo "       $DOMINIO  ->  IP de este VPS"
echo "     (el dominio principal sigue en Banahosting, donde esta el sitio web)"
echo
echo "  2. Copiar el proyecto:"
echo "       bash $RAIZ/../desplegar.sh"
echo "     o manualmente:"
echo "       scp -r proyecto/* $USUARIO@<IP-VPS>:$RAIZ/"
echo
echo "  3. Crear el .env en el servidor y poner APP_KEY y SIHOS_*"
echo
echo "  4. Permisos y certificado:"
echo "       cd $RAIZ"
if [[ -n "$CORREO_CERT" ]]; then
  echo "       sudo certbot --nginx -d $DOMINIO --agree-tos -m $CORREO_CERT --redirect"
else
  echo "       sudo certbot --nginx -d $DOMINIO   # te pide un correo"
fi
echo
echo "  5. Comprobar:"
echo "       sudo -u $USUARIO php artisan instalacion:verificar"
echo
echo "  6. Cerrar la sesion de root por SSH despues de crear tu llave:"
echo "       edit /etc/ssh/sshd_config  ->  PermitRootLogin no"
echo "       systemctl restart ssh"
echo
echo "  Para entrar:"
echo "     ssh $USUARIO@<IP-VPS>"
echo