#!/usr/bin/env bash
set -uo pipefail

SCRIPT_NAME="$(basename "$0")"

# Defaults
TITLE=""
OUTPUT=""
RESOLUTION="1920x1080"
FONT_SIZE="72"
FONT_COLOR="white"
BG_COLOR="black"
IMAGE=""
DRYRUN=false

usage() {
    cat <<EOF
Usage: $SCRIPT_NAME [OPTIONS] <input.mp3>

Convert an MP3 audio file into an MP4 video displaying a static title card.

Arguments:
  <input.mp3>          Path to the MP3 file (required)

Options:
  -t, --title TEXT     Title text to display (required)
  -o, --output PATH    Output file path (default: input with .mp4 extension)
  -r, --resolution WxH Video resolution (default: 1920x1080)
  --font-size N        Font size in pixels (default: 72)
  --font-color COLOR   Font colour (default: white)
  --bg-color COLOR     Background colour (default: black; ignored with --image)
  -i, --image PATH     Background image (scaled to fill; title at bottom)
  -n, --dryrun         Preview what would happen without creating files
  -h, --help           Show this help message
EOF
}

die() {
    echo "Error: $1" >&2
    exit 1
}

# Parse arguments
INPUT=""
while [[ $# -gt 0 ]]; do
    case "$1" in
        -t|--title)    TITLE="$2"; shift 2 ;;
        -o|--output)   OUTPUT="$2"; shift 2 ;;
        -r|--resolution) RESOLUTION="$2"; shift 2 ;;
        --font-size)   FONT_SIZE="$2"; shift 2 ;;
        --font-color)  FONT_COLOR="$2"; shift 2 ;;
        --bg-color)    BG_COLOR="$2"; shift 2 ;;
        -i|--image)    IMAGE="$2"; shift 2 ;;
        -n|--dryrun)   DRYRUN=true; shift ;;
        -h|--help)     usage; exit 0 ;;
        -*)            die "unknown option: $1" ;;
        *)             INPUT="$1"; shift ;;
    esac
done

# Validate
[[ -z "$INPUT" ]] && die "no input file specified. See --help."
[[ -f "$INPUT" ]] || die "file not found: $INPUT"
[[ -z "$TITLE" ]] && die "--title is required"
command -v ffmpeg >/dev/null 2>&1 || die "ffmpeg not found. Install with: sudo apt install ffmpeg"
command -v ffprobe >/dev/null 2>&1 || die "ffprobe not found. Install with: sudo apt install ffmpeg"
[[ -n "$IMAGE" && ! -f "$IMAGE" ]] && die "image not found: $IMAGE"

# Default output path
if [[ -z "$OUTPUT" ]]; then
    OUTPUT="${INPUT%.*}.mp4"
fi

# Get audio duration
DURATION_SECS=$(ffprobe -v error -show_entries format=duration -of csv=p=0 "$INPUT" 2>/dev/null) \
    || die "could not read audio duration from: $INPUT"

# Format duration for display
format_duration() {
    local secs="${1%.*}"
    local mins=$((secs / 60))
    local rem=$((secs % 60))
    if [[ $mins -gt 0 ]]; then
        echo "${mins}m ${rem}s"
    else
        echo "${rem}s"
    fi
}

DURATION_DISPLAY=$(format_duration "$DURATION_SECS")

# Get ffmpeg version
FFMPEG_VERSION=$(ffmpeg -version | head -1 | awk '{print $3}')

if $DRYRUN; then
    echo "[dryrun] Input:       $INPUT"
    echo "[dryrun] Output:      $OUTPUT"
    echo "[dryrun] Title:       $TITLE"
    echo "[dryrun] Duration:    $DURATION_DISPLAY"
    echo "[dryrun] Resolution:  $RESOLUTION"
    echo "[dryrun] Font size:   $FONT_SIZE"
    echo "[dryrun] Font color:  $FONT_COLOR"
    if [[ -n "$IMAGE" ]]; then
        echo "[dryrun] Background:  $IMAGE (image)"
    else
        echo "[dryrun] Background:  $BG_COLOR"
    fi
    echo "[dryrun] Dependencies OK: ffmpeg $FFMPEG_VERSION"
    echo "[dryrun] Would generate .mp4 video file"
    exit 0
fi

# Parse resolution
WIDTH="${RESOLUTION%x*}"
HEIGHT="${RESOLUTION#*x}"

# Escape title for ffmpeg drawtext (colons and backslashes need escaping)
ESCAPED_TITLE=$(echo "$TITLE" | sed "s/'/\\\\\\\\'/g" | sed 's/:/\\:/g')

if [[ -n "$IMAGE" ]]; then
    # Image background: scale+crop to fill, title centred at bottom
    ffmpeg -y \
        -loop 1 -i "$IMAGE" \
        -i "$INPUT" \
        -vf "scale=${WIDTH}:${HEIGHT}:force_original_aspect_ratio=increase,crop=${WIDTH}:${HEIGHT},drawtext=text='${ESCAPED_TITLE}':fontsize=${FONT_SIZE}:fontcolor=${FONT_COLOR}:x=(w-text_w)/2:y=h-text_h-40" \
        -c:v libx264 -tune stillimage -pix_fmt yuv420p \
        -c:a aac -b:a 192k \
        -shortest \
        "$OUTPUT"
else
    # Solid colour background: title centred
    ffmpeg -y \
        -f lavfi -i "color=c=${BG_COLOR}:s=${RESOLUTION}:d=${DURATION_SECS}" \
        -i "$INPUT" \
        -vf "drawtext=text='${ESCAPED_TITLE}':fontsize=${FONT_SIZE}:fontcolor=${FONT_COLOR}:x=(w-text_w)/2:y=(h-text_h)/2" \
        -c:v libx264 -tune stillimage -pix_fmt yuv420p \
        -c:a aac -b:a 192k \
        -shortest \
        "$OUTPUT"
fi

echo "$OUTPUT"
