#!/usr/bin/env bash
# Desktop-only adaptation of ViegPhunt's dotfiles, hosted on 89.35.130.196.
set -Eeuo pipefail

BASE_URL='https://89-35-130-196.sslip.io/hyprland-setup'
BUNDLE_SHA256='637d8324fb673bb9e929ff27c214cbc7f06f233587b397ae64802a43899add78'
PACKAGES=(
    hyprland hyprlock hyprpolkitagent awww waybar swaync rofi rofi-emoji
    grim slurp hyprshot wl-clipboard cliphist yad
    xdg-desktop-portal-hyprland xdg-desktop-portal-gtk xdg-utils
    ghostty nemo gvfs firefox pavucontrol libpulse brightnessctl playerctl
    network-manager-applet blueman bluez bluez-utils
    qt5ct qt6ct qt5-wayland qt6-wayland
    ttf-jetbrains-mono-nerd noto-fonts noto-fonts-emoji fontconfig
    adw-gtk-theme adwaita-cursors papirus-icon-theme gsettings-desktop-schemas
    libvips cava psmisc
)
TARGETS=(
    .config/colors .config/fontconfig .config/ghostty .config/cava
    .config/rofi .config/swaync .config/waybar .config/viegphunt
    .config/gtk-3.0/settings.ini .config/gtk-4.0/settings.ini
    .local/share/icons/default/index.theme Pictures/Wallpapers/ViegPhunt
    .config/hypr
)
WORK=''
BACKUP=''
APPLYING=0

usage() {
    cat <<'HELP'
ViegPhunt desktop style for an installed Arch Linux x86_64 system.
Usage: bash install.sh [--check | --help]

Run WITHOUT sudo as your desktop user. The installer asks for confirmation and
uses sudo only for official Arch packages (including a full system upgrade).
It installs Hyprland, Waybar, Rofi, Ghostty, fonts, GTK theme and 8 wallpapers.
No AUR, repartitioning, shell/locale changes, driver selection, service enabling,
SDDM replacement, automatic logout or reboot. US/RU keyboard: Alt+Shift.
Icons/cursor/power menu differ from the original to avoid AUR builds.
Config replacements are backed up under ~/.local/state/hyprland-style/backups/.
Backup/restore covers the replaced files, NOT pacman package transactions.

--check downloads, verifies and checks the bundle without changing the desktop
or installing packages; also works on a non-Arch host.
Requires a working Internet connection, curl, tar, Bash and (for install) sudo.
HELP
}

cleanup() {
    local status=$?
    trap - EXIT
    if (( APPLYING )); then
        printf '\nInstallation interrupted; restoring previous configs.\n' >&2
        if ! bash "$BACKUP/restore.sh" --yes; then
            printf 'Automatic restore FAILED. Use backup: %s\n' "$BACKUP" >&2
        fi
    fi
    if [[ -n $WORK && -d $WORK ]]; then rm -rf -- "$WORK"; fi
    if (( status != 0 )); then
        printf '\nStopped with error %s. Do not assume installation completed.\n' "$status" >&2
        [[ -z $BACKUP ]] || printf 'Backup: %s\n' "$BACKUP" >&2
    fi
    exit "$status"
}

fetch_bundle() {
    WORK=$(mktemp -d)
    curl --proto '=https' --tlsv1.2 -fL --retry 3 --connect-timeout 20 --max-time 600 \
        "$BASE_URL/desktop-v1.tar.gz" -o "$WORK/desktop-v1.tar.gz"
    printf '%s  %s\n' "$BUNDLE_SHA256" "$WORK/desktop-v1.tar.gz" | sha256sum --check --status
    mkdir "$WORK/payload"
    tar --no-same-owner --no-same-permissions -xzf "$WORK/desktop-v1.tar.gz" -C "$WORK/payload"
    local relative script
    for relative in "${TARGETS[@]}"; do
        [[ -e "$WORK/payload/$relative" ]] || { echo "Missing bundle file: $relative" >&2; return 1; }
    done
    for script in "$WORK/payload/.config/viegphunt/"*.sh; do bash -n "$script"; done
    [[ -s "$WORK/payload/Pictures/Wallpapers/ViegPhunt/fishing.jpg" ]]
    printf '%s\n' 'Bundle checksum, required paths and shell syntax: OK.'
}

backup_configs() {
    local relative target
    mkdir -p "$HOME/.local/state/hyprland-style/backups"
    BACKUP=$(mktemp -d "$HOME/.local/state/hyprland-style/backups/$(date +%Y%m%d-%H%M%S)-XXXXXX")
    mkdir "$BACKUP/originals" "$BACKUP/replaced"
    : > "$BACKUP/paths.txt"
    for relative in "${TARGETS[@]}"; do
        target="$HOME/$relative"
        if [[ -e $target || -L $target ]]; then
            mkdir -p "$BACKUP/originals/$(dirname "$relative")"
            cp -a -- "$target" "$BACKUP/originals/$relative"
        fi
        printf '%s\n' "$relative" >> "$BACKUP/paths.txt"
    done
    cat > "$BACKUP/restore.sh" <<'RESTORE'
#!/usr/bin/env bash
set -euo pipefail
(( EUID != 0 )) || { echo 'Run restore as your desktop user, WITHOUT sudo.' >&2; exit 1; }
backup=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)
[[ ! -e "$backup/RESTORED" ]] || { echo 'This backup has already been restored.' >&2; exit 1; }
if [[ ${1:-} != --yes ]]; then
    echo 'Restore the saved configs? Current configs will also be saved. Type RESTORE:'
    read -r answer
    [[ $answer == RESTORE ]] || exit 1
fi
saved=$(mktemp -d "$backup/before-restore-XXXXXX")
while IFS= read -r relative; do
    case "$relative" in
        ''|/*|*..*) echo 'Unsafe backup manifest.' >&2; exit 1 ;;
    esac
    target="$HOME/$relative"
    if [[ -e $target || -L $target ]]; then
        mkdir -p "$saved/$(dirname "$relative")"
        mv -- "$target" "$saved/$relative"
    fi
    original="$backup/originals/$relative"
    if [[ -e $original || -L $original ]]; then
        mkdir -p "$(dirname "$target")"
        cp -a -- "$original" "$target"
    fi
done < "$backup/paths.txt"
touch "$backup/RESTORED"
printf 'Configs restored. Re-enter Hyprland. Previous new configs: %s\n' "$saved"
echo 'Installed/upgraded packages have not been removed or downgraded.'
RESTORE
    chmod 700 "$BACKUP/restore.sh"
    printf 'Backup: %s\nRestore: bash %q\n' "$BACKUP" "$BACKUP/restore.sh"
}

apply_configs() {
    local relative target
    APPLYING=1
    for relative in "${TARGETS[@]}"; do
        target="$HOME/$relative"
        mkdir -p "$(dirname "$target")"
        if [[ -e $target || -L $target ]]; then
            mkdir -p "$BACKUP/replaced/$(dirname "$relative")"
            mv -- "$target" "$BACKUP/replaced/$relative"
        fi
        cp -a -- "$WORK/payload/$relative" "$target"
    done
    APPLYING=0
}

main() {
    local mode=${1:-install} answer log_file
    case "$mode" in
        --help|-h) usage; return 0 ;;
        --check|install) ;;
        *) usage >&2; return 2 ;;
    esac
    (( $# <= 1 )) || { usage >&2; return 2; }
    if [[ $mode == install ]]; then
        [[ -f /etc/arch-release ]] || { echo 'Installation requires Arch Linux; this host is not Arch.' >&2; return 1; }
        (( EUID != 0 )) || { echo 'Run WITHOUT sudo as your normal desktop user.' >&2; return 1; }
        [[ $(uname -m) == x86_64 ]] || { echo 'Only Arch x86_64 is supported.' >&2; return 1; }
        [[ ${XDG_CONFIG_HOME:-$HOME/.config} == "$HOME/.config" ]] || {
            echo 'Custom XDG_CONFIG_HOME is not supported by these upstream dotfiles.' >&2; return 1;
        }
        command -v sudo >/dev/null || { echo 'sudo is required.' >&2; return 1; }
        command -v pacman >/dev/null
        command -v flock >/dev/null
        [[ -t 0 ]] || { echo 'Download the file and run it in a terminal; do not pipe into bash.' >&2; return 1; }
    fi
    trap cleanup EXIT
    trap 'exit 130' INT
    trap 'exit 143' TERM
    if [[ $mode == --check ]]; then
        fetch_bundle
        echo 'Check only: no packages installed and no desktop files modified.'
        return 0
    fi
    umask 077
    mkdir -p "$HOME/.local/state/hyprland-style"
    exec 9> "$HOME/.local/state/hyprland-style/install.lock"
    flock -n 9 || { echo 'Another installation is running.' >&2; return 1; }
    log_file="$HOME/.local/state/hyprland-style/install-$(date +%Y%m%d-%H%M%S).log"
    exec > >(tee -a "$log_file") 2>&1
    usage
    echo
    echo 'Existing configs for the listed desktop components will be REPLACED.'
    echo 'Save your work. Run from a TTY (Ctrl+Alt+F3) if possible.'
    echo 'A full Arch package upgrade will be performed; allow enough disk space.'
    echo 'Type INSTALL to continue:'
    read -r answer
    [[ $answer == INSTALL ]] || { echo 'Cancelled; desktop unchanged.'; return 0; }
    sudo -v
    fetch_bundle
    backup_configs
    # Install/upgrade in one transaction, avoiding a partially upgraded Arch system.
    # Do not replace an existing PulseAudio/PipeWire setup.
    if ! pacman -Q pipewire-pulse >/dev/null 2>&1 && ! pacman -Q pulseaudio >/dev/null 2>&1; then
        PACKAGES+=(pipewire pipewire-pulse wireplumber)
    fi
    sudo pacman -Syu --needed --noconfirm "${PACKAGES[@]}"
    apply_configs
    fc-cache -f
    echo
    echo 'Files installed. Log out and select Hyprland at the login screen.'
    echo 'If there is no login manager, run start-hyprland (or Hyprland) from a TTY.'
    echo 'Runtime appearance and GPU compatibility still need checking in your session.'
    echo 'Win+Space: terminal | Alt+Space: apps | Win+W: wallpapers | Win+H: help'
    echo 'Alt+Shift: US/RU keyboard. No automatic reboot or logout.'
    printf 'Restore configs: bash %q\nLog: %s\n' "$BACKUP/restore.sh" "$log_file"
}

if [[ ${BASH_SOURCE[0]} == "$0" ]]; then main "$@"; fi
