#!/bin/bash
# push_artifacts.sh — upload benchmark artifacts (galleries, montage frames) to the
# Gitea generic package registry, decoupled from git history entirely. These are
# NOT needed to run the main app — only for benchmarks/experiments/reports.
#
# Requires GITEA_TOKEN in the environment (a Gitea access token with package
# read/write scope). Never hardcode the token; export it in your shell:
#   export GITEA_TOKEN=...
#
# Usage:
#   scripts/artifacts/push_artifacts.sh galleries
#   scripts/artifacts/push_artifacts.sh montage-frames
#   scripts/artifacts/push_artifacts.sh experiment-data
#   scripts/artifacts/push_artifacts.sh report-highlights
#   scripts/artifacts/push_artifacts.sh xsource
#   scripts/artifacts/push_artifacts.sh replay-fixtures
#   scripts/artifacts/push_artifacts.sh galleries montage-frames experiment-data report-highlights
#
# Package layout (owner=dtourolle, repo=scene-actor-extraction):
#   generic/galleries/<version>/gallery_<model>.h5        (one file per model)
#   generic/replay-fixtures/<version>/replay-fixtures.zip (T2 dumps + their gallery)
#   generic/montage-frames/<version>/<film-slug>.zip      (zipped per-film frames)
#   generic/experiment-data/<version>/experiment-data.zip (manifests/trajectories/results)
#   generic/report-highlights/<version>/<name>.jpg        (individual, hand-picked
#     illustrative frames referenced by docs/*.md that aren't reproducible via
#     the automated best/worst montage selection — see scripts/docs/build_site.sh)
# version = current git short SHA, so artifacts are traceable to the code that
# produced them. Re-running with the same SHA overwrites that version's files.
set -euo pipefail

REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
OWNER="dtourolle"
PKG_REPO="scene-actor-extraction"
# NOTE: the generic package registry lives under /api/packages/ (no /v1/) —
# distinct from the regular REST API under /api/v1/packages/ used for listing.
BASE_URL="https://gitea.tourolle.paris/api/packages/${OWNER}"
VERSION="$(git -C "$REPO_ROOT" rev-parse --short HEAD)"

if [ -z "${GITEA_TOKEN:-}" ]; then
    echo "error: GITEA_TOKEN is not set. export GITEA_TOKEN=<your token> and retry." >&2
    exit 1
fi

upload() {
    local package="$1" filename="$2" filepath="$3"
    local url="${BASE_URL}/generic/${package}/${VERSION}/${filename}"
    echo "  uploading ${filename} -> ${package}/${VERSION}..."
    curl -sf -X PUT "$url" \
        -H "Authorization: token ${GITEA_TOKEN}" \
        -H "Content-Type: application/octet-stream" \
        --upload-file "$filepath" \
        -o /dev/null -w "    HTTP %{http_code}\n"
}

push_replay_fixtures() {
    echo "=== replay-fixtures (version ${VERSION}) ==="
    # T2 replay fixtures: per-frame detections, landmarks and embeddings dumped
    # from a real run, so the tracker and identity stages can be replayed on CPU
    # with no GPU, no models and no film. Too large for git (superhero.h5 alone
    # is ~9 MB) and regenerating them needs the film plus a GPU, which CI has
    # neither of — so they ship as artifacts and CI pulls them.
    #
    # The gallery travels with them: a dump replays against the gallery it was
    # produced with, and pairing a dump with a different gallery silently
    # changes every identity decision in it.
    local dir="${REPO_ROOT}/tests/fixtures/dumps"
    if [ ! -d "$dir" ]; then
        echo "  no tests/fixtures/dumps dir, skipping" >&2
        return
    fi
    local tmp
    tmp="$(mktemp -d)"
    ( cd "$dir" && zip -qr "$tmp/replay-fixtures.zip" . )
    upload "replay-fixtures" "replay-fixtures.zip" "$tmp/replay-fixtures.zip"
    rm -rf "$tmp"
}

push_galleries() {
    echo "=== galleries (version ${VERSION}) ==="
    local dir="${REPO_ROOT}/experiments/galleries"
    shopt -s nullglob
    for f in "$dir"/gallery_*.h5; do
        upload "galleries" "$(basename "$f")" "$f"
    done
    shopt -u nullglob
}

push_montage_frames() {
    echo "=== montage-frames (version ${VERSION}) ==="
    local root="${REPO_ROOT}/experiments/results/holdout/montage_bestworst"
    if [ ! -d "$root" ]; then
        echo "  no montage_bestworst dir found, skipping" >&2
        return
    fi
    local tmp
    tmp="$(mktemp -d)"
    trap 'rm -rf "$tmp"' RETURN
    for filmdir in "$root"/*/; do
        [ -d "$filmdir" ] || continue
        local slug ascii_slug zipfile
        slug="$(basename "$filmdir")"
        # Gitea's generic package registry rejects non-ASCII filenames (verified:
        # a bare é in the name 400s). Transliterate for the upload name only —
        # the local directory name (with accents) is untouched.
        ascii_slug="$(echo "$slug" | iconv -f utf-8 -t ascii//translit 2>/dev/null || echo "$slug")"
        zipfile="${tmp}/${ascii_slug}.zip"
        (cd "$filmdir" && zip -qr "$zipfile" .)
        upload "montage-frames" "${ascii_slug}.zip" "$zipfile"
    done
}

push_experiment_data() {
    echo "=== experiment-data (version ${VERSION}) ==="
    # manifests/trajectories/results are all small text/JSON — no source paths
    # (manifests never carry a "movie" field; see experiments/file-lut.json)
    # so this is safe to share as one bundle.
    local tmp; tmp="$(mktemp -d)"
    trap 'rm -rf "$tmp"' RETURN
    local zipfile="${tmp}/experiment-data.zip"
    (cd "$REPO_ROOT" && zip -qr "$zipfile" \
        experiments/manifests experiments/trajectories experiments/results \
        -x '*.log' -x '*/holdout/montage_bestworst/*' -x '*/holdout/frames/*' \
        -x '*/holdout/montage/*' -x '*/holdout/*.jsonl' -x '*/holdout/pred_*.json' \
        -x '*/holdout/raw_*.jsonl')
    upload "experiment-data" "experiment-data.zip" "$zipfile"
}

push_report_highlights() {
    echo "=== report-highlights (version ${VERSION}) ==="
    local src="${REPO_ROOT}/experiments/results/holdout/montage/many_saints/out_of_cast_fpi/10_t003641.jpg"
    if [ ! -f "$src" ]; then
        echo "  [warn] $src not found, skipping" >&2
        return
    fi
    upload "report-highlights" "germar_beats_xray.jpg" "$src"
}

push_xsource() {
    echo "=== xsource (version ${VERSION}) ==="
    local root="${REPO_ROOT}/experiments/xsource"
    if [ ! -d "$root/labelling" ]; then
        echo "  no experiments/xsource/labelling found, skipping" >&2
        return
    fi

    # Source recordings. Already compressed, so uploaded as-is rather than zipped.
    shopt -s nullglob
    for f in "$root"/clips/*.mp4; do
        upload "xsource" "$(basename "$f")" "$f"
    done
    shopt -u nullglob

    # The hand-sorted crops and their manifests. This is human ground truth and
    # the expensive part of the study — a person looked at every crop and put it
    # in a folder. Frames are deliberately NOT pushed: they are deterministic
    # from the clips, and pulling regenerates them.
    local tmp; tmp="$(mktemp -d)"
    trap 'rm -rf "$tmp"' RETURN
    local zipfile="${tmp}/labelling.zip"
    (cd "$root" && zip -qr "$zipfile" labelling -x 'labelling/*.html' -x 'labelling/review_*.jpg' \
        -x 'labelling/verify_*.jpg')
    upload "xsource" "labelling.zip" "$zipfile"
}

if [ $# -eq 0 ]; then
    echo "usage: $0 <galleries|montage-frames|experiment-data|report-highlights|xsource> [...]" >&2
    exit 1
fi

for target in "$@"; do
    case "$target" in
        galleries)          push_galleries ;;
        montage-frames)     push_montage_frames ;;
        experiment-data)    push_experiment_data ;;
        report-highlights)  push_report_highlights ;;
        xsource)            push_xsource ;;
        replay-fixtures)    push_replay_fixtures ;;
        *) echo "unknown target: $target (expected galleries, montage-frames, experiment-data, report-highlights, xsource, or replay-fixtures)" >&2; exit 1 ;;
    esac
done

echo "Done. Browse at: https://gitea.tourolle.paris/${OWNER}/${PKG_REPO}/packages"
