#!/usr/bin/env bash

##########################################################################
#
# This bash script was written by ChatGPT, but not this comment section.
# Everything works after testing, but not 2 functions:
# - Adding metadata to compressed MP4 file.
# - Checking if the file has already been compressed by this script.
#
# However, I have done some fine tuning like adding new rows.
#
##########################################################################

set -u
export LC_NUMERIC=C

SCRIPT_NAME="$(basename "$0")"
UNIQUE_PREFIX="r-"

########################################
# Encoding presets overview:
#
# none  : balanced quality, AAC 96k
# vlog  : spoken voice / crowd, copy audio
# tiny  : max compression, AAC 64k
#
# Resolutions: 720p | 1080p
########################################

show_help() {
  cat <<EOF
Usage:
  $SCRIPT_NAME <file>
  $SCRIPT_NAME [none|vlog|tiny] [720p|1080p] <file>
  $SCRIPT_NAME batch

Batch:
  Compresses all MP4 + MKV files using:
  mode=none, resolution=1080p

Defaults:
  mode=none
  resolution=720p

EOF
  exit 0
}

[[ "${1:-}" == "--help" ]] && show_help

MODE="none"
RES="720p"

# --- Batch mode ---
if [[ "${1:-}" == "batch" ]]; then
  MODE="none"
  RES="1080p"
  shift || true

  shopt -s nullglob
  FILES=( *.mp4 *.MP4 *.mkv )
  shopt -u nullglob

  if [[ ${#FILES[@]} -eq 0 ]]; then
    echo "No MP4 or MKV files found."
    exit 0
  fi

  for f in "${FILES[@]}"; do
    "$0" "$MODE" "$RES" "$f"
  done
  exit 0
fi

# --- Parse arguments ---
if [[ $# -eq 1 ]]; then
  INPUT="$1"
elif [[ $# -eq 2 ]]; then
  MODE="$1"
  INPUT="$2"
elif [[ $# -eq 3 ]]; then
  MODE="$1"
  RES="$2"
  INPUT="$3"
else
  show_help
fi

[[ ! -f "$INPUT" ]] && { echo "File not found: $INPUT"; exit 1; }

BASENAME="${INPUT%.*}"
OUTPUT="${BASENAME}-r.mp4"
SUMMARY="${BASENAME}.json"

########################################
# Resolution
########################################
case "$RES" in
  720p) SCALE="scale=-2:720" ;;
  1080p) SCALE="scale=-2:1080" ;;
  *) echo "Invalid resolution"; exit 1 ;;
esac

########################################
# Mode settings
########################################
CQ=23
AUDIO_OPTS=("-c:a" "aac" "-b:a" "96k")

case "$MODE" in
  vlog)
    AUDIO_OPTS=("-c:a" "copy")
    CQ=23
    ;;
  tiny)
    AUDIO_OPTS=("-c:a" "aac" "-b:a" "64k")
    CQ=28
    ;;
  none) ;;
  *)
    echo "Invalid mode"
    exit 1
    ;;
esac

########################################
# Metadata detection (robust)
########################################
EXISTING_ID="$(ffprobe -v error \
  -show_entries format_tags=compressed_by \
  -of default=nk=1:nw=1 "$INPUT" 2>/dev/null || true)"

if [[ "$EXISTING_ID" =~ ^${UNIQUE_PREFIX}[A-Za-z0-9]+$ ]]; then
  echo "Skipping already-compressed file: $INPUT"
  exit 0
fi

########################################
# Generate unique ID
########################################
COMPRESS_ID="${UNIQUE_PREFIX}$(tr -dc A-Za-z0-9 </dev/urandom | head -c 12)"

########################################
# Encode
########################################
echo
echo "Compressing: $INPUT > $OUTPUT"

DURATION=$(ffprobe -v error -show_entries format=duration \
  -of default=nk=1:nw=1 "$INPUT")

START_TIME=$(date +%s)

ffmpeg -y -hide_banner -loglevel error \
  -i "$INPUT" \
  -map 0:v:0 -map 0:a? \
  -vf "$SCALE" \
  -c:v hevc_nvenc \
  -preset p6 -tune hq \
  -rc vbr -multipass fullres \
  -profile:v main -pix_fmt yuv420p \
  -spatial_aq 1 -temporal_aq 1 -aq-strength 8 \
  -cq "$CQ" \
  "${AUDIO_OPTS[@]}" \
  -movflags +faststart \
  -metadata compressed_by="$COMPRESS_ID" \
  -progress pipe:1 \
  "$OUTPUT" 2>/dev/null | while IFS='=' read -r key value; do

    if [[ "$key" == "out_time_ms" ]]; then
      CURRENT_SEC=$(awk "BEGIN { print $value / 1000000 }")

      PERCENT=$(awk -v c="$CURRENT_SEC" -v d="$DURATION" \
        'BEGIN { if (d>0) printf "%.1f", (c/d)*100; else print 0 }')

      NOW=$(date +%s)
      ELAPSED_SEC=$(( NOW - START_TIME ))

      ETA_SEC=$(awk -v e="$ELAPSED_SEC" -v p="$PERCENT" '
        BEGIN {
          if (p>0) printf "%.0f", e*(100-p)/p;
          else print 0
        }')

      printf "\rProgress: %5.1f%% | Elapsed: %02d:%02d | ETA: %02d:%02d" \
        "$PERCENT" \
        $((ELAPSED_SEC/60)) $((ELAPSED_SEC%60)) \
        $((ETA_SEC/60)) $((ETA_SEC%60))
    fi

done

########################################
# Size check
########################################
ORIG_SIZE=$(stat -c%s "$INPUT")
NEW_SIZE=$(stat -c%s "$OUTPUT")

if (( NEW_SIZE >= ORIG_SIZE )); then
  echo
  echo "Result larger than original - skipping"
  rm -f "$OUTPUT"
  exit 0
fi

########################################
# JSON summary
########################################
HUMAN_ORIG=$(numfmt --to=iec --suffix=B "$ORIG_SIZE")
HUMAN_NEW=$(numfmt --to=iec --suffix=B "$NEW_SIZE")
OCCURRED=$(date +"%Y-%m-%d %H:%M:%S")

########################################
# Safe reduction percent calculation
########################################
if [[ -z "$ORIG_SIZE" ]] || (( ORIG_SIZE == 0 )); then
    REDUCTION_PERCENT=0
else
    REDUCTION_PERCENT=$(awk "BEGIN { pct=(1-$NEW_SIZE/$ORIG_SIZE)*100; if(pct<0) pct=0; printf \"%.2f\", pct }")
fi

cat > "$SUMMARY" <<EOF
{
  "input": "$(basename "$INPUT")",
  "output": "$(basename "$OUTPUT")",

  "original_bytes": $ORIG_SIZE,
  "compressed_bytes": $NEW_SIZE,

  "original": "$HUMAN_ORIG",
  "compressed": "$HUMAN_NEW",

  "reduction_percent": $REDUCTION_PERCENT,
  "occurred": "$OCCURRED",

  "compression_id": "$COMPRESS_ID",

  "settings": {
    "codec": "hevc_nvenc",
    "resolution": "$RES",
    "mode": "$MODE",
    "cq": $CQ,
    "scale_filter": "$SCALE",
    "audio": "${AUDIO_OPTS[*]}",
    "preset": "p6",
    "rate_control": "vbr",
    "multipass": "fullres",
    "pixel_format": "yuv420p",
    "aq": {
      "spatial": 1,
      "temporal": 1,
      "strength": 8
    }
  }
}
EOF

REDUCTION_HR=$(awk "BEGIN { printf \"%.2f\", (1 - $NEW_SIZE / $ORIG_SIZE) * 100 }")

echo
echo "Done. Final reduction: $REDUCTION_HR% ($HUMAN_ORIG > $HUMAN_NEW)"
echo