#!/usr/bin/env bash
# =============================================================================
#  instalar-drivers-tbs.sh
#  Instalador PROFESIONAL de drivers para tarjetas TBS (DVB) en Linux.
#
#  MODOS:
#    sudo bash instalar-drivers-tbs.sh              AUTO (recomendado)
#        1) Detecta CUALQUIER tarjeta TBS (PCI /sys + lspci + USB).
#        2) Verifica si el kernel YA la soporta.
#        3) Prueba modulos DVB del kernel.
#        4) Si falta, instala el DRIVER OFICIAL TBS (metodo media_build,
#           el mismo que usa TBS para todas sus tarjetas: 6205, 6281,
#           6902/03/04/05/08/09/10/12/16, 6522, USB 5520/5925/5927...).
#        5) Verifica todo (adaptadores, frontends, tuners) SIN Astra.
#
#    sudo bash instalar-drivers-tbs.sh --oficial     Fuerza el driver OFICIAL
#    sudo bash instalar-drivers-tbs.sh --verificar   Solo comprueba (no instala)
# =============================================================================

set -uo pipefail

SOLO_VERIFICAR=0
FORZAR_OFICIAL=0
case "${1:-}" in
    --verificar|-v)  SOLO_VERIFICAR=1 ;;
    --oficial|-o)    FORZAR_OFICIAL=1 ;;
    --help|-h)
        sed -n '2,20p' "$0" | sed 's/^# \{0,1\}//'
        exit 0 ;;
esac

MORADO="\033[1;35m"; VERDE="\033[1;32m"; AMAR="\033[1;33m"; ROJO="\033[1;31m"; NC="\033[0m"
ok()   { echo -e "   ${VERDE}OK${NC}  $*"; }
warn() { echo -e "   ${AMAR}!${NC}   $*"; }
err()  { echo -e "   ${ROJO}X${NC}   $*"; }

if [ "$(id -u)" != "0" ]; then
    err "Ejecuta con sudo:   sudo bash $0"
    exit 1
fi

LOG="/var/log/instalar-drivers-tbs.log"
echo "===================================================================="
echo -e " ${MORADO}TBS DRIVERS${NC} — instalacion profesional y verificacion DVB"
echo "===================================================================="
DISTRO="$(. /etc/os-release 2>/dev/null && echo "${PRETTY_NAME:-Linux}" || uname -s)"
KERNEL="$(uname -r)"
echo "   Sistema : $DISTRO"
echo "   Kernel  : $KERNEL"
echo "   Modo    : $([ "$SOLO_VERIFICAR" = 1 ] && echo 'solo verificar' || { [ "$FORZAR_OFICIAL" = 1 ] && echo 'driver OFICIAL TBS (forzado)' || echo 'automatico'; })"

# ------------------------------------------- 0) herramientas de deteccion
if ! command -v lspci >/dev/null 2>&1 || ! command -v lsusb >/dev/null 2>&1; then
    if command -v apt-get >/dev/null 2>&1; then
        export DEBIAN_FRONTEND=noninteractive
        apt-get update -qq >/dev/null 2>&1 || true
        apt-get install -y -qq pciutils usbutils >/dev/null 2>&1 || true
    fi
fi

# ---------------------------------------------------------------- 1) hardware
echo ""
echo "[1/5] Detectando tarjetas TBS (cualquier modelo)..."
TBS_HW=0
# 1a) PCI por /sys (sin depender de ninguna herramienta): vendor 0x544d = TBS
for d in /sys/bus/pci/devices/*/; do
    v="$(cat "$d/vendor" 2>/dev/null || true)"
    if [ "$v" = "0x544d" ]; then
        dv="$(cat "$d/device" 2>/dev/null || true)"
        sv="$(cat "$d/subsystem_vendor" 2>/dev/null || true)"
        sd="$(cat "$d/subsystem_device" 2>/dev/null || true)"
        echo "        PCI: TBS Technologies [544d:$dv  modelo:$sv:$sd]  ($(basename "$d"))"
        TBS_HW=1
    fi
done
# 1b) PCI por nombre (lspci)
if [ "$TBS_HW" = 0 ]; then
    HW_PCI="$(lspci -nn 2>/dev/null | grep -i -E "544d:|TBS Technologies|TurboSight" || true)"
    if [ -n "$HW_PCI" ]; then
        echo "$HW_PCI" | sed 's/^/        PCI: /'
        TBS_HW=1
    fi
fi
# 1c) USB TBS (nombre y vendor 0x734c)
HW_USB="$(lsusb 2>/dev/null | grep -i -E "TBS|TurboSight" || true)"
for d in /sys/bus/usb/devices/*/; do
    vi="$(cat "$d/idVendor" 2>/dev/null || true)"
    if [ "$vi" = "734c" ]; then
        pi="$(cat "$d/idProduct" 2>/dev/null || true)"
        HW_USB="${HW_USB}
        USB: TBS [734c:$pi]  ($(basename "$d"))"
        TBS_HW=1
    fi
done
[ -n "$HW_USB" ] && echo "$HW_USB" | sed 's/^/        /'

MULTIMEDIA="$(lspci -nn 2>/dev/null | grep -i -E "multimedia|saa71" || true)"
if [ "$TBS_HW" = 1 ]; then
    ok "Hardware TBS presente."
elif [ -n "$MULTIMEDIA" ]; then
    warn "No se reconocio el nombre como TBS, pero hay dispositivos multimedia:"
    echo "$MULTIMEDIA" | sed 's/^/          /'
    warn "(posible tarjeta TBS con ID no listado: se intentara el driver oficial)"
else
    warn "No se detectaron tarjetas TBS ni dispositivos multimedia."
    echo "        Diagnostico:"
    lspci -nn 2>/dev/null | sed 's/^/          /' | head -12
    lsusb 2>/dev/null | sed 's/^/          /' | head -8
    warn "Si la tarjeta TBS esta puesta y no aparece, revisa el slot/conexion."
fi

# --------------------------------------------------- 2) soporte actual kernel
echo ""
echo "[2/5] Comprobando soporte actual del kernel (sin tocar nada)..."
contar_frontends() { ls /dev/dvb/adapter*/frontend0 2>/dev/null | wc -l | tr -d ' '; }
mods_dvb() { lsmod | awk 'NR>1{print $1}' | grep -i -E "tbsecp3|saa716|cx23885|stv|m88ds|dvb_usb" | tr '\n' ' ' || true; }
FRONTENDS="$(contar_frontends)"
ADAPTADORES="$(ls -d /dev/dvb/adapter* 2>/dev/null | wc -l | tr -d ' ')"
echo "        Adaptadores DVB : $ADAPTADORES"
echo "        Frontends       : $FRONTENDS"
echo "        Modulos activos : $(mods_dvb)"

INSTALAR=0
if [ "$SOLO_VERIFICAR" = 1 ]; then
    [ "$FRONTENDS" -ge 1 ] && ok "Ya hay $FRONTENDS frontend(s) funcionando." \
                           || warn "No hay frontends (modo solo verificar: no se instala nada)."
elif [ "$FORZAR_OFICIAL" = 1 ]; then
    warn "Modo --oficial: se instalara el driver oficial TBS."
    INSTALAR=1
elif [ "$FRONTENDS" -ge 1 ]; then
    ok "El kernel/driver actual YA soporta la tarjeta: no hace falta instalar nada."
else
    if [ "$TBS_HW" = 1 ] || [ -n "$MULTIMEDIA" ]; then
        warn "Aun no hay frontends: se intentara habilitar/instalar el driver."
        INSTALAR=1
    else
        warn "No hay frontends y no se vio hardware: se OMITE la instalacion."
        warn "Si estas seguro de que la tarjeta esta puesta, ejecuta:  sudo bash $0 --oficial"
    fi
fi

# ------------------------------------------------- 3) preparar compilacion
if [ "$INSTALAR" = 1 ] && [ "$SOLO_VERIFICAR" = 0 ]; then
    echo ""
    echo "[3/5] Preparando herramientas de compilacion..."
    if command -v apt-get >/dev/null 2>&1; then
        export DEBIAN_FRONTEND=noninteractive
        apt-get update -qq >/dev/null 2>&1 || true
        apt-get install -y -qq build-essential "linux-headers-${KERNEL}" git wget unzip \
                patchutils libproc-processtable-perl dvb-tools pciutils usbutils >/dev/null 2>&1 \
            && ok "Paquetes instalados (compilador, headers del kernel, dvb-tools...)." \
            || warn "Algun paquete no se pudo instalar (revisa la conexion a internet)."
    else
        warn "Sistema sin apt-get: instala manualmente build-essential y los headers del kernel."
    fi

    # --------------- 3b) modulos incluidos en el kernel (familia EC P3)
    echo ""
    echo "[3b/5] Probando modulos DVB incluidos en el kernel..."
    for m in tbsecp3 saa7164 cx23885; do
        if modinfo "$m" >/dev/null 2>&1; then
            modprobe "$m" 2>/dev/null && ok "modprobe $m" || warn "modprobe $m no tuvo efecto"
        fi
    done
    sleep 2
    FRONTENDS="$(contar_frontends)"
    if [ "$FRONTENDS" -ge 1 ]; then
        ok "Frontends detectados con los modulos del kernel: no hace falta driver externo."
        INSTALAR=0
    fi
fi

# --------------------- 4) DRIVER OFICIAL TBS (metodos oficiales de TBS)
if [ "$INSTALAR" = 1 ] && [ "$SOLO_VERIFICAR" = 0 ]; then
    echo ""
    echo "[4/5] Instalando DRIVER OFICIAL TBS..."
    if command -v mokutil >/dev/null 2>&1 && mokutil --sb-state 2>/dev/null | grep -qi enabled; then
        warn "Secure Boot ACTIVO: un modulo externo sin firmar no cargara (firmalo o desactiva Secure Boot)."
    fi

    # Version del kernel: >= 6.8 -> metodo automatico oficial; si no, manual oficial
    KK="$(uname -r | cut -d. -f1)"; KV="$(uname -r | cut -d. -f2)"
    echo "== $(date '+%F %T') build para $(uname -r) ==" >> "$LOG"

    if [ "$KK" -gt 6 ] || { [ "$KK" -eq 6 ] && [ "$KV" -ge 8 ]; }; then
        echo "        Metodo OFICIAL automatico de TBS (kernel >= 6.8)..."
        if curl -fsSL --retry 3 --connect-timeout 20 \
             "https://www.tbsdtv.com/download/document/linux/drv-tbs.sh" -o /tmp/drv-tbs.sh \
           && sh /tmp/drv-tbs.sh >>"$LOG" 2>&1; then
            ok "Driver oficial instalado (script oficial de TBS, log: $LOG)."
        else
            warn "El instalador automatico de TBS fallo; se intenta el metodo manual..."
            INSTALAR_MANUAL=1
        fi
    else
        INSTALAR_MANUAL=1
    fi

    if [ "${INSTALAR_MANUAL:-0}" = 1 ]; then
        echo "        Metodo OFICIAL manual (kernel <= 6.14)..."
        echo "        (compila el arbol multimedia completo: puede tardar 15-30 min)"
        if command -v apt-get >/dev/null 2>&1; then
            export DEBIAN_FRONTEND=noninteractive
            apt-get update -qq >/dev/null 2>&1 || true
            apt-get install -y -qq gcc build-essential patchutils libproc-processtable-perl \
                    "linux-headers-$(uname -r)" git wget curl >/dev/null 2>&1 \
                && ok "Dependencias de compilacion listas." || warn "Faltaron algunas dependencias."
        fi
        SRC=/usr/local/src/tbs
        mkdir -p "$SRC"; cd "$SRC" || exit 1
        if [ ! -d "$SRC/media_build/.git" ]; then
            git clone --depth=1 https://github.com/tbsdtv/media_build.git "$SRC/media_build" >>"$LOG" 2>&1 || true
        fi
        if [ ! -d "$SRC/media/.git" ]; then
            git clone --depth=1 https://github.com/tbsdtv/linux_media.git -b latest "$SRC/media" >>"$LOG" 2>&1 || true
        fi
        if [ -d "$SRC/media_build" ] && [ -d "$SRC/media" ]; then
            cd "$SRC/media_build" || exit 1
            # Procedimiento oficial: make -C ../media && ./install.sh
            if make -C ../media >>"$LOG" 2>&1 && ./install.sh >>"$LOG" 2>&1; then
                ok "Driver oficial compilado e instalado (log: $LOG)."
            # Plan B: flujo clasico media_build
            elif make dirs >>"$LOG" 2>&1 && make -j"$(nproc)" >>"$LOG" 2>&1 && make install >>"$LOG" 2>&1; then
                ok "Driver oficial compilado e instalado (flujo clasico, log: $LOG)."
            else
                warn "La compilacion fallo (revisa: tail -40 $LOG)"
                warn "Alternativa manual: https://www.tbsdtv.com/download/"
            fi
            # Firmware OFICIAL de TBS (imprescindible en muchas tarjetas)
            echo "        Instalando firmware oficial de TBS..."
            if curl -fsSL --retry 3 "http://www.tbsdtv.com/download/document/linux/tbs-tuner-firmwares_v1.0.tar.bz2" \
                 -o /tmp/tbs-fw.tar.bz2 && tar -C /lib/firmware/ -jxf /tmp/tbs-fw.tar.bz2 2>/dev/null; then
                ok "Firmware instalado en /lib/firmware/."
            else
                warn "No se pudo instalar el firmware (revisa internet)."
            fi
            depmod -a 2>/dev/null || true
        else
            warn "No se pudieron obtener las fuentes del driver oficial."
            warn "Descarga manual en: https://www.tbsdtv.com/download/"
        fi
    fi
    warn "REINICIA el equipo para activar los drivers:  sudo reboot"
fi

# ---------------------------------------------------------- 5) verificacion
echo ""
echo "[5/5] VERIFICACION FINAL"
FRONTENDS="$(contar_frontends)"
ADAPTADORES="$(ls -d /dev/dvb/adapter* 2>/dev/null | wc -l | tr -d ' ')"
echo "        ------------------------------------------------------------"
echo "        Adaptadores: $ADAPTADORES    Frontends: $FRONTENDS"
if [ "$FRONTENDS" -ge 1 ] && command -v dvb-fe-tool >/dev/null 2>&1; then
    i=0
    for f in /dev/dvb/adapter*/frontend0; do
        [ -c "$f" ] || continue
        linea="$(timeout 6 dvb-fe-tool -a "$i" 2>/dev/null | grep -m1 "Device " | sed 's/ capabilities:.*//')"
        if [ -n "$linea" ]; then
            echo "        adapter$i : ${linea#Device }"
        else
            echo "        adapter$i : (sin lectura; puede estar en uso por otro software)"
        fi
        i=$((i+1))
    done
fi
echo "        Modulos    : $(mods_dvb)"
# ---- Diagnostico ampliado (para saber si el driver quedo bien) ----
if [ -d "/lib/modules/$(uname -r)/updates" ]; then
    echo "        Driver upd.: $(ls /lib/modules/"$(uname -r)"/updates 2>/dev/null | tr '\n' ' ')"
fi
FW="$(ls /lib/firmware 2>/dev/null | grep -i -E "tbs|dvb" | head -6 | tr '\n' ' ')"
echo "        Firmware   : ${FW:-ninguno (revisa /lib/firmware)}"
if command -v mokutil >/dev/null 2>&1; then
    echo "        SecureBoot : $(mokutil --sb-state 2>/dev/null | head -1)"
fi
DM="$(dmesg 2>/dev/null | grep -i -E "tbs|dvb|frontend|pcie.*error" | grep -v -i -E "apparmor|snap|audit" | tail -6)"
if [ -n "$DM" ]; then
    echo "        dmesg (ultimas señales):"
    echo "$DM" | sed 's/^/          /'
fi
echo "        ------------------------------------------------------------"

if [ "$FRONTENDS" -ge 1 ]; then
    echo ""
    ok "LISTO: hay $FRONTENDS frontend(s) funcionando. Ya puedes instalar/ejecutar el software de TV."
    exit 0
else
    echo ""
    err "TODAVIA NO HAY FRONTENDS."
    echo ""
    echo "        CONSEJOS OFICIALES DE TBS (tarjeta no detectada):"
    echo "         1) BIOS: pon el 'PCIe Link Speed' en GEN1 (solucion oficial TBS)."
    echo "         2) PCIe estable (recomendado por TBS): edita /etc/default/grub y agrega:"
    echo "              GRUB_CMDLINE_LINUX_DEFAULT=\"quiet splash pcie_aspm=off pci=nommconf\""
    echo "            y aplica:  sudo update-grub"
    echo "         3) Secure Boot: desactivado (los modulos externos no estan firmados)."
    echo "         4) Firmware: debe existir /lib/firmware/tbs*.fw (lo instala este script)."
    echo ""
    echo "        1) Si acabas de instalar el driver:  sudo reboot"
    echo "        2) Luego verifica con:  sudo bash $0 --verificar"
    echo "        3) Diagnostico:  dmesg | grep -i -E 'dvb|tbs|pcie' | tail -30"
    exit 1
fi
