#!/bin/bash
# make-finals.sh — one-off recovery script.
#
# Scans ALL *-temp.mp4 files under a backup root, infers the camera name from
# the path, uses season_info.py to get the correct movement info for each
# file's date, speed-adjusts to the right target duration, and writes
# *-final.mp4 files into MOVIES_DIR (from sky-cam.conf / .env).
#
# Safe to run multiple times — skips any final that already exists.
# Never modifies the backup.
#
# Usage:
#   ./make-finals.sh <backup_root> [--dry-run]
#
# Example:
#   ./make-finals.sh ~/drives/data2-main --dry-run
#   ./make-finals.sh ~/drives/data2-main

set -euo pipefail

SCRIPT_DIR="$(dirname "$(realpath "$0")")"
source "$SCRIPT_DIR/sky-cam.conf"
export TIMEZONE
ENCODE_PRESET="${ENCODE_PRESET:-slow}"
CRF_SEASONS_FINAL="${CRF_SEASONS_FINAL:-26}"

BACKUP_ROOT=""
DRY_RUN=false
FILTER_CAM=""
FILTER_SEASON=""
FILTER_MVT=""

while [[ $# -gt 0 ]]; do
    case "$1" in
        --dry-run)  DRY_RUN=true;          shift   ;;
        --cam)      FILTER_CAM="$2";       shift 2 ;;
        --season)   FILTER_SEASON="$2";    shift 2 ;;
        --mvt)      FILTER_MVT="$2";       shift 2 ;;
        -*)         echo "Unknown option: $1"; exit 1 ;;
        *)          BACKUP_ROOT="$1";      shift   ;;
    esac
done

if [ -z "$BACKUP_ROOT" ]; then
    echo "Usage: $0 <backup_root> [--cam CAM] [--season SEASON] [--mvt N] [--dry-run]"
    echo "  e.g. $0 ~/drives/data2-main --cam north --season Autumn --mvt 1"
    exit 1
fi

BACKUP_ROOT="$(realpath "$BACKUP_ROOT")"
music_base_dir="$MUSIC_DIR"
[ ! -d "$music_base_dir" ] && music_base_dir="$SCRIPT_DIR/music"

$DRY_RUN && echo "DRY RUN — no files will be written"
echo "Scanning: $BACKUP_ROOT"
echo "Output:   $MOVIES_DIR"
[ -n "$FILTER_CAM" ]    && echo "Filter:   cam=$FILTER_CAM"
[ -n "$FILTER_SEASON" ] && echo "Filter:   season=$FILTER_SEASON"
[ -n "$FILTER_MVT" ]    && echo "Filter:   mvt=$FILTER_MVT"
echo ""

# Known camera names in order of specificity (longer matches first)
KNOWN_CAMS=(sunrise north south east west)

infer_cam() {
    local path="$1"
    for cam in "${KNOWN_CAMS[@]}"; do
        if echo "$path" | grep -qE "(^|/)${cam}(/|$)"; then
            echo "$cam"
            return
        fi
    done
    echo ""
}

processed=0; skipped=0; errors=0

while IFS= read -r -d '' temp_file; do
    filename="$(basename "$temp_file")"
    date_str="${filename%%_*}"

    if ! [[ "$date_str" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
        echo "SKIP (bad name): $temp_file"
        (( skipped++ )) || true
        continue
    fi

    cam=$(infer_cam "${temp_file#$BACKUP_ROOT/}")
    if [ -z "$cam" ]; then
        echo "SKIP (unknown cam): $temp_file"
        (( skipped++ )) || true
        continue
    fi
    [ -n "$FILTER_CAM" ] && [ "$cam" != "$FILTER_CAM" ] && continue

    _info="$(python3 "$SCRIPT_DIR/season_info.py" "$date_str" 2>/dev/null)" || {
        echo "SKIP (season_info failed $date_str): $filename"
        (( skipped++ )) || true
        continue
    }
    eval "$_info"
    [ -n "$FILTER_SEASON" ] && [ "$SEASON" != "$FILTER_SEASON" ] && continue
    [ -n "$FILTER_MVT" ]    && [ "$MVT_NUM" != "$FILTER_MVT" ]   && continue

    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" ]; then
        echo "SKIP (no music $SEASON Mvt$MVT_NUM): $filename"
        (( skipped++ )) || true
        continue
    fi

    music_duration=$(ffprobe -v error -show_entries format=duration -of csv=p=0 "$music_file")
    loops_var="MONTAGE_MUSIC_LOOPS_${SEASON}_${MVT_NUM}"
    loops="${!loops_var:-${MONTAGE_MUSIC_LOOPS:-1}}"
    target=$(echo "scale=6; $music_duration * $loops / $DAYS_IN_MVT" | bc)

    out_dir="$MOVIES_DIR/$cam/$ASTRO_YEAR/$SEASON/Mvt$MVT_NUM"
    final="$out_dir/${date_str}_Mvt${MVT_NUM}-Day${DAY_OF_MVT}of${DAYS_IN_MVT}-final.mp4"

    if [ -f "$final" ]; then
        echo "EXISTS $cam/$ASTRO_YEAR/$SEASON/Mvt$MVT_NUM/$(basename "$final")"
        (( skipped++ )) || true
        continue
    fi

    raw_dur=$(ffprobe -v error -show_entries format=duration -of csv=p=0 "$temp_file" 2>/dev/null) || raw_dur=""
    vid_codec=$(ffprobe -v error -select_streams v:0 -show_entries stream=codec_name \
        -of csv=p=0 "$temp_file" 2>/dev/null) || vid_codec=""
    if [ -z "$raw_dur" ] || [ "$raw_dur" = "N/A" ] || [ -z "$vid_codec" ]; then
        echo "SKIP (corrupt/unreadable): $temp_file"
        (( skipped++ )) || true
        continue
    fi
    speed=$(echo "scale=6; $raw_dur / $target" | bc)

    echo "MAKE  $cam/$ASTRO_YEAR/$SEASON/Mvt$MVT_NUM/$(basename "$final")  [${speed}x]"

    if $DRY_RUN; then
        (( processed++ )) || true
        continue
    fi

    mkdir -p "$out_dir"
    if ffmpeg -loglevel warning \
        -i "$temp_file" \
        -vf "setpts=PTS/$speed" \
        -c:v libx264 -pix_fmt yuv420p -preset "$ENCODE_PRESET" -crf "$CRF_SEASONS_FINAL" \
        -t "$target" -an \
        -y "$final"; then
        (( processed++ )) || true
    else
        rm -f "$final"
        echo "  ERROR: ffmpeg failed"
        (( errors++ )) || true
    fi

done < <(find "$BACKUP_ROOT" -name "*-temp.mp4" -print0 | sort -z)

echo ""
echo "────────────────────────────────────────"
echo "Written: $processed   Skipped: $skipped   Errors: $errors"
$DRY_RUN && echo "(dry run — re-run without --dry-run to write files)"
