package com.auto.clicker.autoclicker.service;

import android.accessibilityservice.AccessibilityService;
import android.accessibilityservice.GestureDescription;
import android.content.Intent;
import android.graphics.Path;
import android.graphics.Point;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.accessibility.AccessibilityEvent;

import androidx.localbroadcastmanager.content.LocalBroadcastManager;

import com.auto.clicker.autoclicker.data.Event;
import com.auto.clicker.autoclicker.data.EventWrapper;
import com.auto.clicker.autoclicker.data.PointEvent;
import com.auto.clicker.autoclicker.data.SlideEvent;
import com.auto.clicker.autoclicker.util.EventViewBinder;
import com.auto.clicker.autoclicker.util.ScreenUtils;
import com.auto.clicker.autoclicker.view.FloatingViewManager;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

public class AutoClickService extends AccessibilityService {
    private static final String TAG = "AutoClickService";
    private static AutoClickService instance;

    private static final long MIN_CLICK_INTERVAL = 40;
    private static final long MAX_CLICK_INTERVAL = 10000;
    private static final int MIN_CLICK_DURATION = 50;
    private static final int MAX_CLICK_DURATION = 1000;
    private static final int MIN_SLIDE_DURATION = 100;
    private static final int MAX_SLIDE_DURATION = 2000;

    private List<EventWrapper> runtimeEvents = new ArrayList<>();

    private FloatingViewManager floatingViewManager;
    private int touchPointSize;

    private final Handler handler = new Handler(Looper.getMainLooper());
    private boolean isRunning = false;

    private long clickInterval = 1000;
    private int clickDuration = 200;
    private int slideDuration = 500;
    private int currentEventIndex = 0;

    private int loopCount = 1;
    private long loopTimeMillis = 0;
    private long startTimeMillis;
    private int currentLoop = 0;

    @Override
    public void onCreate() {
        super.onCreate();
        instance = this;
        Point screenSize = ScreenUtils.getScreenSize(this);
        int screenWidth = screenSize.x;
        int screenHeight = screenSize.y;
        logDebug("屏幕尺寸: " + screenWidth + "x" + screenHeight);

        ForegroundService service = ForegroundService.getInstance();
        if (service != null) {
            floatingViewManager = service.getFloatingViewManager();
        }

        if (floatingViewManager != null) {
            touchPointSize = floatingViewManager.getTouchPointSize();
        }
    }

    public static AutoClickService getInstance() {
        return instance;
    }

    @Override
    public void onServiceConnected() {
        super.onServiceConnected();
        logDebug("无障碍服务已连接");
    }

    @Override
    public void onInterrupt() {
        stopClicking();
        logDebug("无障碍服务中断");
    }

    public void clearEvents() {
        runtimeEvents.clear();
        logDebug("清除所有事件");
    }

    public void addMultipleClickEvents(List<EventWrapper> eventWrapperList) {
        clearEvents();

        runtimeEvents = new ArrayList<>(eventWrapperList);
        logDebug("设置多点点击事件: " + eventWrapperList.size() + " 个点");
    }

    public void setClickInterval(long interval) {
        if (interval < MIN_CLICK_INTERVAL || interval > MAX_CLICK_INTERVAL) {
            Log.w(TAG, "点击间隔超出范围: " + interval + "ms");
            return;
        }
        this.clickInterval = interval;
        logDebug("设置点击间隔: " + interval + "ms");
    }

    public void setClickDuration(int duration) {
        if (duration < MIN_CLICK_DURATION || duration > MAX_CLICK_DURATION) {
            Log.w(TAG, "点击时长超出范围: " + duration + "ms");
            return;
        }
        this.clickDuration = duration;
        logDebug("设置点击时长: " + duration + "ms");
    }

    public void setSlideDuration(int duration) {
        if (duration < MIN_SLIDE_DURATION || duration > MAX_SLIDE_DURATION) {
            Log.w(TAG, "滑动时长超出范围: " + duration + "ms");
            return;
        }
        this.slideDuration = duration;
        logDebug("设置滑动时长: " + duration + "ms");
    }

    /**
     * 设置事件队列的循环次数。
     *
     * @param count 循环次数。设置为0表示无限循环，设置为1表示不循环（执行一次）。
     */
    public void setLoopCount(int count) {
        if (count < 0) {
            Log.w(TAG, "循环次数不能为负数，已设置为默认值 1");
            this.loopCount = 1;
        } else {
            this.loopCount = count;
        }
        logDebug("设置循环次数: " + loopCount + " 次");
        // 如果设置了循环次数，则重置循环时间为0，确保两种模式不冲突
        if (this.loopCount > 0) {
            this.loopTimeMillis = 0;
            logDebug("已重置循环时间为 0ms");
        }
    }

    /**
     * 设置事件队列的循环总时间。
     *
     * @param timeMillis 循环总时间，单位毫秒。设置为0表示不按时间循环。
     */
    public void setLoopTime(long timeMillis) {
        if (timeMillis < 0) {
            Log.w(TAG, "循环时间不能为负数，已设置为默认值 0ms");
            this.loopTimeMillis = 0;
        } else {
            this.loopTimeMillis = timeMillis;
        }
        logDebug("设置循环时间: " + loopTimeMillis + "ms");
        // 如果设置了循环时间，则重置循环次数为0，确保两种模式不冲突
        if (this.loopTimeMillis > 0) {
            this.loopCount = 0;
            logDebug("已重置循环次数为 0");
        }
    }

    public void startClicking() {
        if (!isRunning) {
            if (runtimeEvents.isEmpty()) {
                Log.w(TAG, "无事件队列，忽略开始");
                return;
            }

            isRunning = true;
            currentEventIndex = 0;
            currentLoop = 0; // 重置循环计数
            startTimeMillis = System.currentTimeMillis(); // 记录开始时间

            EventViewBinder.setAllTouchPointsDraggable(false);

            // 根据循环设置调整日志输出
            String loopInfo;
            if (loopCount > 0) {
                loopInfo = "循环 " + (loopCount == 1 ? "1 次" : loopCount + " 次");
            } else if (loopTimeMillis > 0) {
                loopInfo = "循环 " + (loopTimeMillis / 1000) + " 秒";
            } else {
                loopInfo = "无限循环"; // 如果两者都为0
            }
            logDebug("开始执行事件队列 - 共 " + runtimeEvents.size() + " 个事件. " + loopInfo);

            executeEventsByType();
        }
    }

    public void stopClicking() {
        if (isRunning) {
            isRunning = false;
            handler.removeCallbacksAndMessages(null);

            EventViewBinder.setAllTouchPointsDraggable(true);

            // 重置循环状态
            currentEventIndex = 0; // 停止时重置事件索引
            currentLoop = 0; // 停止时重置循环计数
            startTimeMillis = 0; // 停止时重置开始时间

            logDebug("停止执行事件");
        }
    }

    public boolean isClicking() {
        return isRunning;
    }

    private void executeEventsByType() {
        if (!isRunning) {
            logDebug("跳过执行：服务未运行");
            return;
        }

        if (runtimeEvents.isEmpty()) {
            logDebug("跳过执行：事件队列为空");
            stopClicking(); // 如果事件队列为空，则停止服务
            return;
        }

        // 在每一轮循环开始前排序，确保顺序正确
        runtimeEvents.sort(Comparator.comparingInt(EventWrapper::getOrder));

        // 检查是否完成了一轮事件列表
        if (currentEventIndex >= runtimeEvents.size()) {
            currentEventIndex = 0; // 重置事件索引，准备开始新一轮循环
            currentLoop++; // 完成一轮，增加循环计数
            logDebug("完成第 " + currentLoop + " 轮事件执行。");

            // 判断是否继续循环
            boolean continueLoop = false;
            if (loopCount > 0) { // 按次数循环模式
                if (currentLoop < loopCount) {
                    continueLoop = true;
                    logDebug("继续第 " + (currentLoop + 1) + " 轮循环 (共 " + loopCount + " 轮)");
                } else {
                    logDebug("已达到设定的循环次数 (" + loopCount + " 次)，停止循环。");
                }
            } else if (loopTimeMillis > 0) { // 按时间循环模式
                long elapsedTime = System.currentTimeMillis() - startTimeMillis;
                if (elapsedTime < loopTimeMillis) {
                    continueLoop = true;
                    logDebug("继续循环 (已用时 " + (elapsedTime / 1000) + "s, 总时长 " + (loopTimeMillis / 1000) + "s)");
                } else {
                    logDebug("已达到设定的循环时间 (" + (loopTimeMillis / 1000) + "s)，停止循环。");
                }
            } else { // 无限循环模式 (loopCount == 0 && loopTimeMillis == 0)
                continueLoop = true;
                logDebug("无限循环模式，继续下一轮循环。");
            }

            if (!continueLoop) {
                stopClicking(); // 不再继续循环，则停止服务
                return;
            }
        }

        EventWrapper wrapper = runtimeEvents.get(currentEventIndex);
        Event event = wrapper.getEvent();

        if (wrapper.getType() == EventWrapper.EventType.POINT && event instanceof PointEvent) {
            performSingleClick((PointEvent) event);
        } else if (wrapper.getType() == EventWrapper.EventType.SLIDE && event instanceof SlideEvent) {
            performSlide((SlideEvent) event);
        } else {
            logDebug("未知或不匹配的事件类型，跳过执行: " + wrapper.getType());
            currentEventIndex++; // 跳过当前事件
            handler.postDelayed(this::executeEventsByType, clickInterval); // 立即尝试下一个事件
        }
    }

    private void performSingleClick(PointEvent pointEvent) {
        int viewLeftX = pointEvent.getX();
        int viewTopY = pointEvent.getY();

        final int CORRECTION_X = 54;
        final int CORRECTION_Y = 165;

        int correctedViewLeftX = viewLeftX + CORRECTION_X;
        int correctedViewTopY = viewTopY + CORRECTION_Y;

        int finalClickX = correctedViewLeftX + touchPointSize / 2;
        int finalClickY = correctedViewTopY + touchPointSize / 2;

        Path path = new Path();
        path.moveTo(finalClickX, finalClickY); // 使用最终计算出的点击中心坐标
        GestureDescription.StrokeDescription stroke =
                new GestureDescription.StrokeDescription(path, 0, clickDuration);
        GestureDescription gesture =
                new GestureDescription.Builder().addStroke(stroke).build();

        dispatchGesture(gesture, new GestureResultCallback() {
            @Override
            public void onCompleted(GestureDescription gestureDescription) {
                logDebug("点击完成");
                if (isRunning) {
                    int feedbackIndex = currentEventIndex;
                    currentEventIndex++; // 事件索引递增
                    // 延迟执行下一个事件，循环逻辑在executeEventsByType中处理
                    handler.postDelayed(() -> executeEventsByType(), clickInterval);
                    flashTouchFeedback(feedbackIndex);
                }
            }

            @Override
            public void onCancelled(GestureDescription gestureDescription) {
                Log.e(TAG, "点击被取消");
                if (isRunning) {
                    currentEventIndex++; // 事件索引递增
                    // 延迟执行下一个事件
                    handler.postDelayed(() -> executeEventsByType(), clickInterval + 300);
                }
            }
        }, null);
    }

    private void performSlide(SlideEvent slideEvent) {
        PointEvent start = slideEvent.getStartPoint();
        PointEvent end = slideEvent.getEndPoint();

        int viewStartX = start.getX();
        int viewStartY = start.getY();
        int viewEndX = end.getX();
        int viewEndY = end.getY();

        logDebug("--- performSlide start ---");
        logDebug("原始 SlideEvent 起点: (" + viewStartX + ", " + viewStartY + ")");
        logDebug("原始 SlideEvent 终点: (" + viewEndX + ", " + viewEndY + ")");

        final int CORRECTION_X = 54;
        final int CORRECTION_Y = 165;

        int finalStartX = viewStartX + CORRECTION_X + touchPointSize / 2;
        int finalStartY = viewStartY + CORRECTION_Y + touchPointSize / 2;
        int finalEndX = viewEndX + CORRECTION_X + touchPointSize / 2;
        int finalEndY = viewEndY + CORRECTION_Y + touchPointSize / 2;

        logDebug("滑动起点（视图坐标）: (" + viewStartX + ", " + viewStartY + ")");
        logDebug("滑动终点（视图坐标）: (" + viewEndX + ", " + viewEndY + ")");
        logDebug("滑动起点（修正后）: (" + finalStartX + ", " + finalStartY + ")");
        logDebug("滑动终点（修正后）: (" + finalEndX + ", " + finalEndY + ")");

        Path path = new Path();
        // 这里必须使用修正后的坐标，才能确保手势在正确的位置执行
        path.moveTo(finalStartX, finalStartY);
        path.lineTo(finalEndX, finalEndY);

        GestureDescription.StrokeDescription stroke =
                new GestureDescription.StrokeDescription(path, 0, slideDuration);
        GestureDescription gesture =
                new GestureDescription.Builder().addStroke(stroke).build();

        dispatchGesture(gesture, new GestureResultCallback() {
            @Override
            public void onCompleted(GestureDescription gestureDescription) {
                logDebug("滑动完成");
                if (isRunning) {
                    int feedbackIndex = currentEventIndex;
                    currentEventIndex++; // 事件索引递增
                    // 延迟执行下一个事件
                    handler.postDelayed(() -> executeEventsByType(), clickInterval);
                    flashTouchFeedback(feedbackIndex);
                }
                logDebug("--- onCompleted: 下一个事件将是 index " + currentEventIndex + " ---");
                logDebug("onCompleted 后，SlideEvent 起点: (" + slideEvent.getStartPoint().getX() + ", " + slideEvent.getStartPoint().getY() + ")");
                logDebug("onCompleted 后，SlideEvent 终点: (" + slideEvent.getEndPoint().getX() + ", " + slideEvent.getEndPoint().getY() + ")");
            }

            @Override
            public void onCancelled(GestureDescription gestureDescription) {
                Log.e(TAG, "滑动被取消");
                if (isRunning) {
                    currentEventIndex++; // 事件索引递增
                    // 延迟执行下一个事件
                    handler.postDelayed(() -> executeEventsByType(), clickInterval + 300);
                }
                logDebug("--- onCancelled: 下一个事件将是 index " + currentEventIndex + " ---");
                logDebug("onCancelled 后，SlideEvent 起点: (" + slideEvent.getStartPoint().getX() + ", " + slideEvent.getStartPoint().getY() + ")");
                logDebug("onCancelled 后，SlideEvent 终点: (" + slideEvent.getEndPoint().getX() + ", " + slideEvent.getEndPoint().getY() + ")");
            }
        }, null);
        logDebug("--- performSlide end ---");
    }

    private void flashTouchFeedback(int index) {
        Intent intent = new Intent("com.auto.clicker.autoclicker.FLASH_TOUCH_POINT");
        intent.putExtra("index", index);
        LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
    }

    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
    }

    private void logDebug(String message) {
        Log.d(TAG, message);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        instance = null;
        stopClicking();

        EventViewBinder.setAllTouchPointsDraggable(true);

        Intent intent = new Intent("com.auto.clicker.autoclicker.SERVICE_DESTROYED");
        LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
        logDebug("无障碍服务已销毁");
    }
}