#!/bin/bash
set -euo pipefail

# Small helper for pacnew-checker executed via pkexec as root.
# Usage: pacnew-helper.sh <merge|remove|replace> <file> [<target>] [<caller_uid> <DISPLAY> <DBUS_SESSION_BUS_ADDRESS> <XAUTHORITY>]
# - merge <file>               : launches meld as root but in the caller's graphical session (so GTK/GSettings work)
# - remove <file>              : remove the pacnew/pacsave file (runs as root)
# - replace <file> <target>    : move <file> to <target> (runs as root)
#
# Only operates on absolute paths under /etc and refuses critical files.

if [[ "$(id -u)" -ne 0 ]]; then
    echo "This helper must be run as root (via pkexec)." >&2
    exit 1
fi

if [[ $# -lt 2 ]]; then
    echo "Usage: $0 <merge|remove|replace> <file> [<target>] [<caller_uid> <DISPLAY> <DBUS_SESSION_BUS_ADDRESS> <XAUTHORITY>]" >&2
    exit 2
fi

action="$1"
file="$2"
target="${3:-}"
caller_uid="${4:-}"
caller_display="${5:-}"
caller_dbus="${6:-}"
caller_xauth="${7:-}"

# Resolve and validate path
if ! realpath=$(readlink -f -- "$file"); then
    echo "Invalid path" >&2
    exit 3
fi

# Restrict to /etc
case "$realpath" in
    /etc/*) ;;
    *)
        echo "Refusing to operate on non-/etc path: $realpath" >&2
        exit 4
        ;;
esac

# Reject critical files and their pacnew/pacsave forms
case "$realpath" in
    /etc/passwd|/etc/passwd.*|/etc/shadow|/etc/shadow.*|/etc/gshadow|/etc/group)
        echo "Operation on critical system files is disallowed: $realpath" >&2
        exit 5
        ;;
esac

orig="${realpath%.*}"
suffix="${realpath##*.}"

logger -t pacnew-helper "action=$action file=$realpath target=$target invoked by UID=$(id -u) caller_uid=$caller_uid display=${caller_display:-unset} dbus=${caller_dbus:+set} xauth=${caller_xauth:+set}"

case "$action" in
    merge)
        if [[ ! -x /usr/bin/meld ]]; then
            echo "meld not found" >&2
            exit 6
        fi

        # If caller session info provided, run meld AS ROOT but with caller's env so GTK/GSettings/DBus work
        if [[ -n "$caller_display" ]]; then
            env_cmd=( )
            env_cmd+=( "DISPLAY=${caller_display}" )
            if [[ -n "$caller_dbus" ]]; then
                env_cmd+=( "DBUS_SESSION_BUS_ADDRESS=${caller_dbus}" )
            fi
            if [[ -n "$caller_xauth" ]]; then
                env_cmd+=( "XAUTHORITY=${caller_xauth}" )
            fi

            # Run meld as root with the user's graphical env (so it can display in user's session and read GSettings).
            # Root can open files directly, so use admin-free file paths.
            env "${env_cmd[@]}" /usr/bin/meld "${orig}" "${realpath}"
            exit $?
        else
            # No session info: fallback to running meld as root without extra env
            exec /usr/bin/meld "${orig}" "${realpath}"
        fi
        ;;

    remove)
        /usr/bin/rm -f -- "$realpath"
        logger -t pacnew-helper "removed $realpath"
        ;;

    replace)
        if [[ -n "$target" && "$target" != "$realpath" ]]; then
            dest=$(readlink -f -- "$target")
        else
            dest="$orig"
        fi

        case "$dest" in
            /etc/*) ;;
            *)
                echo "Refusing to move to non-/etc target: $dest" >&2
                exit 8
                ;;
        esac

        /usr/bin/mv -f -- "$realpath" "$dest"
        logger -t pacnew-helper "replaced $dest with $realpath"
        ;;

    *)
        echo "Unknown action: $action" >&2
        exit 7
        ;;
esac