#!/bin/bash

#==============================================================================
# Script: InstallSSL_LAMP.sh
# Descripcion: Instala certificado SSL Wildcard de Let's Encrypt para
#              instalaciones LAMP (Apache + PHP) en Ubuntu
# Autor: Copilot
# Fecha: 2025-11-28
# Version: 1.0
#
# Requisitos:
# - Ubuntu 20.04 o superior
# - Apache2 instalado y funcionando
# - Dominio apuntando al servidor (DNS configurado)
#
# Uso:
#   sudo bash InstallSSL_LAMP.sh dominio.com
#   Ejemplo: sudo bash InstallSSL_LAMP.sh sufacturae.com
#==============================================================================

# Colores para output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
BOLD='\033[1m'

#-------------------------------------FUNCIONES----------------------------------------------------------------
print_step() {
    echo ""
    echo -e "${BLUE}${BOLD}===================================================================================================${NC}"
    echo -e "${BLUE}${BOLD}  $1${NC}"
    echo -e "${BLUE}${BOLD}===================================================================================================${NC}"
    echo ""
}

print_success() {
    echo -e "${GREEN}[OK]${NC} $1"
}

print_error() {
    echo -e "${RED}[X]${NC} $1"
}

print_warning() {
    echo -e "${YELLOW}[!]${NC} $1"
}

print_info() {
    echo -e "${CYAN}[i]${NC} $1"
}

#-------------------------------------VERIFICACIONES INICIALES-------------------------------------------------
print_step "Verificaciones iniciales"

# Verificar que se ejecuta como root
if [ "$EUID" -ne 0 ]; then
    print_error "Este script debe ejecutarse como root (sudo)"
    echo -e "${YELLOW}Uso: sudo bash $0 tu-dominio.com${NC}"
    exit 1
fi

print_success "Ejecutando como root"

# Información del sistema
UBUNTU_VERSION=$(lsb_release -rs)
print_info "Sistema: Ubuntu $UBUNTU_VERSION"

# Verificar versión de Ubuntu soportada
UBUNTU_MAJOR=$(echo "$UBUNTU_VERSION" | cut -d. -f1)

if [[ "$UBUNTU_MAJOR" -lt 20 ]]; then
    print_error "APIDIAN 2026 no es compatible con Ubuntu versiones menores a 20.04"
    print_warning "Tu versión: Ubuntu $UBUNTU_VERSION"
    print_info "Se requiere mínimo Ubuntu 20.04 LTS"
    exit 1
elif [[ ! "$UBUNTU_VERSION" =~ ^(20.04|22.04|24.04) ]]; then
    print_warning "Ubuntu $UBUNTU_VERSION no ha sido testeada oficialmente"
    print_info "Se procederá con instalación de SSL (compatibilidad parcial)"
fi

print_success "Versión de Ubuntu compatible"

# Verificar parametro del dominio
HOST=${1:-''}
if [ -z "$HOST" ]; then
    print_error "Debes especificar el dominio"
    echo -e "${YELLOW}Uso: sudo bash $0 tu-dominio.com${NC}"
    echo -e "${CYAN}Ejemplo: sudo bash $0 sufacturae.com${NC}"
    exit 1
fi

print_success "Dominio: ${BOLD}$HOST${NC}"

# Verificar que Apache esta instalado
if ! command -v apache2 &> /dev/null; then
    print_error "Apache2 no esta instalado"
    exit 1
fi

print_success "Apache2 detectado"

# Verificar que Apache esta corriendo
if ! systemctl is-active --quiet apache2; then
    print_warning "Apache2 no esta corriendo, intentando iniciar..."
    systemctl start apache2
    if ! systemctl is-active --quiet apache2; then
        print_error "No se pudo iniciar Apache2"
        exit 1
    fi
fi

print_success "Apache2 esta corriendo"

#-------------------------------------DETECTAR CONFIGURACION---------------------------------------------------
print_step "Detectando configuracion"

# Detectar rutas de instalacion
PATH_CURRENT=$(pwd)
DIR_API="apidian"

# Detectar si existe instalacion de API
if [ -d "$PATH_CURRENT/$DIR_API" ]; then
    print_success "Instalacion API detectada en: $PATH_CURRENT/$DIR_API"
    DOCUMENT_ROOT="$PATH_CURRENT/$DIR_API/public"
else
    # Buscar en ubicaciones comunes
    if [ -d "/var/www/$DIR_API" ]; then
        PATH_CURRENT="/var/www"
        DOCUMENT_ROOT="/var/www/$DIR_API/public"
        print_success "Instalacion API encontrada en: /var/www/$DIR_API"
    else
        print_warning "No se detecto instalacion automaticamente"
        read -p "$(echo -e ${CYAN}Ingresa el DocumentRoot de tu aplicacion: ${NC})" DOCUMENT_ROOT
        if [ ! -d "$DOCUMENT_ROOT" ]; then
            print_error "El directorio $DOCUMENT_ROOT no existe"
            exit 1
        fi
    fi
fi

print_info "DocumentRoot: $DOCUMENT_ROOT"

#-------------------------------------INSTALAR CERTBOT---------------------------------------------------------
print_step "Instalando Certbot"

apt-get update > /dev/null 2>&1

if ! command -v certbot &> /dev/null; then
    print_info "Instalando certbot..."
    DEBIAN_FRONTEND=noninteractive apt-get install -y certbot python3-certbot-apache > /dev/null 2>&1
    print_success "Certbot instalado"
else
    print_success "Certbot ya esta instalado"
fi

#-------------------------------------OBTENER CERTIFICADO------------------------------------------------------
print_step "Instalando certificado SSL Wildcard"

print_warning "IMPORTANTE: Asegurate de que el DNS apunte correctamente al servidor"
echo ""
echo -e "${YELLOW}${BOLD}[!] NOTA IMPORTANTE SOBRE RENOVACION:${NC}"
echo -e "${YELLOW}==========================================================${NC}"
echo -e "${YELLOW}El metodo DNS manual NO permite renovacion automatica.${NC}"
echo -e "${YELLOW}Deberas repetir este proceso cada 90 dias (recibiras email).${NC}"
echo -e "${YELLOW}Los registros TXT son de un solo uso, no los guardes.${NC}"
echo -e "${YELLOW}==========================================================${NC}"
echo ""
echo -e "${YELLOW}+-------------------------------------------------------+${NC}"
echo -e "${YELLOW}| ${BOLD}INSTRUCCIONES:${NC}${YELLOW}                                        |${NC}"
echo -e "${YELLOW}+-------------------------------------------------------+${NC}"
echo -e "${YELLOW}| 1. Copiar los 2 registros TXT que aparezcan           |${NC}"
echo -e "${RED}${BOLD}| 2. NO usar [Ctrl+C] ya que cancelara el proceso       |${NC}"
echo -e "${YELLOW}| 3. Ingresar tu correo electronico                     |${NC}"
echo -e "${YELLOW}| 4. Aceptar los terminos y condiciones                 |${NC}"
echo -e "${YELLOW}| 5. Los registros TXT son temporales (no permanentes)  |${NC}"
echo -e "${YELLOW}+-------------------------------------------------------+${NC}"
echo ""

certbot certonly --manual -d *.$HOST -d $HOST --agree-tos --no-bootstrap --manual-public-ip-logging-ok --preferred-challenges dns-01 --server https://acme-v02.api.letsencrypt.org/directory

print_info "Verificando certificados generados..."

if ! [ -f /etc/letsencrypt/live/$HOST/privkey.pem ]; then
    print_error "No se ha generado el certificado SSL"
    print_warning "Verifica que los registros DNS TXT se hayan propagado correctamente"
    exit 1
fi

print_success "Certificado SSL generado exitosamente"

#-------------------------------------CONFIGURAR APACHE PARA SSL-----------------------------------------------
print_step "Configurando Apache para SSL"

print_info "Verificando certificado generado..."

if [ -f "/etc/letsencrypt/live/$HOST/fullchain.pem" ]; then
    print_success "Certificado encontrado en /etc/letsencrypt/live/$HOST/"

    print_info "Informacion del certificado:"
    openssl x509 -in /etc/letsencrypt/live/$HOST/fullchain.pem -noout -dates 2>/dev/null | while read line; do
        echo "  $line"
    done
else
    print_error "No se encontro el certificado"
    exit 1
fi

print_warning "NOTA: El metodo DNS manual requiere renovacion manual cada 90 dias"
print_info "Recibiras un email de aviso antes de que expire el certificado"

#-------------------------------------VERIFICAR CONFIGURACION APACHE-------------------------------------------
print_step "Verificando configuracion de Apache"

# Verificar que el modulo SSL esta habilitado
if a2query -m ssl > /dev/null 2>&1; then
    print_success "Modulo SSL habilitado"
else
    print_warning "Habilitando modulo SSL..."
    a2enmod ssl
    systemctl restart apache2
    print_success "Modulo SSL habilitado"
fi

# Verificar sintaxis de Apache
if apache2ctl configtest > /dev/null 2>&1; then
    print_success "Configuracion de Apache valida"
else
    print_warning "Hay advertencias en la configuracion de Apache"
    apache2ctl configtest
fi

# Reiniciar Apache para aplicar cambios
print_info "Reiniciando Apache..."
systemctl restart apache2

if systemctl is-active --quiet apache2; then
    print_success "Apache reiniciado correctamente"
else
    print_error "Error al reiniciar Apache"
    systemctl status apache2 --no-pager
    exit 1
fi

#-------------------------------------CONFIGURAR VIRTUALHOST SSL----------------------------------------------
print_step "Configurando VirtualHost SSL"

# Detectar subdomain si existe
if [ -f "$PATH_CURRENT/$DIR_API/.env" ] && grep -q "^APP_URL=" "$PATH_CURRENT/$DIR_API/.env"; then
    APP_URL=$(grep "^APP_URL=" "$PATH_CURRENT/$DIR_API/.env" | cut -d '=' -f2 | tr -d '"' | tr -d "'")
    SUBDOMAIN=$(echo "$APP_URL" | sed 's|https\?://||' | cut -d '.' -f1)
    if [ -z "$SUBDOMAIN" ] || [ "$SUBDOMAIN" = "$HOST" ]; then
        SUBDOMAIN="api"
    fi
else
    SUBDOMAIN="api"
fi

SERVER_NAME="$SUBDOMAIN.$HOST"
VHOST_SSL_CONF="/etc/apache2/sites-available/${DIR_API}-ssl.conf"

print_info "Creando VirtualHost SSL para: $SERVER_NAME"

cat > $VHOST_SSL_CONF << VHOSTSSLEOF
<VirtualHost *:443>
    ServerName $SERVER_NAME
    DocumentRoot $DOCUMENT_ROOT

    SSLEngine on
    SSLCertificateFile /etc/letsencrypt/live/$HOST/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/$HOST/privkey.pem

    <Directory $DOCUMENT_ROOT>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>

    ErrorLog \${APACHE_LOG_DIR}/${DIR_API}_ssl_error.log
    CustomLog \${APACHE_LOG_DIR}/${DIR_API}_ssl_access.log combined

    <FilesMatch \.php$>
        SetHandler application/x-httpd-php
    </FilesMatch>

    <IfModule mod_headers.c>
        Header always set X-Content-Type-Options "nosniff"
        Header always set X-Frame-Options "SAMEORIGIN"
        Header always set X-XSS-Protection "1; mode=block"
        Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
    </IfModule>
</VirtualHost>

# Redireccion HTTP a HTTPS
<VirtualHost *:80>
    ServerName $SERVER_NAME
    Redirect permanent / https://$SERVER_NAME/
</VirtualHost>
VHOSTSSLEOF

print_success "VirtualHost SSL creado: $VHOST_SSL_CONF"

# Habilitar sitio SSL
a2ensite ${DIR_API}-ssl > /dev/null 2>&1
print_success "Sitio SSL habilitado"

# Recargar Apache
systemctl reload apache2
print_success "Apache recargado"

#-------------------------------------ACTUALIZAR CONFIGURACION APP---------------------------------------------
if [ -f "$PATH_CURRENT/$DIR_API/.env" ]; then
    print_step "Actualizando configuracion de aplicacion"

    cd "$PATH_CURRENT/$DIR_API"

    # Actualizar APP_URL a HTTPS
    sed -i "/APP_URL=/c\APP_URL=https://$SERVER_NAME" .env
    print_success "APP_URL actualizado a HTTPS"

    # Forzar HTTPS si la variable existe
    if grep -q "FORCE_HTTPS=" .env; then
        sed -i '/FORCE_HTTPS=/c\FORCE_HTTPS=true' .env
        print_success "FORCE_HTTPS habilitado"
    fi

    # Limpiar cache de Laravel
    if [ -f "artisan" ]; then
        php artisan config:cache > /dev/null 2>&1
        php artisan cache:clear > /dev/null 2>&1
        print_success "Cache de Laravel limpiado"
    fi
fi

#-------------------------------------RESUMEN FINAL------------------------------------------------------------
print_step "Instalacion completada!"

echo ""
echo -e "${GREEN}${BOLD}+================================================================+${NC}"
echo -e "${GREEN}${BOLD}|         CERTIFICADO SSL WILDCARD INSTALADO                     |${NC}"
echo -e "${GREEN}${BOLD}+================================================================+${NC}"
echo ""
echo -e "${CYAN}${BOLD}Informacion del certificado:${NC}"
echo -e "  ${BOLD}Dominio:${NC}         $HOST"
echo -e "  ${BOLD}Wildcard:${NC}        *.$HOST"
echo -e "  ${BOLD}Servidor:${NC}        https://$SERVER_NAME"
echo -e "  ${BOLD}Certificados:${NC}    /etc/letsencrypt/live/$HOST/"
echo ""
echo -e "${CYAN}${BOLD}Configuracion:${NC}"
echo -e "  ${BOLD}VirtualHost:${NC}     $VHOST_SSL_CONF"
echo -e "  ${BOLD}DocumentRoot:${NC}    $DOCUMENT_ROOT"
echo -e "  ${BOLD}Logs:${NC}            /var/log/apache2/${DIR_API}_ssl_*.log"
echo ""
echo -e "${YELLOW}${BOLD}[!] IMPORTANTE - RENOVACION:${NC}"
echo -e "${YELLOW}  El metodo DNS-01 manual requiere renovacion MANUAL cada 90 dias${NC}"
echo -e "${YELLOW}  Recibiras un email antes de que expire el certificado${NC}"
echo -e "${YELLOW}  Para renovar, ejecuta nuevamente este script:${NC}"
echo -e "${CYAN}  sudo bash $0 $HOST${NC}"
echo ""
echo -e "${CYAN}${BOLD}Comandos utiles:${NC}"
echo -e "  ${BOLD}Ver certificados:${NC}    certbot certificates"
echo -e "  ${BOLD}Ver expiracion:${NC}      certbot certificates | grep -A2 $HOST"
echo -e "  ${BOLD}Revocar:${NC}             certbot revoke --cert-path /etc/letsencrypt/live/$HOST/fullchain.pem"
echo ""
echo -e "${GREEN}${BOLD}Tu sitio ahora tiene SSL/TLS activado! [SSL]${NC}"
echo -e "${GREEN}Accede a: https://$SERVER_NAME${NC}"
echo ""
