#!/usr/bin/env bash
# tugas.sh — tugas terjadwal: sinkronisasi folder sumber ke mirror.
#
# Tugas ini dirancang untuk dipanggil scheduler (cron / systemd timer):
#   - idempoten: berapa kali pun dijalankan, keadaan akhir mirror sama,
#   - lokasi kerja dihitung dari letak skrip, bukan cwd pemanggil,
#     sehingga aman dipanggil dari environment minimal milik cron,
#   - setiap eksekusi menuliskan SATU baris log terstruktur yang bisa
#     dibaca cek-jadwal.sh.
#
# Pemakaian:
#   tugas.sh [--dry-run] [--verbose]
#
# Opsi:
#   --dry-run   tampilkan perubahan yang akan dilakukan tanpa menjalankannya
#   --verbose   tampilkan daftar perubahan per berkas
#
# Variabel lingkungan (berguna untuk pengujian deterministik):
#   TUGAS_SRC   folder sumber  (default: <letak skrip>/sumber)
#   TUGAS_DEST  folder mirror  (default: <letak skrip>/mirror)
#   TUGAS_LOG   berkas log    (default: <letak skrip>/log/tugas.log)
#   STAMP       waktu eksekusi, format YYYYMMDDTHHMMSS (default: sekarang)
#
# Kode keluar:
#   0 sukses                       1 opsi tidak dikenal
#   2 folder sumber tidak ada      3 rsync gagal
#
# Catatan: kunci anti-dobel (flock) sengaja TIDAK ada di skrip ini;
# kunci dipasang di lapisan scheduler (baris crontab / ExecStart unit)
# supaya satu berkas kunci melindungi kedua cara penjadwalan.

set -u

# Lokasi kerja dihitung dari letak skrip, bukan cwd pemanggil.
BASE=$(cd "$(dirname "$0")" && pwd)
TUGAS_SRC="${TUGAS_SRC:-$BASE/sumber}"
TUGAS_DEST="${TUGAS_DEST:-$BASE/mirror}"
TUGAS_LOG="${TUGAS_LOG:-$BASE/log/tugas.log}"
STAMP="${STAMP:-$(date +%Y%m%dT%H%M%S)}"

DRY_RUN=0
VERBOSE=0
for arg in "$@"; do
    case $arg in
        --dry-run) DRY_RUN=1 ;;
        --verbose) VERBOSE=1 ;;
        *)
            printf 'tugas.sh: opsi tidak dikenal: %s\n' "$arg" >&2
            printf 'pemakaian: tugas.sh [--dry-run] [--verbose]\n' >&2
            exit 1
            ;;
    esac
done

# waktu() : bentuk terbaca dari STAMP untuk baris-ringkasan di stdout.
waktu() {
    printf '%s-%s-%s %s:%s:%s' \
        "${STAMP:0:4}" "${STAMP:4:2}" "${STAMP:6:2}" \
        "${STAMP:9:2}" "${STAMP:11:2}" "${STAMP:13:2}"
}

# Siapkan folder log sebelum bisa mencatat apa pun.
mkdir -p "$(dirname "$TUGAS_LOG")"
SECONDS=0

# --- 1. Validasi sumber --------------------------------------------------
if [ ! -d "$TUGAS_SRC" ]; then
    printf '%s|GAGAL|keluar=2|durasi=%ds|sumber tidak ditemukan: %s\n' \
        "$STAMP" "${TUGAS_DURASI:-$SECONDS}" "$TUGAS_SRC" >> "$TUGAS_LOG"
    printf 'tugas.sh: folder sumber tidak ditemukan: %s\n' "$TUGAS_SRC" >&2
    exit 2
fi

# --- 2. Sinkronisasi rsync ------------------------------------------------
# --itemize-changes membuat rsync mencetak satu baris per perubahan
# (">f..." berkas dipindah, "*deleting" berkas dihapus); baris itulah
# yang dihitung menjadi ringkasan.
Opsi=(-a --delete --itemize-changes)
[ "$DRY_RUN" -eq 1 ] && Opsi+=(--dry-run)

if ! ubah=$(rsync "${Opsi[@]}" "$TUGAS_SRC/" "$TUGAS_DEST/"); then
    printf '%s|GAGAL|keluar=3|durasi=%ds|rsync gagal\n' \
        "$STAMP" "${TUGAS_DURASI:-$SECONDS}" >> "$TUGAS_LOG"
    printf 'tugas.sh: rsync gagal\n' >&2
    exit 3
fi

total=$(find "$TUGAS_SRC" -type f | wc -l)
pindah=$(printf '%s\n' "$ubah" | grep -c '^[<>]f' || true)
hapus=$(printf '%s\n' "$ubah" | grep -c '^\*deleting' || true)

# --- 3. Dry-run: pratinjau tanpa mengubah apa pun, termasuk log -----------
if [ "$DRY_RUN" -eq 1 ]; then
    printf '[%s] dry-run: %s -> %s\n' "$(waktu)" "$TUGAS_SRC" "$TUGAS_DEST"
    [ -n "$ubah" ] && printf '%s\n' "$ubah"
    printf '[%s] tidak ada yang diubah (dry-run)\n' "$(waktu)"
    exit 0
fi

# --- 4. Catat log terstruktur + ringkasan ---------------------------------
printf '%s|OK|keluar=0|durasi=%ds|total=%d|pindah=%d|hapus=%d\n' \
    "$STAMP" "${TUGAS_DURASI:-$SECONDS}" "$total" "$pindah" "$hapus" >> "$TUGAS_LOG"

printf '[%s] mulai sinkronisasi: %s -> %s\n' "$(waktu)" "$TUGAS_SRC" "$TUGAS_DEST"
[ "$VERBOSE" -eq 1 ] && [ -n "$ubah" ] && printf '%s\n' "$ubah"
printf '[%s] %d berkas diperiksa, %d dipindah, %d dihapus\n' \
    "$(waktu)" "$total" "$pindah" "$hapus"
printf '[%s] selesai: OK (%d detik)\n' "$(waktu)" "${TUGAS_DURASI:-$SECONDS}"
exit 0
