#!/usr/bin/env bash

set -euo pipefail

repo_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"

fail() {
    printf 'settings pages contract: %s\n' "$1" >&2
    exit 1
}

pages=(Home Displays Connectivity Sound Notifications ScreenIntelligence Services About)
for page in "${pages[@]}"; do
    page_file="$repo_dir/config/dot/quickshell/modules/settings/${page}Page.qml"
    [[ -f "$page_file" ]] || fail "${page}Page.qml is missing"

    root_type="$(awk '
        /^import / { next }
        /^[[:space:]]*\/\// { next }
        /^[[:space:]]*$/ { next }
        match($0, /^[[:space:]]*([A-Za-z][A-Za-z0-9]*)[[:space:]]*\{/, found) {
            print found[1]
            exit
        }
    ' "$page_file")"
    [[ "$root_type" == "SettingsPage" ]] \
        || fail "${page}Page.qml root is ${root_type:-unknown}, expected SettingsPage"
    ! rg -q '^[[:space:]]*Flickable[[:space:]]*\{' "$page_file" \
        || fail "${page}Page.qml still copies the page Flickable scaffold"
done

require_row() {
    local file="$1"
    local row_type="$2"
    local setting="$3"

    python3 - "$file" "$row_type" "$setting" <<'PY' || \
        fail "$(basename "$file") is missing $row_type for $setting"
import re
import sys

text = open(sys.argv[1], encoding="utf-8").read()
row_type = re.escape(sys.argv[2])
setting = re.escape(sys.argv[3])
pattern = rf"{row_type}\s*\{{(?:(?!\n\s*[A-Z][A-Za-z0-9]*\s*\{{).)*?setting\s*:\s*\"{setting}\""
raise SystemExit(0 if re.search(pattern, text, re.S) else 1)
PY
}

home_page="$repo_dir/config/dot/quickshell/modules/settings/HomePage.qml"
require_row "$home_page" ChoiceRow temperatureUnit
require_row "$home_page" SliderRow weatherRefreshMinutes
require_row "$home_page" SliderRow vitalsIntervalMs

notifications_page="$repo_dir/config/dot/quickshell/modules/settings/NotificationsPage.qml"
for setting in notificationTimeoutMs notificationTimeoutCriticalMs notificationHistoryLimit maxVisibleToasts; do
    require_row "$notifications_page" SliderRow "$setting"
done
python3 - "$notifications_page" <<'PY' || fail 'critical notification timeout does not render zero as Never'
import re
import sys

text = open(sys.argv[1], encoding="utf-8").read()
block = re.search(
    r'SliderRow\s*\{(?:(?!\n\s*[A-Z][A-Za-z0-9]*\s*\{).)*?'
    r'setting\s*:\s*"notificationTimeoutCriticalMs"(?P<tail>.*?)\n\s*\}',
    text,
    re.S,
)
raise SystemExit(0 if block and re.search(r'zeroLabel\s*:\s*"Never"', block.group(0)) else 1)
PY

intelligence_page="$repo_dir/config/dot/quickshell/modules/settings/ScreenIntelligencePage.qml"
require_row "$intelligence_page" ChoiceRow screenshotDir
require_row "$intelligence_page" ChoiceRow recordingDir
require_row "$intelligence_page" ChoiceRow recorderArgs

# The source-only contract is safe during a shared Quickshell quiet window.
# The existing compositor integration checks remain available explicitly.
if [[ "${PANAMA_SETTINGS_STATIC_ONLY:-0}" == "1" ]]; then
    printf 'settings pages contract: PASS (static)\n'
    exit 0
fi

state_home="$(mktemp -d /tmp/panama-settings-pages-state.XXXXXX)"
source_config_path="$repo_dir/config/dot/quickshell"
config_path="$state_home/quickshell"
test_bin="$state_home/bin"
shell_log="$state_home/quickshell.log"

cleanup_bootstrap() {
    rm -rf "$state_home"
}
trap cleanup_bootstrap EXIT

mkdir -p "$test_bin"
cp -a "$source_config_path" "$config_path"

cat >"$config_path/scripts/panama-home-assistant" <<'EOF'
#!/usr/bin/env bash
set -euo pipefail

case "${1:-}" in
    catalog)
        printf '%s\n' '{"ok":false,"error":"test-helper"}'
        ;;
    toggle|brightness)
        printf '%s\n' '{"ok":true}'
        ;;
esac
EOF
chmod +x "$config_path/scripts/panama-home-assistant"

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

if [[ "${1:-}" == "-j" && "${2:-}" == "monitors" ]]; then
    printf '%s\n' '[{"focused":true,"name":"TEST-1","description":"Settings contract","width":1920,"height":1080,"refreshRate":60,"scale":1,"currentFormat":"XRGB8888","colorManagementPreset":"srgb","vrr":false}]'
    exit 0
fi
if [[ "${1:-}" == "keyword" ]]; then
    exit 0
fi
exec /usr/sbin/hyprctl "$@"
EOF
chmod +x "$test_bin/hyprctl"

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

if [[ "${1:-}" == "info" ]]; then
    exit 1
fi
exit 97
EOF
chmod +x "$test_bin/flatpak"

qs_for_test() {
    PATH="$test_bin:$PATH" QS_CONFIG_PATH="$config_path" XDG_STATE_HOME="$state_home" \
        qs -p "$config_path" "$@"
}

stop_test_shell() {
    qs_for_test kill >/dev/null 2>&1 || true
    for _ in $(seq 1 80); do
        if ! qs_for_test list 2>/dev/null | rg '^Instance ' >/dev/null \
                && ! qs_for_test ipc show >/dev/null 2>&1; then
            return 0
        fi
        sleep 0.1
    done
    return 1
}

cleanup() {
    qs_for_test ipc call settings close >/dev/null 2>&1 || true
    if stop_test_shell; then
        rm -rf "$state_home"
    else
        printf 'settings pages contract: branch shell did not stop; retained %s\n' \
            "$state_home" >&2
    fi
}
trap cleanup EXIT

start_test_shell() {
    stop_test_shell || fail 'pre-existing branch shell did not stop cleanly'
    for _attempt in 1 2; do
        qs_for_test --daemonize >"$shell_log" 2>&1
        for _ in $(seq 1 80); do
            if qs_for_test ipc show 2>/dev/null | rg '^target settings$' >/dev/null; then
                return
            fi
            sleep 0.1
        done
        stop_test_shell || fail 'failed branch-shell attempt did not stop cleanly'
    done
    sed -n '1,200p' "$shell_log" >&2
    fail 'isolated branch shell did not start'
}

start_test_shell
qs_for_test ipc call home-assistant fixture ready >/dev/null
shell_pid="$(qs_for_test list | awk '/Process ID:/ { print $3; exit }')"
[[ "$shell_pid" =~ ^[0-9]+$ ]] || fail 'could not identify the branch shell process'

pages=(home appearance displays connectivity home-phone desktop sound notifications screen-intelligence shortcuts services about)
for page in "${pages[@]}"; do
    qs_for_test ipc call settings page "$page" >/dev/null
    for _ in $(seq 1 20); do
        [[ "$(qs_for_test ipc call settings status | jq -r .page)" == "$page" ]] && break
        sleep 0.1
    done
    [[ "$(qs_for_test ipc call settings status | jq -r .page)" == "$page" ]] || fail "$page did not route"
    /usr/sbin/hyprctl -j clients | jq -e --argjson pid "$shell_pid" \
        '[.[] | select(.pid == $pid and .title == "Panama Settings" and .floating == false)] | length == 1' >/dev/null \
        || fail "$page created a missing, floating, or duplicate Settings window"
done

qs_for_test ipc call settings page '__unsupported__' >/dev/null
[[ "$(qs_for_test ipc call settings status | jq -r .page)" == "home" ]] || fail 'unsupported page did not fall back to Home'

/usr/sbin/hyprctl -j binds | jq -e '.[] | select(.description == "Panama Settings" and .key == "I" and .modmask == 64)' >/dev/null \
    || fail 'Super+I is not registered as Panama Settings'
/usr/sbin/hyprctl -j binds | jq -e '.[] | select(.description == "Screen Intelligence" and .key == "S" and .modmask == 65)' >/dev/null \
    || fail 'Super+Shift+S is not registered as Screen Intelligence'

desktop_file="$HOME/.local/share/applications/panama-settings.desktop"
[[ -L "$desktop_file" || -f "$desktop_file" ]] || fail 'searchable desktop entry is not installed'
desktop-file-validate "$desktop_file" >/dev/null || fail 'desktop entry is invalid'
gnome_desktop_file="$HOME/.local/share/applications/gnome-settings-hyprland.desktop"
[[ -L "$gnome_desktop_file" || -f "$gnome_desktop_file" ]] || fail 'searchable GNOME Settings fallback is not installed'
desktop-file-validate "$gnome_desktop_file" >/dev/null || fail 'GNOME Settings fallback entry is invalid'
intelligence_desktop_file="$HOME/.local/share/applications/panama-screen-intelligence.desktop"
[[ -L "$intelligence_desktop_file" || -f "$intelligence_desktop_file" ]] || fail 'Screen Intelligence desktop entry is not installed'
desktop-file-validate "$intelligence_desktop_file" >/dev/null || fail 'Screen Intelligence desktop entry is invalid'

trap - EXIT
cleanup
[[ ! -e "$state_home" ]] || fail 'temporary Settings state was not removed after shell exit'
printf 'settings pages contract: PASS\n'
