#!/usr/bin/env bash
set -euo pipefail

REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
HOMELAB_STATE_DIR="${HOMELAB_STATE_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/homelab}"
KUBECONFIG="${KUBECONFIG:-${KUBECONFIG_PATH:-${HOME}/.kube/config}}"

section() {
    printf '\n== %s ==\n' "$1"
}

check_file() {
    local label="$1"
    local path="$2"

    printf '%-34s ' "${label}"
    if [[ -s "${path}" ]]; then
        printf 'ok - %s\n' "${path}"
    else
        printf 'fail - missing or empty: %s\n' "${path}"
        return 1
    fi
}

latest_file() {
    local directory="$1"
    local glob="$2"

    find "${directory}" -maxdepth 1 -type f -name "${glob}" -print0 2>/dev/null |
        xargs -0 ls -t 2>/dev/null |
        sed -n '1p'
}

drill_gitea() {
    local backup_dir="${LAB_GITEA_BACKUP_DIR:-/home/jv/backups/gitea}"
    local latest

    section "Gitea Restore Drill"
    latest="$(latest_file "${backup_dir}" 'gitea-*.zip' || true)"
    if [[ -z "${latest}" ]]; then
        printf 'fail - no Gitea backup archive found in %s\n' "${backup_dir}"
        return 1
    fi

    python3 - "${latest}" <<'PY'
import sys
import zipfile

archive = sys.argv[1]
with zipfile.ZipFile(archive) as handle:
    bad = handle.testzip()
    if bad:
        raise SystemExit(f"fail - corrupt archive member: {bad}")
    members = handle.namelist()
    if not members:
        raise SystemExit("fail - archive is empty")
print(f"ok - archive valid: {archive} ({len(members)} members)")
PY
}

drill_pihole() {
    section "Pi-hole Restore Drill"
    check_file "adlists" "${REPO_ROOT}/infra/rpi-services/adlists.txt"
    check_file "local DNS records" "${REPO_ROOT}/infra/rpi-services/local-dns-records.txt"
    check_file "CNAME records" "${REPO_ROOT}/infra/rpi-services/cname-records.txt"
    check_file "static DHCP notes" "${REPO_ROOT}/infra/rpi-services/static-dhcp-hosts.txt"
    check_file "RPi compose" "${REPO_ROOT}/infra/rpi-services/docker-compose.yml"
    check_file "RPi bootstrap" "${REPO_ROOT}/infra/rpi-services/bootstrap.sh"
}

drill_state() {
    local backup_dir="${HOMELAB_TOFU_STATE_BACKUP_DIR:-${HOMELAB_STATE_DIR}/tofu-state-backups}"
    local latest

    section "Jeannie/OpenTofu State Restore Drill"
    latest="$(latest_file "${backup_dir}" 'tofu-state-*.tgz' || true)"
    if [[ -z "${latest}" ]]; then
        printf 'warn - no local OpenTofu state backup archive found in %s\n' "${backup_dir}"
        printf 'hint - run ./jeannie state-backup after important changes\n'
        return 0
    fi
    tar -tzf "${latest}" >/dev/null
    printf 'ok - state archive can be listed: %s\n' "${latest}"
}

drill_gitops() {
    section "GitOps Rebuild Drill"
    git -C "${REPO_ROOT}" status --short
    git -C "${REPO_ROOT}" rev-parse --verify HEAD >/dev/null
    printf 'ok - repository HEAD: %s\n' "$(git -C "${REPO_ROOT}" rev-parse --short HEAD)"

    if command -v kubectl >/dev/null 2>&1 && [[ -s "${KUBECONFIG}" ]]; then
        kubectl --kubeconfig "${KUBECONFIG}" -n argocd get applications.argoproj.io 2>/dev/null || true
    else
        printf 'info - kubeconfig unavailable; skipping Argo CD application list\n'
    fi
}

usage() {
    cat <<'EOF'
Usage: scripts/restore-drill {all|gitea|pihole|state|gitops}

Read-only restore drills. These checks prove that restore inputs exist and can
be inspected, but they do not replace running services or mutate Kubernetes.
EOF
}

main() {
    case "${1:-all}" in
        all)
            drill_gitea
            drill_pihole
            drill_state
            drill_gitops
            ;;
        gitea)
            drill_gitea
            ;;
        pihole)
            drill_pihole
            ;;
        state)
            drill_state
            ;;
        gitops)
            drill_gitops
            ;;
        -h | --help | help)
            usage
            ;;
        *)
            usage >&2
            return 2
            ;;
    esac
}

main "$@"
