#!/usr/bin/env bash

set -euo pipefail

repo_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
service="$repo_dir/config/dot/quickshell/services/Wallpaper.qml"
fixture="$(mktemp -d /tmp/panama-wallpaper-service.XXXXXX)"
config_home="$fixture/config"
state_home="$fixture/state"
config_path="$config_home/quickshell"
harness="$config_path/wallpaper-service-harness.qml"
test_bin="$fixture/bin"
command_log="$fixture/commands.log"
active_state="$fixture/active.json"
control="$fixture/control"
shell_log="$fixture/quickshell.log"
harness_pid=""

fail() {
    printf 'wallpaper service contract: %s\n' "$1" >&2
    [[ -s "$shell_log" ]] && sed -n '1,180p' "$shell_log" >&2
    exit 1
}

for needle in 'property var activeByOutput' 'function applyPolicy' 'function setSingle'; do
    rg -Fq "$needle" "$service" || fail "Wallpaper service is missing $needle"
done

instances_for_harness() {
    qs list --all 2>/dev/null | awk -v expected="$harness" '
        /^Instance / { pid = "" }
        /^[[:space:]]*Process ID:/ { pid = $3 }
        /^[[:space:]]*Config path:/ {
            path = $0
            sub(/^[[:space:]]*Config path: /, "", path)
            if (path == expected && pid ~ /^[0-9]+$/) print pid
        }
    '
}

cleanup() {
    if [[ "$harness_pid" =~ ^[0-9]+$ ]] && kill -0 "$harness_pid" 2>/dev/null; then
        kill "$harness_pid" 2>/dev/null || true
    fi
    rm -rf "$fixture"
}
trap cleanup EXIT

mkdir -p "$config_home/panama" "$state_home" "$test_bin"
cp -a "$repo_dir/config/dot/quickshell" "$config_path"
printf '%s\n' '{}' >"$config_home/panama/settings.json"
printf '%s\n' '{}' >"$active_state"
: >"$command_log"
: >"$control"

cat >"$test_bin/hyprctl" <<'EOF'
#!/usr/bin/env bash
set -euo pipefail

printf '%s' 'hyprctl' >>"$PANAMA_WALLPAPER_COMMAND_LOG"
printf ' %s' "$@" >>"$PANAMA_WALLPAPER_COMMAND_LOG"
printf '\n' >>"$PANAMA_WALLPAPER_COMMAND_LOG"

if [[ "${1:-}" == "hyprpaper" && "${2:-}" == "wallpaper" ]]; then
    request="${3:-}"
    output="${request%%,*}"
    path="${request#*,}"
    if [[ "$(<"$PANAMA_WALLPAPER_CONTROL")" == fail-second && "$output" == HDMI-A-1 ]]; then
        exit 7
    fi
    next="$(jq -c --arg output "$output" --arg path "$path" '. + {($output):$path}' \
        "$PANAMA_WALLPAPER_ACTIVE_STATE")"
    printf '%s\n' "$next" >"$PANAMA_WALLPAPER_ACTIVE_STATE"
    exit 0
fi

if [[ "${1:-}" == "hyprpaper" && "${2:-}" == "listactive" ]]; then
    if [[ "$(<"$PANAMA_WALLPAPER_CONTROL")" == wrong ]]; then
        printf 'DP-2: /images/wrong.jpg\nHDMI-A-1: /images/b.jpg\n'
        exit 0
    fi
    jq -r 'to_entries[] | "\(.key): \(.value)"' "$PANAMA_WALLPAPER_ACTIVE_STATE"
    exit 0
fi

exit 91
EOF
chmod +x "$test_bin/hyprctl"

qs_for_harness() {
    env_args=(
        XDG_CONFIG_HOME="$config_home"
        XDG_STATE_HOME="$state_home"
        PATH="$test_bin:$PATH"
        PANAMA_WALLPAPER_COMMAND_LOG="$command_log"
        PANAMA_WALLPAPER_ACTIVE_STATE="$active_state"
        PANAMA_WALLPAPER_CONTROL="$control"
    )
    if [[ "$harness_pid" =~ ^[0-9]+$ && "${1:-}" == "ipc" ]]; then
        env "${env_args[@]}" qs -p "$harness" ipc --pid "$harness_pid" "${@:2}"
    else
        env "${env_args[@]}" qs -p "$harness" "$@"
    fi
}

wait_idle() {
    local status=""
    for _ in $(seq 1 80); do
        status="$(qs_for_harness ipc call wallpaper-service-test status)"
        [[ "$(jq -r '.busy' <<<"$status")" == false ]] && { printf '%s' "$status"; return; }
        sleep 0.1
    done
    fail "wallpaper transaction did not settle: $status"
}

qs_for_harness --daemonize >"$shell_log" 2>&1 || fail 'isolated service harness did not launch'
for _ in $(seq 1 60); do
    harness_pid="$(instances_for_harness | head -1)"
    if [[ "$harness_pid" =~ ^[0-9]+$ ]] \
        && qs_for_harness ipc show 2>/dev/null | rg -q '^target wallpaper-service-test$'; then
        break
    fi
    sleep 0.1
done
[[ "$harness_pid" =~ ^[0-9]+$ ]] || fail 'isolated service harness process did not start'
wait_idle >/dev/null

: >"$command_log"
printf '%s\n' '{}' >"$active_state"
qs_for_harness ipc call wallpaper-service-test applyPerMonitor >/dev/null
success="$(wait_idle)"
expected_calls=$'hyprctl hyprpaper wallpaper DP-2,/images/a.jpg\nhyprctl hyprpaper wallpaper HDMI-A-1,/images/b.jpg\nhyprctl hyprpaper listactive'
[[ "$(<"$command_log")" == "$expected_calls" ]] || fail "transaction argv/order was wrong: $(<"$command_log")"
jq -e '.lastError == "" and .mode == "per-monitor" and .path == "/images/a.jpg"
    and .assignments == {"HDMI-A-1":"/images/b.jpg"}
    and .activeByOutput == {"DP-2":"/images/a.jpg","HDMI-A-1":"/images/b.jpg"}' \
    <<<"$success" >/dev/null || fail "verified policy was not persisted: $success"

printf 'wrong\n' >"$control"
: >"$command_log"
qs_for_harness ipc call wallpaper-service-test applySingle /images/c.jpg >/dev/null
wrong="$(wait_idle)"
jq -e '.path == "/images/a.jpg" and .mode == "per-monitor"
    and .lastError == "Hyprpaper did not confirm that background."' \
    <<<"$wrong" >/dev/null || fail "wrong readback persisted an unverified policy: $wrong"

printf 'fail-second\n' >"$control"
: >"$command_log"
qs_for_harness ipc call wallpaper-service-test applyPerMonitor >/dev/null
failed="$(wait_idle)"
jq -e '.path == "/images/a.jpg" and .mode == "per-monitor"
    and .lastError == "Hyprpaper did not apply that background."' \
    <<<"$failed" >/dev/null || fail "partial output failure changed policy: $failed"
[[ "$(tail -1 "$command_log")" == 'hyprctl hyprpaper wallpaper HDMI-A-1,/images/b.jpg' ]] \
    || fail 'transaction continued after the failed output'

printf '\n' >"$control"
printf '%s\n' '{}' >"$active_state"
: >"$command_log"
qs_for_harness ipc call wallpaper-service-test seedSlideshow \
    ' ["/images/a.jpg","/images/b.jpg","/images/c.jpg"]' false >/dev/null
seeded="$(qs_for_harness ipc call wallpaper-service-test status)"
jq -e '.slideshowTimerRunning == true and .slideshowPath == "/images/a.jpg"' \
    <<<"$seeded" >/dev/null || fail "multi-image slideshow did not arm: $seeded"
qs_for_harness ipc call wallpaper-service-test advanceSlideshow >/dev/null
advanced="$(wait_idle)"
jq -e '.mode == "slideshow" and .path == "/images/a.jpg"
    and .slideshowPath == "/images/b.jpg"
    and .activeByOutput == {"DP-2":"/images/b.jpg","HDMI-A-1":"/images/b.jpg"}' \
    <<<"$advanced" >/dev/null || fail "automatic advance persisted policy or lost runtime state: $advanced"

printf 'wrong\n' >"$control"
qs_for_harness ipc call wallpaper-service-test advanceSlideshow >/dev/null
automatic_failure="$(wait_idle)"
jq -e '.path == "/images/a.jpg" and .slideshowPath == "/images/b.jpg"
    and .slideshowTimerRunning == true
    and .lastError == "Hyprpaper did not confirm that background."' \
    <<<"$automatic_failure" >/dev/null \
    || fail "failed automatic advance changed runtime policy or stopped normal scheduling: $automatic_failure"
printf '\n' >"$control"

qs_for_harness ipc call wallpaper-service-test seedSlideshow ' ["/images/a.jpg"]' false >/dev/null
single_item="$(qs_for_harness ipc call wallpaper-service-test status)"
jq -e '.slideshowTimerRunning == false' <<<"$single_item" >/dev/null \
    || fail "one-item slideshow armed a repeating timer: $single_item"

qs_for_harness ipc call wallpaper-service-test applySingle /images/a.jpg >/dev/null
wait_idle >/dev/null
printf '%s\n' '{}' >"$active_state"
: >"$command_log"
qs_for_harness ipc call wallpaper-service-test rapidOutputs >/dev/null
sleep 0.6
hotplug="$(wait_idle)"
[[ "$(rg -c '^hyprctl hyprpaper listactive$' "$command_log")" -eq 1 ]] \
    || fail "rapid output changes did not coalesce: $(<"$command_log")"
jq -e '.lastError == "" and .activeByOutput == {"DP-2":"/images/a.jpg","HDMI-A-1":"/images/a.jpg"}' \
    <<<"$hotplug" >/dev/null || fail "hotplug reapply was not verified: $hotplug"

if rg -n 'ReferenceError|TypeError|Binding loop|Unable to assign|Cannot assign' "$shell_log"; then
    fail 'service harness emitted a QML runtime warning'
fi

printf 'wallpaper service contract: PASS\n'
