#!/usr/bin/env bash
# optimize.sh
# Baja bitrate de archivos .mp4 en:
#   /var/www/html/uploads/events
#   /var/www/html/uploads/videos
# Evita reprocesar usando marcador externo: archivo.mp4.procesado.ok
# Borra automáticamente sus propios logs de más de 4 días.
# Este script lo hice con IA así que hay que evaluar su funcionamiento.

set -o pipefail

BASE_DIR="/var/www/html/uploads"
DIR_EVENTS="$BASE_DIR/events"
DIR_VIDEOS="$BASE_DIR/videos"

DRY_RUN=0
DIRECTORIO_ESPECIFICO=""
declare -a MODOS_FECHA=()
MODO_TODO=0

TARGET_BITRATE="200k"
SKIP_BITRATE_BPS=250000

FECHA="$(date +%Y%m%d_%H%M%S)"
LOG_DIR="/var/log/optimize_videos"
LOCK_FILE="/tmp/optimize_videos.lock"

mkdir -p "$LOG_DIR" 2>/dev/null || LOG_DIR="/tmp"
LOG_FILE="$LOG_DIR/optimize_$FECHA.log"

log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG_FILE"
}

usage() {
    cat <<USAGE
Uso:
  bash $0 [opciones]

Opciones (Por defecto procesa los últimos 3 días si no se especifican opciones):
  --dir RUTA        Procesa una ruta específica.
  --today           Procesa únicamente el día actual.
  --yesterday       Procesa únicamente el día anterior.
  --all             Procesa TODO el histórico (comportamiento antiguo por defecto).
  --dry-run         Simula, no comprime ni reemplaza archivos.
  --help            Muestra esta ayuda.
USAGE
}

while [[ $# -gt 0 ]]; do
    case "$1" in
        --dir)
            shift
            if [[ -z "${1:-}" ]]; then
                echo "Error: falta ruta después de --dir"
                exit 1
            fi
            DIRECTORIO_ESPECIFICO="$1"
            ;;
        --today)
            MODOS_FECHA=("$(date +%F)")
            ;;
        --yesterday)
            MODOS_FECHA=("$(date -d 'yesterday' +%F)")
            ;;
        --all)
            MODO_TODO=1
            ;;
        --dry-run)
            DRY_RUN=1
            ;;
        --help|-h)
            usage
            exit 0
            ;;
        *)
            echo "Opción no reconocida: $1"
            usage
            exit 1
            ;;
    esac
    shift
done

exec 200>"$LOCK_FILE"
if ! flock -n 200; then
    echo "Ya existe otra ejecución activa. Saliendo."
    exit 0
fi

if ! command -v ffmpeg >/dev/null 2>&1; then
    log "ERROR: ffmpeg no está instalado o no está en PATH."
    exit 1
fi

if ! command -v ffprobe >/dev/null 2>&1; then
    log "ERROR: ffprobe no está instalado o no está en PATH."
    exit 1
fi

get_bitrate_bps() {
    local file="$1"
    local br=""

    br="$(ffprobe -v error -select_streams v:0 -show_entries stream=bit_rate -of default=noprint_wrappers=1:nokey=1 "$file" 2>/dev/null | head -n 1 | tr -d '\r')"

    if [[ -z "$br" || "$br" == "N/A" || ! "$br" =~ ^[0-9]+$ ]]; then
        br="$(ffprobe -v error -show_entries format=bit_rate -of default=noprint_wrappers=1:nokey=1 "$file" 2>/dev/null | head -n 1 | tr -d '\r')"
    fi

    if [[ -z "$br" || "$br" == "N/A" || ! "$br" =~ ^[0-9]+$ ]]; then
        echo "0"
    else
        echo "$br"
    fi
}

get_audio_count() {
    local file="$1"
    ffprobe -v error -select_streams a -show_entries stream=index -of csv=p=0 "$file" 2>/dev/null | wc -l | tr -d ' '
}

TOTAL=0
SALTADOS=0
PROCESADOS=0
ERRORES=0
MARCADOS=0

procesar_directorio() {
    local DIRECTORIO="$1"

    if [[ ! -d "$DIRECTORIO" ]]; then
        log "[SKIP] Directorio no existe: $DIRECTORIO"
        return
    fi

    log "------------------------------------------------"
    log "Procesando directorio: $DIRECTORIO"

    while IFS= read -r -d '' video; do
        TOTAL=$((TOTAL + 1))
        video="$(echo "$video" | tr -d '\r')"
        marker="${video}.procesado.ok"

        if [[ ! -f "$video" ]]; then
            log "[ERROR] No existe físicamente: $video"
            ERRORES=$((ERRORES + 1))
            continue
        fi

        if [[ "$video" == *.tmp.mp4 || "$video" == *.tmp.*.mp4 ]]; then
            log "[SKIP] Temporal ignorado: $video"
            SALTADOS=$((SALTADOS + 1))
            continue
        fi

        if [[ -f "$marker" && "$marker" -nt "$video" ]]; then
            log "[SKIP] Ya procesado por marcador: $video"
            SALTADOS=$((SALTADOS + 1))
            continue
        fi

        if ffprobe -v error -show_entries format_tags=procesado -of default=noprint_wrappers=1:nokey=1 "$video" 2>/dev/null | grep -qi "true"; then
            log "[SKIP] Ya procesado por metadata: $video"
            [[ "$DRY_RUN" -eq 0 ]] && touch "$marker"
            SALTADOS=$((SALTADOS + 1))
            continue
        fi

        bitrate_bps="$(get_bitrate_bps "$video")"
        audio_count="$(get_audio_count "$video")"

        if [[ "$bitrate_bps" =~ ^[0-9]+$ && "$bitrate_bps" -gt 0 && "$bitrate_bps" -le "$SKIP_BITRATE_BPS" && "$audio_count" -eq 0 ]]; then
            log "[SKIP] Parece ya comprimido: ${bitrate_bps} bps, audio=${audio_count}. Marcando: $video"
            [[ "$DRY_RUN" -eq 0 ]] && touch "$marker"
            SALTADOS=$((SALTADOS + 1))
            MARCADOS=$((MARCADOS + 1))
            continue
        fi

        log "[PROC] Procesando: $video"
        log "       Bitrate actual: ${bitrate_bps} bps | Audio streams: ${audio_count}"

        tmp_video="${video%.mp4}.tmp.$$.$RANDOM.mp4"

        if [[ "$DRY_RUN" -eq 1 ]]; then
            log "       DRY-RUN: no se ejecuta ffmpeg."
            continue
        fi

        ffmpeg -nostdin -v error -i "$video" \
            -c:v libx264 \
            -b:v "$TARGET_BITRATE" \
            -preset medium \
            -an \
            -metadata procesado="true" \
            -metadata comment="procesado=true" \
            -y "$tmp_video"

        if [[ $? -eq 0 && -s "$tmp_video" ]]; then
            mv -f "$tmp_video" "$video"
            touch "$marker"
            log "       [OK] Video comprimido, reemplazado y marcado."
            PROCESADOS=$((PROCESADOS + 1))
        else
            log "       [ERROR] Falló la compresión. Manteniendo original."
            rm -f "$tmp_video"
            ERRORES=$((ERRORES + 1))
        fi
    done < <(find "$DIRECTORIO" -type f -iname "*.mp4" ! -iname "*.tmp.mp4" ! -iname "*.tmp.*.mp4" -print0)
}

log "Iniciando compresión de videos."
log "Modo dry-run: $DRY_RUN"
log "Bitrate objetivo: $TARGET_BITRATE"

if [[ -n "$DIRECTORIO_ESPECIFICO" ]]; then
    procesar_directorio "$DIRECTORIO_ESPECIFICO"
elif [[ "$MODO_TODO" -eq 1 ]]; then
    log "Modo: Escaneo completo de directorios principales."
    procesar_directorio "$DIR_EVENTS"
    procesar_directorio "$DIR_VIDEOS"
else
    if [[ ${#MODOS_FECHA[@]} -eq 0 ]]; then
        log "Modo por defecto: Analizando últimos 3 días."
        MODOS_FECHA=(
            "$(date +%F)"
            "$(date -d '1 day ago' +%F)"
            "$(date -d '2 days ago' +%F)"
        )
    fi

    for fecha in "${MODOS_FECHA[@]}"; do
        procesar_directorio "$DIR_EVENTS/$fecha"
        procesar_directorio "$DIR_VIDEOS/$fecha"
    done
fi

log "------------------------------------------------"
log "Proceso finalizado."
log "Total detectados: $TOTAL"
log "Procesados: $PROCESADOS"
log "Saltados: $SALTADOS"
log "Marcados como ya comprimidos: $MARCADOS"
log "Errores: $ERRORES"

# --- NUEVA SECCIÓN: AUTOLIMPIEZA DE LOGS VIEJOS ---
log "Iniciando limpieza de logs antiguos (mayores a 4 días)..."
if [[ "$DRY_RUN" -eq 1 ]]; then
    log "       DRY-RUN: Simulando borrado de logs antiguos."
    find "$LOG_DIR" -type f -name "optimize_*.log" -mtime +4 -exec echo "       [SIMULACIÓN] Se borraría: {}" \;
else
    # Busca logs creados hace más de 4 días (+4) y los elimina
    LOGS_ELIMINADOS=$(find "$LOG_DIR" -type f -name "optimize_*.log" -mtime +4 -delete -print | wc -l)
    log "       Se eliminaron $LOGS_ELIMINADOS archivo(s) de log antiguos."
fi
# --------------------------------------------------

log "Log actual guardado en: $LOG_FILE"
