#!/bin/bash
# =============================================================
# cdrom_helper.sh - Helper de CD-ROM con permisos elevados
# Sistema Robot de Grabación Médica
# Ejecutado por PHP via sudo (sin contraseña) para operaciones
# que requieren acceso a /dev/sr* en Linux.
# =============================================================

ACCION="$1"
UNIDAD="$2"

# Validar que la unidad sea un dispositivo óptico real (seguridad)
validar_unidad() {
    local dev="$1"
    # Solo permitir /dev/sr*, /dev/scd*, /dev/cdrom, /dev/dvd
    if [[ ! "$dev" =~ ^/dev/(sr[0-9]+|scd[0-9]+|cdrom[0-9]*|dvd[0-9rw]*|dvdrw[0-9]*)$ ]]; then
        echo "ERROR: Dispositivo no permitido: $dev"
        exit 1
    fi
    if [ ! -e "$dev" ]; then
        echo "ERROR: Dispositivo no existe: $dev"
        exit 1
    fi
}

case "$ACCION" in

    # ── EXPULSAR DISCO ─────────────────────────────────────────────────────────
    # Orden de métodos: eject nativo → udisksctl → ioctl via Python → sg_start
    eject)
        validar_unidad "$UNIDAD"

        # MÉTODO 1: eject nativo (el más común en Ubuntu/Debian/Fedora)
        if command -v eject &>/dev/null; then
            eject "$UNIDAD" 2>&1
            if [ $? -eq 0 ]; then
                echo "EJECT_OK: eject nativo"
                exit 0
            fi
        fi

        # MÉTODO 2: udisksctl (moderno, no requiere sudo si el usuario tiene permisos)
        if command -v udisksctl &>/dev/null; then
            # eject via udisksctl
            udisksctl power-off -b "$UNIDAD" 2>/dev/null || true
            eject "$UNIDAD" 2>&1
            if [ $? -eq 0 ]; then
                echo "EJECT_OK: udisksctl + eject"
                exit 0
            fi
        fi

        # MÉTODO 3: ioctl directo via Python (funciona siempre que tengamos Python)
        if command -v python3 &>/dev/null; then
            python3 -c "
import fcntl, os, sys
CDROM_EJECT = 0x5309
try:
    fd = os.open('$UNIDAD', os.O_RDONLY | os.O_NONBLOCK)
    fcntl.ioctl(fd, CDROM_EJECT)
    os.close(fd)
    print('EJECT_OK: ioctl Python3')
    sys.exit(0)
except Exception as e:
    print('ioctl error:', e)
    sys.exit(1)
" 2>&1
            if [ $? -eq 0 ]; then
                exit 0
            fi
        fi

        # MÉTODO 4: sg_start (parte del paquete sg3-utils)
        if command -v sg_start &>/dev/null; then
            sg_start --eject "$UNIDAD" 2>&1
            if [ $? -eq 0 ]; then
                echo "EJECT_OK: sg_start"
                exit 0
            fi
        fi

        # MÉTODO 5: Último recurso - usar hdparm
        if command -v hdparm &>/dev/null; then
            hdparm -e "$UNIDAD" 2>&1
            if [ $? -eq 0 ]; then
                echo "EJECT_OK: hdparm"
                exit 0
            fi
        fi

        echo "EJECT_FAIL: Todos los métodos fallaron para $UNIDAD"
        exit 1
        ;;

    # ── ESTADO DEL DISCO ───────────────────────────────────────────────────────
    status)
        validar_unidad "$UNIDAD"

        # Verificar si hay medio insertado leyendo 1 bloque
        DD_OUT=$(dd if="$UNIDAD" of=/dev/null bs=2048 count=1 2>&1)
        if echo "$DD_OUT" | grep -qi "No medium\|no medium\|No such\|Input/output error"; then
            echo "STATUS=EMPTY"
            exit 0
        fi

        # Hay disco: verificar si tiene FS (datos) o está vacío (blanco)
        FS=$(blkid -o value -s TYPE "$UNIDAD" 2>/dev/null)
        LABEL=$(blkid -o value -s LABEL "$UNIDAD" 2>/dev/null)

        if [ -n "$FS" ]; then
            echo "STATUS=DATA"
            echo "FS=$FS"
            if [ -n "$LABEL" ]; then
                echo "VOLNAME=$LABEL"
            fi
        else
            echo "STATUS=BLANK"
            echo "FS="
        fi

        # Detectar capacidad del disco
        if command -v wodim &>/dev/null; then
            CAP_RAW=$(wodim dev="$UNIDAD" -atip 2>/dev/null | grep -i "Disk capacity" | grep -oP '[0-9]+')
            if [ -n "$CAP_RAW" ]; then
                # Convertir sectores (2048 bytes) a MB
                CAP_MB=$(echo "scale=0; $CAP_RAW * 2048 / 1048576" | bc 2>/dev/null)
                if [ -n "$CAP_MB" ]; then
                    echo "CAP=${CAP_MB}MB"
                fi
            fi
        fi

        # Detectar si es Regrabable (RW)
        RW="False"

        # Método 1: wodim -prcap (más preciso)
        if command -v wodim &>/dev/null; then
            CAPS=$(wodim dev="$UNIDAD" -prcap 2>/dev/null)
            if echo "$CAPS" | grep -qi "Does write CD-RW\|Does write DVD-RW\|Does write DVD+RW\|Does write DVD-RAM\|BD-RE"; then
                RW="True"
            fi
        fi

        # Método 2: /proc/sys/dev/cdrom/info como fallback
        if [ "$RW" = "False" ] && [ -f /proc/sys/dev/cdrom/info ]; then
            if grep -q "Can write CD-RW:[[:space:]]*1\|Can write DVD-R:[[:space:]]*1" /proc/sys/dev/cdrom/info; then
                RW="True"
            fi
        fi

        # Método 3: udev/sysfs
        if [ "$RW" = "False" ]; then
            DEV_NAME=$(basename "$UNIDAD")
            CAPS_SYSFS="/sys/block/$DEV_NAME/capability"
            if [ -f "$CAPS_SYSFS" ]; then
                CAP_VAL=$(cat "$CAPS_SYSFS" 2>/dev/null)
                # Bit 3 (8) = CD-RW, Bit 9 (512) = DVD-RW
                if (( (CAP_VAL & 8) != 0 || (CAP_VAL & 512) != 0 )); then
                    RW="True"
                fi
            fi
        fi

        echo "RW=$RW"
        exit 0
        ;;

    # ── GRABAR DISCO (growisofs) ───────────────────────────────────────────────
    burn_growisofs)
        # $3 = ruta fuente, $4 = nombre volumen
        FUENTE="$3"
        VOLNAME="${4:-EstudioMedico}"
        validar_unidad "$UNIDAD"
        if [ ! -d "$FUENTE" ]; then
            echo "ERROR: Carpeta fuente no existe: $FUENTE"
            exit 1
        fi
        growisofs -Z "$UNIDAD" -R -J -V "$VOLNAME" "$FUENTE" 2>&1
        exit $?
        ;;

    # ── GRABAR DISCO (wodim + genisoimage) ────────────────────────────────────
    burn_wodim)
        FUENTE="$3"
        VOLNAME="${4:-EstudioMedico}"
        validar_unidad "$UNIDAD"
        if [ ! -d "$FUENTE" ]; then
            echo "ERROR: Carpeta fuente no existe: $FUENTE"
            exit 1
        fi
        ISO_TMP="/tmp/robot_burn_$(date +%s).iso"
        # Crear imagen ISO con soporte Rock Ridge + Joliet
        genisoimage -R -J -V "$VOLNAME" -o "$ISO_TMP" "$FUENTE" 2>&1
        if [ $? -ne 0 ]; then
            rm -f "$ISO_TMP"
            echo "ERROR: Fallo al crear imagen ISO con genisoimage"
            exit 1
        fi
        # Grabar con velocidad configurable (arg $5 o default 8)
        SPEED="${5:-8}"
        wodim -v dev="$UNIDAD" speed="$SPEED" "$ISO_TMP" 2>&1
        CODE=$?
        rm -f "$ISO_TMP"
        exit $CODE
        ;;

    # ── VERIFICAR PERMISOS ─────────────────────────────────────────────────────
    test)
        echo "OK: cdrom_helper ejecutado como $(whoami)"
        echo "Dispositivos opticos disponibles:"
        ls /dev/sr* /dev/scd* /dev/cdrom /dev/dvd 2>/dev/null || echo "  (ninguno detectado)"
        echo "Herramientas disponibles:"
        for tool in eject udisksctl wodim growisofs genisoimage blkid sg_start hdparm python3; do
            if command -v "$tool" &>/dev/null; then
                echo "  [OK] $tool: $(command -v $tool)"
            else
                echo "  [--] $tool: no instalado"
            fi
        done
        exit 0
        ;;

    *)
        echo "ERROR: Acción desconocida: $ACCION"
        echo "Uso: $0 {eject|status|burn_growisofs|burn_wodim|test} /dev/sr0 [fuente] [volname]"
        exit 1
        ;;
esac
