#!/usr/bin/env bash
# setup.sh — bangun lingkungan development dalam satu perintah.
#
# Memeriksa toolchain inti (gcc, make, git, python3, curl), memasang
# dotfiles dari config/ dengan backup .bak untuk yang lama, lalu
# melaporkan hasilnya. Idempoten: dijalankan berapa kali pun dengan isi
# config/ yang sama, keadaan akhirnya selalu sama.
#
# Pemakaian:
#   setup.sh            periksa tool lalu pasang dotfiles
#   setup.sh --check    dry-run: laporan saja, tidak mengubah apa pun
#
# Variabel lingkungan (berguna untuk pengujian):
#   DEV_HOME  folder home tujuan pemasangan (default: $HOME)
#   DEV_SRC   folder config berisi dotfile  (default: <skrip>/../config)
#
# Kode keluar:
#   0 sukses                        1 opsi tidak dikenal
#   2 config/ tidak ditemukan       3 tool inti hilang/terlalu tua

set -u

MODE=pasang
for arg in "$@"; do
    case $arg in
        --check) MODE=cek ;;
        *)
            printf 'setup.sh: opsi tidak dikenal: %s\n' "$arg" >&2
            printf 'pemakaian: setup.sh [--check]\n' >&2
            exit 1
            ;;
    esac
done

BASE=$(cd "$(dirname "$0")" && pwd)
DEV_SRC="${DEV_SRC:-$BASE/../config}"
DEV_HOME="${DEV_HOME:-$HOME}"

if [ ! -d "$DEV_SRC" ]; then
    printf 'setup.sh: folder config tidak ditemukan: %s\n' "$DEV_SRC" >&2
    exit 2
fi

if [ "$MODE" = cek ]; then
    printf 'mode --check: laporan saja, tidak ada yang diubah\n'
fi

# --- tool inti: nama:versi-minimum ---------------------------------------
DAFTAR_TOOL="gcc:10.0 make:4.0 git:2.30 python3:3.8 curl:7.70"

# versi_cukup <versi> <minimum>: keluar 0 bila versi >= minimum.
# Hanya major.minor yang dibandingkan — patch tidak menentukan layak/tidak.
versi_cukup() {
    awk -v v="$1" -v m="$2" 'BEGIN {
        split(v, a, "."); split(m, b, ".");
        if (a[1] + 0 < b[1] + 0) exit 1;
        if (a[1] + 0 == b[1] + 0 && a[2] + 0 < b[2] + 0) exit 1;
    }'
}

# versi_tool <nama>: cetak nomor versi untuk tool yang dikenal.
versi_tool() {
    case $1 in
        gcc)     gcc -dumpfullversion ;;
        make)    make --version | sed -n '1s/^GNU Make //p' ;;
        git)     git --version | sed -n 's/^git version //p' ;;
        python3) python3 --version | sed -n 's/^Python //p' ;;
        curl)    curl --version | awk 'NR==1 {print $2}' ;;
        *)       printf '0' ;;
    esac
}

# cek_tool <nama> <minimum>: laporan satu baris + usul instalasi bila hilang.
#   exit 0 siap, 1 hilang, 2 versi terlalu tua.
cek_tool() {
    nama=$1
    min=$2
    if ! jalur=$(command -v "$nama" 2>/dev/null); then
        printf '[HILANG] %-8s tidak ditemukan\n' "$nama"
        printf '         usul: sudo apt-get install %s\n' "$nama"
        return 1
    fi
    versi=$(versi_tool "$nama")
    if versi_cukup "$versi" "$min"; then
        printf '[OK]     %-8s versi %s (minimum %s) — %s\n' \
            "$nama" "$versi" "$min" "$jalur"
        return 0
    fi
    printf '[TUA]    %-8s versi %s di bawah minimum %s\n' \
        "$nama" "$versi" "$min"
    return 2
}

# --- tahap 1: periksa tool ------------------------------------------------
printf '== tahap 1: tool development ==\n'
hilang=0
# shellcheck disable=SC2086  # daftar tool memang dipisah spasi
for item in $DAFTAR_TOOL; do
    nama=${item%%:*}
    min=${item#*:}
    cek_tool "$nama" "$min" || hilang=$((hilang + 1))
done
# shellcheck disable=SC2086
printf 'ringkasan: %d tool diperiksa, %d bermasalah\n' \
    "$(printf '%s\n' $DAFTAR_TOOL | wc -w)" "$hilang"

# --- tahap 2: pasang dotfiles ----------------------------------------------
# pasang_dotfile <sumber> <target>: salin dengan backup; idempoten.
pasang_dotfile() {
    sumber=$1
    target=$2
    if [ -f "$target" ] && cmp -s "$sumber" "$target"; then
        printf '[OK]     %s sudah terpasang\n' "$target"
        return 0
    fi
    if [ "$MODE" = cek ]; then
        printf '[BARU]   %s akan dipasang\n' "$target"
        return 0
    fi
    if [ -f "$target" ]; then
        cp "$target" "$target.bak"
        printf '[BAK]    %s -> %s.bak\n' "$target" "$target"
    fi
    cp "$sumber" "$target"
    printf '[PASANG] %s\n' "$target"
}

# pasang_hook_bashrc: pastikan ~/.bashrc memuat ~/.bashrc-dev (sekali saja).
pasang_hook_bashrc() {
    bashrc="$DEV_HOME/.bashrc"
    if [ -f "$bashrc" ] && grep -qF '.bashrc-dev' "$bashrc"; then
        printf '[OK]     %s sudah memuat .bashrc-dev\n' "$bashrc"
        return 0
    fi
    if [ "$MODE" = cek ]; then
        printf '[BARU]   hook .bashrc akan memuat .bashrc-dev\n'
        return 0
    fi
    if [ -f "$bashrc" ]; then
        cp "$bashrc" "$bashrc.bak"
        printf '[BAK]    %s -> %s.bak\n' "$bashrc" "$bashrc"
    fi
    {
        printf '\n'
        printf '# >>> lingkungan-dev: muat kustomisasi shell >>>\n'
        printf '[ -f "$HOME/.bashrc-dev" ] && . "$HOME/.bashrc-dev"\n'
        printf '# <<< lingkungan-dev <<<\n'
    } >> "$bashrc"
    printf '[PASANG] hook .bashrc memuat .bashrc-dev\n'
}

printf '== tahap 2: dotfiles ==\n'
pasang_dotfile "$DEV_SRC/.bashrc-dev"   "$DEV_HOME/.bashrc-dev"
pasang_dotfile "$DEV_SRC/.gitconfig"   "$DEV_HOME/.gitconfig"
pasang_dotfile "$DEV_SRC/.editorconfig" "$DEV_HOME/.editorconfig"
pasang_hook_bashrc

if [ "$hilang" -gt 0 ]; then
    printf 'setup.sh: selesai dengan catatan: %d tool bermasalah\n' "$hilang"
    exit 3
fi
printf 'setup.sh: selesai — lingkungan siap\n'
exit 0
