#!/usr/bin/env bash
# migrate-hyprland-to-hyprlua — switch an existing hyprland install to hyprlua
#
# Packages are identical between the two environments; this script only
# swaps configs.  Run it from inside (or outside) a live Hyprland session.
# If run from inside, Hyprland is reloaded automatically at the end.
#
# Usage:
#   ./migrate-hyprland-to-hyprlua.sh          # interactive
#   ./migrate-hyprland-to-hyprlua.sh --dry-run # preview only, no changes

set -euo pipefail

DOTFILES="${DOTFILES:-$HOME/Dotfiles}"
SRC="$DOTFILES/desktopenvs/hyprlua"
TARGET="${XDG_CONFIG_HOME:-$HOME/.config}"
BACKUP_DIR="$HOME/.config-hyprland-backup-$(date +%Y%m%d-%H%M%S)"
DRY_RUN=0

RED='\033[0;31m'; YEL='\033[1;33m'; GRN='\033[0;32m'; DIM='\033[2m'; RST='\033[0m'
err()  { printf "${RED}✖  %s${RST}\n" "$*" >&2; }
warn() { printf "${YEL}⚠  %s${RST}\n" "$*"; }
ok()   { printf "${GRN}✔  %s${RST}\n" "$*"; }
note() { printf "${DIM}   %s${RST}\n" "$*"; }
die()  { err "$*"; exit 1; }
run()  {
    if (( DRY_RUN )); then
        printf "${DIM}  [dry] %s${RST}\n" "$*"
    else
        eval "$@"
    fi
}

# ── args ──────────────────────────────────────────────────────────────────────
for arg in "$@"; do
    case "$arg" in
        --dry-run|-n) DRY_RUN=1 ;;
        --help|-h)
            echo "Usage: $0 [--dry-run]"
            echo "  --dry-run   Preview changes without applying them."
            exit 0 ;;
        *) die "Unknown argument: $arg" ;;
    esac
done

# ── preflight ─────────────────────────────────────────────────────────────────
[[ -d "$SRC" ]] || die "hyprlua source not found: $SRC"
[[ -d "$DOTFILES" ]] || die "Dotfiles directory not found: $DOTFILES"

if [[ -f "$TARGET/hypr/hyprland.lua" ]] && [[ ! -f "$TARGET/hypr/hyprland.conf" ]]; then
    warn "Already on hyprlua (hyprland.lua found, no hyprland.conf). Nothing to do."
    exit 0
fi

(( DRY_RUN )) && warn "Dry-run mode — no files will be modified."

printf '\n'
note "Source : $SRC"
note "Target : $TARGET"
note "Backup : $BACKUP_DIR"
printf '\n'

# ── backup ────────────────────────────────────────────────────────────────────
# Save the hypr-usr .conf files that will be removed from ~/.config/
HYPR_USR_CONFS=(autostart.conf binds.conf envvars.conf input.conf monitors.conf windowrules.conf)

run "mkdir -p '$BACKUP_DIR/hypr-usr' '$BACKUP_DIR/hypr'"

for f in "${HYPR_USR_CONFS[@]}"; do
    [[ -f "$TARGET/$f" ]] && run "cp '$TARGET/$f' '$BACKUP_DIR/hypr-usr/'"
done

[[ -f "$TARGET/hypr/hyprland.conf" ]] && run "cp '$TARGET/hypr/hyprland.conf' '$BACKUP_DIR/hypr/'"

ok "Backup staged at $BACKUP_DIR"

# ── swap config directories ───────────────────────────────────────────────────
# These directories are identical between hyprland and hyprlua, but we
# re-copy anyway so script paths inside them point to the correct source.
CONFIGS=(
    kitty mimeapps.list vicinae walker ulauncher
    hypr xfce4 wofi dunst alacritty
    nwg-dock-hyprland nwg-drawer nwg-panel
    scripts btop gtk-3.0
)

printf '\n'
for cfg in "${CONFIGS[@]}"; do
    src_path="$SRC/$cfg"
    dst_path="$TARGET/$cfg"
    if [[ ! -e "$src_path" ]]; then
        warn "Source missing, skipping: $cfg"
        continue
    fi
    run "rm -rf '$dst_path'"
    run "cp -r '$src_path' '$dst_path'"
    ok "config  $cfg"
done

# ── swap hypr-usr (the part that actually differs) ────────────────────────────
# hyprland: *.conf files live at ~/.config/ root (sourced by hyprland.conf)
# hyprlua:  device-specific files live at ~/.config/hypr/usr/
#           (required via require("usr.*") in hyprland.lua)

printf '\n'

# Remove old .conf files from ~/.config/ root
for f in "${HYPR_USR_CONFS[@]}"; do
    [[ -f "$TARGET/$f" ]] && run "rm '$TARGET/$f'" && note "removed ~/.config/$f"
done
# Remove wallpaper.conf from ~/.config/ root if present (old location)
[[ -f "$TARGET/wallpaper.conf" ]] && run "rm '$TARGET/wallpaper.conf'" && note "removed ~/.config/wallpaper.conf"

# Deploy device-specific files into ~/.config/hypr/usr/
if [[ -d "$SRC/hypr/usr" ]]; then
    run "mkdir -p '$TARGET/hypr/usr'"
    for f in "$SRC/hypr/usr"/*; do
        [[ -e "$f" ]] || continue
        run "cp '$f' '$TARGET/hypr/usr/'"
        ok "hypr/usr  $(basename "$f") → ~/.config/hypr/usr/"
    done
fi

# ── update config-updater ─────────────────────────────────────────────────────
printf '\n'
UPDATER_DIR="$TARGET/config-updater"
UPDATER_CONF="$UPDATER_DIR/updater.conf"
UPDATER_SCRIPT="$HOME/update-configs.sh"

run "mkdir -p '$UPDATER_DIR'"

# Re-point the symlink (or file) to hyprlua's updater.conf
if [[ -L "$UPDATER_CONF" ]] || [[ -f "$UPDATER_CONF" ]]; then
    run "rm '$UPDATER_CONF'"
fi
run "ln -sf '$SRC/config-updater/updater.conf' '$UPDATER_CONF'"
ok "config-updater → hyprlua"

# Re-point the update-configs.sh convenience symlink if it exists
if [[ -L "$UPDATER_SCRIPT" ]] || [[ -f "$UPDATER_SCRIPT" ]]; then
    run "ln -sf '$SRC/config-updater/update-configs.sh' '$UPDATER_SCRIPT'"
    ok "~/update-configs.sh → hyprlua"
fi

# ── reload Hyprland ───────────────────────────────────────────────────────────
printf '\n'
if command -v hyprctl &>/dev/null && hyprctl version &>/dev/null 2>&1; then
    ok "Hyprland session detected — reloading..."
    run "hyprctl reload"
else
    warn "Not inside a Hyprland session — start/restart Hyprland to apply changes."
fi

# ── done ──────────────────────────────────────────────────────────────────────
printf '\n'
if (( DRY_RUN )); then
    note "Dry run complete. Run without --dry-run to apply."
else
    ok "Migration complete."
    note "Rollback: restore files from $BACKUP_DIR"
    note "          and re-run ~/Dotfiles/desktopenvs/hyprland/config-updater/update-configs.sh"
fi
