#!/usr/bin/env bash

set -euo pipefail

project_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
source_config_path="$project_root/config/dot/quickshell"
quicksettings_path="$source_config_path/modules/quicksettings"
state_home="$(mktemp -d /tmp/panama-control-center-ui.XXXXXX)"
config_path="$state_home/quickshell"
helper_log="$state_home/home-helper.log"
shell_log="$state_home/quickshell.log"

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

qs_for_test() {
    QS_CONFIG_PATH="$config_path" XDG_STATE_HOME="$state_home" \
        QS_DISABLE_CRASH_HANDLER=1 \
        PANAMA_HOME_HELPER_LOG="$helper_log" \
        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 quicksettings close >/dev/null 2>&1 || true
    qs_for_test ipc call kdeconnect reset >/dev/null 2>&1 || true
    qs_for_test ipc call home-assistant reset >/dev/null 2>&1 || true
    if stop_test_shell; then
        rm -rf "$state_home"
    else
        printf 'Control Center 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 quicksettings$' >/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'
}

rg -Fq 'readonly property int controlCenterWidth: 430' \
    "$source_config_path/config/Theme.qml" \
    || fail 'approved Control Center width is missing'
rg -Fq 'readonly property int controlCenterTopGap: 2' \
    "$source_config_path/config/Theme.qml" \
    || fail 'approved top attachment is missing'
rg -Fq 'margins.top: Theme.barHeight + Theme.controlCenterTopGap' \
    "$quicksettings_path/QuickSettings.qml" \
    || fail 'Control Center is not tightly attached to the bar'
rg -Fq 'implicitWidth: Theme.controlCenterWidth' \
    "$quicksettings_path/QuickSettings.qml" \
    || fail 'Control Center window does not use its geometry token'
rg -Fq 'HomeControls' \
    "$quicksettings_path/QuickSettingsPanel.qml" \
    || fail 'Home controls are not mounted'
rg -Fq 'PhoneControls' \
    "$quicksettings_path/QuickSettingsPanel.qml" \
    || fail 'Phone controls are not mounted'
rg -Fq 'visible: KdeConnect.phoneReachable' \
    "$source_config_path/modules/bar/StatusCluster.qml" \
    || fail 'reachable phone state is absent from the bar'

for component in ControlSectionHeader HomeBrightnessSlider HomeControls HomeTile PhoneActions PhoneControls RecentExchange; do
    [[ -f "$quicksettings_path/$component.qml" ]] \
        || fail "$component is missing"
done

[[ "$(rg -c 'id: "(share|clipboard|ring|messages)"' "$quicksettings_path/PhoneActions.qml")" -eq 4 ]] \
    || fail 'Phone controls do not expose four stable action models'
rg -Fq 'columns: 4' "$quicksettings_path/PhoneControls.qml" \
    || fail 'Phone actions are not arranged in four equal columns'
if rg -Fq '.filter(' "$quicksettings_path/PhoneActions.qml"; then
    fail 'Phone action columns change when a KDE capability is unavailable'
fi
rg -Fq 'SystemSettings.bluebubblesAvailable' "$quicksettings_path/PhoneControls.qml" \
    || fail 'Messages action is not independently enabled by BlueBubbles'
rg -Fq 'KdeConnect.phoneReachable' "$quicksettings_path/PhoneControls.qml" \
    || fail 'KDE action reachability behavior is missing'

[[ -f "$quicksettings_path/qmldir" ]] \
    || fail 'quick-settings module manifest is missing'
rg -Fq 'HomeBrightnessSlider 1.0 HomeBrightnessSlider.qml' \
    "$quicksettings_path/qmldir" \
    || fail 'brightness slider is not registered in the quick-settings module'
rg -Fq 'PhoneActions 1.0 PhoneActions.qml' \
    "$quicksettings_path/qmldir" \
    || fail 'Phone actions model is not registered in the quick-settings module'

[[ "$(rg -c '^[[:space:]]*columns: 2$' "$quicksettings_path/HomeControls.qml")" -ge 2 ]] \
    || fail 'resting and expanded Home shelves are not both two-column grids'
rg -Fq 'model: HomeAssistant.visibleEntities' "$quicksettings_path/HomeControls.qml" \
    || fail 'resting Home shelf does not use the first four selected lights'
rg -Fq 'model: HomeAssistant.selectedEntities' "$quicksettings_path/HomeControls.qml" \
    || fail 'expanded Home shelf does not use every selected light'
rg -Fq 'HomeAssistant.pendingFor(' "$quicksettings_path/HomeControls.qml" \
    || fail 'Home tiles do not receive per-light pending brightness'
rg -Fq 'HomeAssistant.setBrightness(' "$quicksettings_path/HomeControls.qml" \
    || fail 'Home brightness commits are not wired to the service'
rg -Fq 'ShellState.openSettings("home-phone")' "$quicksettings_path/HomeControls.qml" \
    || fail 'Manage in Settings does not open Home & Phone'

rg -Fq 'signal previewChanged(int value)' "$quicksettings_path/HomeBrightnessSlider.qml" \
    || fail 'brightness slider has no preview contract'
rg -Fq 'signal committed(int value)' "$quicksettings_path/HomeBrightnessSlider.qml" \
    || fail 'brightness slider has no release-commit contract'
rg -Fq 'onReleased: event =>' "$quicksettings_path/HomeBrightnessSlider.qml" \
    || fail 'brightness slider does not route pointer release through its interaction state'
rg -Fq 'root.releasePointerInteraction();' "$quicksettings_path/HomeBrightnessSlider.qml" \
    || fail 'brightness slider release is not wired to one-shot commit semantics'
rg -Fq 'onCanceled: root.cancelPointerInteraction()' "$quicksettings_path/HomeBrightnessSlider.qml" \
    || fail 'brightness slider does not restore its external value when a Flickable steals the pointer'
if rg -Fq 'preventStealing: true' "$quicksettings_path/HomeBrightnessSlider.qml"; then
    fail 'brightness slider blocks the expanded shelf from stealing vertical drags'
fi
rg -Fq 'onWheel:' "$quicksettings_path/HomeBrightnessSlider.qml" \
    || fail 'brightness slider has no wheel commit path'
rg -Fq 'onCommitted: value => root.brightnessRequested(value)' "$quicksettings_path/HomeTile.qml" \
    || fail 'Home tile does not forward the slider release commit'
rg -Fq 'accessibleName: root.entity.name + " brightness"' "$quicksettings_path/HomeTile.qml" \
    || fail 'Home tile does not give its dimmer an accessory-specific accessible name'

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

printf '%s\n' "$*" >>"$PANAMA_HOME_HELPER_LOG"
case "${1:-}" in
    catalog)
        printf '%s\n' '{"ok":false,"configured":false,"entities":[],"legacyEntityIds":[],"error":"test-helper"}'
        ;;
    toggle|brightness)
        printf '%s\n' '{"ok":false,"error":"contract-action-forbidden"}'
        exit 73
        ;;
esac
EOF
chmod +x "$config_path/scripts/panama-home-assistant"

start_test_shell

qs_for_test ipc call home-assistant fixture ready >/dev/null
home_ready="$(qs_for_test ipc call home-assistant status)"
jq -e '.fixture == true and .visibleCount == 4 and .configuredCount == 7' \
    <<<"$home_ready" >/dev/null \
    || fail 'Home fixture does not expose four resting and seven expanded accessories'

qs_for_test ipc call kdeconnect fixture reachable >/dev/null
qs_for_test ipc call quicksettings open >/dev/null

hyprctl layers | rg -q 'namespace: qs-popover-quicksettings' \
    || fail 'Control Center layer did not map'
jq -e '.open == true and .expandedSection == ""' \
    <<<"$(qs_for_test ipc call quicksettings status)" >/dev/null \
    || fail 'Control Center did not open in its resting state'

qs_for_test ipc call quicksettings section home >/dev/null
jq -e '.open == true and .expandedSection == "home"' \
    <<<"$(qs_for_test ipc call quicksettings status)" >/dev/null \
    || fail 'Home section did not expand'

qs_for_test ipc call quicksettings section phone >/dev/null
jq -e '.open == true and .expandedSection == "phone"' \
    <<<"$(qs_for_test ipc call quicksettings status)" >/dev/null \
    || fail 'Phone did not replace Home as the expanded section'

qs_for_test ipc call quicksettings section phone >/dev/null
jq -e '.open == true and .expandedSection == ""' \
    <<<"$(qs_for_test ipc call quicksettings status)" >/dev/null \
    || fail 'expanded Phone section did not collapse'

if rg '^(toggle|brightness)( |$)' "$helper_log" >&2; then
    fail 'Control Center contract attempted a real Home action path'
fi

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