#!/bin/bash
# 4-seasons.sh — create one daily clip from yesterday's images, sized to its
# share of the corresponding Vivaldi movement's music duration.
#
# On the last day of a movement period, automatically runs montage-mvt.sh to
# compile the full movement montage.
#
# Run once per day from cron (e.g. 01:00 daily).

set -euo pipefail

SCRIPT_DIR="$(dirname "$(realpath "$0")")"
source "$SCRIPT_DIR/sky-cam.conf"
export TIMEZONE   # make it visible to season_info.py subprocess

# Camera name: first argument overrides conf (systemd passes it via ExecStart).
CAM_NAME="${1:-$SUNRISE_CAM}"

# ── Configuration ──────────────────────────────────────────────────────────────
base_dir="$BASE_DIR"
music_base_dir="$MUSIC_DIR"
[ ! -d "$music_base_dir" ] && music_base_dir="$SCRIPT_DIR/music"

# ── Date setup ────────────────────────────────────────────────────────────────
yesterday=$(date --date="yesterday" +%Y-%m-%d)
echo "Processing: $yesterday"

# ── Season / movement info from astronomical calculation ──────────────────────
_season_info="$(python3 "$SCRIPT_DIR/season_info.py" "$yesterday")" || {
    echo "Error: season_info.py failed — check Python dependencies (suntime pytz)"
    exit 1
}
eval "$_season_info"
# Provides: SEASON  MVT_NUM  DAY_OF_MVT  DAYS_IN_MVT  MVT_START  MVT_END
#           IS_LAST_DAY  ASTRO_YEAR
echo "Season=$SEASON  Mvt=$MVT_NUM  Year=$ASTRO_YEAR  Day=$DAY_OF_MVT/$DAYS_IN_MVT  LastDay=$IS_LAST_DAY"

# ── Locate music file and get its duration ────────────────────────────────────
music_file=$(find "$music_base_dir" -type f -iname "*${SEASON}*" \
    | grep -iE "Mvt[^0-9]*${MVT_NUM}[^0-9]" | sort | head -n 1)
if [ -z "$music_file" ] || [ ! -f "$music_file" ]; then
    echo "ERROR: Music file not found for $SEASON Mvt $MVT_NUM in $music_base_dir"
    exit 1
fi
music_duration=$(ffprobe -v error -show_entries format=duration -of csv=p=0 "$music_file")
echo "Music: $(basename "$music_file")  ($music_duration s)"

# Each daily clip covers music_duration / DAYS_IN_MVT seconds so that
# concatenating all clips for the movement sums to the exact music duration.
target_per_clip=$(echo "scale=6; $music_duration / $DAYS_IN_MVT" | bc)
echo "Target clip duration: $target_per_clip s  ($DAYS_IN_MVT days in movement)"

# ── Locate yesterday's images ─────────────────────────────────────────────────
image_dir="$base_dir/$CAM_NAME/$yesterday"

if [ ! -d "$image_dir" ]; then
    echo "WARNING: Image directory $image_dir not found — skipping $yesterday."
    exit 0
fi

total_images=$(find "$image_dir" -type f -name "*.jpg" | wc -l)
if [ "$total_images" -lt 1 ]; then
    echo "WARNING: No images in $image_dir — skipping $yesterday."
    exit 0
fi
echo "Images found: $total_images"

# ── Prepare output directory ──────────────────────────────────────────────────
output_dir="$MOVIES_DIR/$CAM_NAME/$ASTRO_YEAR/$SEASON/Mvt$MVT_NUM"
mkdir -p "$output_dir"

# ── Build sorted image list ───────────────────────────────────────────────────
temp_file=$(mktemp --suffix=.txt)
temp_video="$output_dir/${yesterday}_Mvt${MVT_NUM}-temp.mp4"
cleanup() { rm -f "$temp_file" "$temp_video" 2>/dev/null || true; }
trap cleanup EXIT

find "$image_dir" -type f -name "*.jpg" | sort | while read -r img; do
    echo "file '$img'"
done > "$temp_file"

# ── Step 1: Build raw video at default frame rate ─────────────────────────────
echo "Step 1/2: encoding raw video..."
ffmpeg -loglevel warning \
    -f concat -safe 0 -i "$temp_file" \
    -c:v libx264 -pix_fmt yuv420p -crf "$CRF_SEASONS_RAW" -vsync 2 -an \
    -y "$temp_video"

raw_duration=$(ffprobe -v error -show_entries format=duration -of csv=p=0 "$temp_video")
echo "Raw duration: $raw_duration s"

# ── Step 2: Speed-adjust to target clip duration ──────────────────────────────
speed_factor=$(echo "scale=6; $raw_duration / $target_per_clip" | bc)
echo "Step 2/2: speed factor $speed_factor..."

final_file="$output_dir/${yesterday}_Mvt${MVT_NUM}-Day${DAY_OF_MVT}of${DAYS_IN_MVT}-final.mp4"
if ! ffmpeg -loglevel warning \
    -i "$temp_video" \
    -vf "setpts=PTS/$speed_factor" \
    -c:v libx264 -pix_fmt yuv420p -crf "$CRF_SEASONS_FINAL" \
    -t "$target_per_clip" -an \
    -y "$final_file"; then
    rm -f "$final_file"
    "$SCRIPT_DIR/notify.sh" "FAILED: $SEASON Mvt$MVT_NUM Day$DAY_OF_MVT speed-adjust ($yesterday)" \
        "ffmpeg speed-adjust failed — re-run 4-seasons.sh $CAM_NAME while JPGs exist" || true
    exit 1
fi

adjusted=$(ffprobe -v error -show_entries format=duration -of csv=p=0 "$final_file")
echo "Daily clip: $final_file  ($adjusted s)"

# Warn if clip duration deviates more than 0.5 s from target (float drift check)
drift=$(echo "scale=3; $adjusted - $target_per_clip" | bc | sed 's/^-//')
if awk "BEGIN{exit !($drift > 0.5)}"; then
    echo "WARNING: clip duration ${adjusted}s differs from target ${target_per_clip}s by ${drift}s"
    "$SCRIPT_DIR/notify.sh" "WARNING: $SEASON Mvt$MVT_NUM Day$DAY_OF_MVT duration drift ($yesterday)" \
        "Clip ${adjusted}s vs target ${target_per_clip}s (drift ${drift}s)" || true
fi

"$SCRIPT_DIR/notify.sh" "$SEASON Mvt$MVT_NUM Day$DAY_OF_MVT/$DAYS_IN_MVT saved ($yesterday)" \
    "$(basename "$final_file") — ${adjusted}s" || true

# ── Auto-trigger montage on last day of movement ──────────────────────────────
if [ "$IS_LAST_DAY" = "true" ]; then
    echo "Last day of $SEASON Mvt $MVT_NUM — triggering montage compilation..."
    # Pass $yesterday so montage-mvt.sh looks up the correct movement
    # (running the next morning, "today" would already be the next movement).
    "$SCRIPT_DIR/montage-mvt.sh" "$yesterday" "$CAM_NAME"
fi
