package com.ttstd.controlled.activity.main;

import android.Manifest;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.app.AlertDialog;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.media.projection.MediaProjectionManager;
import android.os.Build;
import android.os.IBinder;
import android.provider.Settings;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import android.widget.Toast;

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

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import com.ttstd.controlled.R;
import com.ttstd.controlled.accessibility.AccessibilityServiceHelper;
import com.ttstd.controlled.base.BaseMvvmActivity;
import com.ttstd.controlled.databinding.ActivityMainBinding;
import com.ttstd.controlled.activity.settings.SettingsActivity;
import com.ttstd.controlled.service.ScreenCaptureService;
import com.ttstd.controlled.accessibility.KeyboardAccessibilityService;
import com.ttstd.controlled.utils.DeviceUtils;
import com.ttstd.controlled.utils.SignatureUtils;
import com.ttstd.controlled.webrtc.WebRtcClient;

import org.webrtc.RendererCommon;

public class MainActivity extends BaseMvvmActivity<MainViewModel, ActivityMainBinding>
        implements ScreenCaptureService.ServiceStateListener {

    private static final String TAG = "ControlledMain";
    private static final int REQUEST_MEDIA_PROJECTION = 1001;
    private static final int REQUEST_NOTIFICATION_PERMISSION = 1002;

    private boolean isServiceRunning = false;
    private ScreenCaptureService screenCaptureService;
    private boolean isBound = false;
    private boolean isLocalViewInitialized = false;

    /** 是否为特权应用（系统签名或无 root 权限），缓存后避免重复在主线程执行 su 检测。 */
    private boolean isPrivileged = false;
    private AlertDialog accessibilityDialog;

    private final ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            ScreenCaptureService.LocalBinder binder = (ScreenCaptureService.LocalBinder) service;
            screenCaptureService = binder.getService();
            isBound = true;
            // 注册状态监听，使界面能感知信令断开/控制端断开并同步显示。
            screenCaptureService.setStateListener(MainActivity.this);
            setupLocalPreview();
            setupResolutionSpinner();
            setupFpsSpinner();
            // 重新绑定（如 Activity 销毁后重新打开）时，依据服务实际状态恢复界面显示为“运行中”。
            if (screenCaptureService.isStreaming()) {
                updateUI(true);
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            isBound = false;
            screenCaptureService = null;
        }
    };

    @Override
    protected int getLayoutId() {
        return R.layout.activity_main;
    }

    @Override
    protected void initView() {
        // 默认服务器地址
        binding.etServerUrl.setText("wss://www.ttstd.com/signal");
        // 生成设备ID
//        if (binding.etDeviceId.getText().toString().isEmpty()) {
//            binding.etDeviceId.setText(DeviceUtils.getSystemSerialNumber());
//        }

        binding.btnStart.setOnClickListener(v -> startScreenSharing());
        binding.btnStop.setOnClickListener(v -> stopScreenSharing());

        // 打开安全与输入设置页面（动态验证码 / 固定密码 / 免密连接 / 模拟点击方式）
        binding.btnOpenSettings.setOnClickListener(v ->
                startActivity(new Intent(this, SettingsActivity.class)));

        updateUI(false);
    }

    @Override
    protected void initData() {
        // Initialization logic if any
        Log.e(TAG, "initData: isSystemApp = " + SignatureUtils.isSystemApp(this));
        Log.e(TAG, "initData: isSystemSignature = " + SignatureUtils.isSystemSignature(this));
        Log.e(TAG, "initData: isSharedSystemUid = " + SignatureUtils.isSharedSystemUid(this));
        Log.e(TAG, "initData: isSystemUid = " + SignatureUtils.isSystemUid());
        Log.e(TAG, "initData: isDeviceRooted = " + SignatureUtils.isDeviceRooted());
        Log.e(TAG, "initData: isAppHasRootPermission = " + SignatureUtils.isAppHasRootPermission());

        // 特权应用判定：系统签名（含共享系统 UID / 系统 UID）或已获取 Root 权限。
        // 特权应用无需依赖无障碍服务即可模拟输入，缓存结果避免每次 onResume 在主线程检测 su。
        boolean systemSigned = SignatureUtils.isSystemSignature(this)
                || SignatureUtils.isSharedSystemUid(this)
                || SignatureUtils.isSystemUid();
        boolean rooted = SignatureUtils.isDeviceRooted() || SignatureUtils.isAppHasRootPermission();
        isPrivileged = systemSigned || rooted;
        Log.e(TAG, "initData: isPrivileged = " + isPrivileged);
    }

    @Override
    protected void onResume() {
        super.onResume();
        // MainActivity 关闭后 ScreenCaptureService 仍在后台串流。重新打开时检查服务是否正在
        // 采集/串流屏幕，若是则重新绑定并恢复界面状态，避免串流状态丢失。
        checkServiceRunningOnResume();
    }

    /**
     * 重新打开 Activity 时检查后台 ScreenCaptureService 是否仍在串流/采集屏幕。
     * 若是，则重新绑定服务（不会重复创建，服务此前已作为前台服务启动），并由
     * onServiceConnected 恢复界面为“运行中”状态。
     */
    private void checkServiceRunningOnResume() {
        ScreenCaptureService service = ScreenCaptureService.getInstance();
        if (service != null && service.isStreaming() && !isBound) {
            Intent serviceIntent = new Intent(this, ScreenCaptureService.class);
            bindService(serviceIntent, serviceConnection, BIND_AUTO_CREATE);
        }
    }

    /** 弹窗提示开启无障碍服务；同一运行周期内仅提示一次。 */
    private void showAccessibilityPermissionDialog() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle(R.string.accessibility_dialog_title)
                .setMessage(R.string.accessibility_dialog_message)
                .setCancelable(false)
                .setPositiveButton(R.string.accessibility_dialog_go, (dialog, which) -> {
                    AccessibilityServiceHelper.jumpToAccessibilitySettings(this);
                })
                .setNegativeButton(R.string.accessibility_dialog_cancel, (dialog, which) -> {
                    dialog.dismiss();
                });
        accessibilityDialog = builder.create();
        accessibilityDialog.show();
    }

    private void startScreenSharing() {
        // 非特权应用且未开启无障碍服务时，弹窗提示用户前往系统设置开启。
        if (!isPrivileged && !AccessibilityServiceHelper.isAccessibilityEnabled(this)) {
            showAccessibilityPermissionDialog();
            return;
        }

        // 检查通知权限 (Android 13+)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS)
                    != PackageManager.PERMISSION_GRANTED) {
                ActivityCompat.requestPermissions(this,
                        new String[]{Manifest.permission.POST_NOTIFICATIONS},
                        REQUEST_NOTIFICATION_PERMISSION);
                return;
            }
        }

        // 请求屏幕录制权限
        MediaProjectionManager projectionManager =
                (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
        startActivityForResult(projectionManager.createScreenCaptureIntent(), REQUEST_MEDIA_PROJECTION);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == REQUEST_MEDIA_PROJECTION) {
            if (resultCode == RESULT_OK && data != null) {
                // 设置静态授权结果（针对 Android 10+ 解决 Token 传递失效）
                ScreenCaptureService.sResultCode = resultCode;
                ScreenCaptureService.sResultData = data;

                Intent serviceIntent = new Intent(this, ScreenCaptureService.class);
                serviceIntent.putExtra(ScreenCaptureService.EXTRA_RESULT_CODE, resultCode);
                serviceIntent.putExtra(ScreenCaptureService.EXTRA_RESULT_DATA, data);
                serviceIntent.putExtra(ScreenCaptureService.EXTRA_SERVER_URL, binding.etServerUrl.getText().toString());
                serviceIntent.putExtra(ScreenCaptureService.EXTRA_DEVICE_ID, binding.etDeviceId.getText().toString());

                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                    startForegroundService(serviceIntent);
                } else {
                    startService(serviceIntent);
                }

                bindService(serviceIntent, serviceConnection, BIND_AUTO_CREATE);

                updateUI(true);
                Toast.makeText(this, "屏幕共享已启动", Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(this, "屏幕录制权限被拒绝", Toast.LENGTH_SHORT).show();
            }
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == REQUEST_NOTIFICATION_PERMISSION) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                startScreenSharing();
            } else {
                Toast.makeText(this, "需要通知权限才能运行", Toast.LENGTH_SHORT).show();
            }
        }
    }

    private void stopScreenSharing() {
        if (isBound) {
            if (screenCaptureService != null) {
                screenCaptureService.setStateListener(null);
            }
            unbindService(serviceConnection);
            isBound = false;
        }
        Intent serviceIntent = new Intent(this, ScreenCaptureService.class);
        stopService(serviceIntent);
        if (binding.localView != null) {
            binding.localView.release();
            isLocalViewInitialized = false;
        }
        updateUI(false);
        Toast.makeText(this, "屏幕共享已停止", Toast.LENGTH_SHORT).show();
    }

    private void setupLocalPreview() {
        if (isBound && screenCaptureService != null && !isLocalViewInitialized) {
            WebRtcClient webRtcClient = screenCaptureService.getWebRtcClient();
            if (webRtcClient != null && webRtcClient.getEglContext() != null) {
                try {
                    binding.localView.init(webRtcClient.getEglContext(), null);
                    binding.localView.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FIT);
                    binding.localView.setMirror(false);
                    webRtcClient.setLocalSink(binding.localView);
                    isLocalViewInitialized = true;
                } catch (Exception e) {
                    Log.e(TAG, "Error initializing local view", e);
                }
            } else {
                // 如果 webRtcClient 还没准备好，稍后重试
                binding.localView.postDelayed(this::setupLocalPreview, 500);
            }
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (accessibilityDialog != null && accessibilityDialog.isShowing()) {
            accessibilityDialog.dismiss();
            accessibilityDialog = null;
        }
        if (isBound) {
            if (screenCaptureService != null) {
                screenCaptureService.setStateListener(null);
            }
            unbindService(serviceConnection);
            isBound = false;
        }
        if (binding != null && binding.localView != null) {
            binding.localView.release();
            isLocalViewInitialized = false;
        }
    }

    // ---- ScreenCaptureService.ServiceStateListener 实现 ----

    @Override
    public void onSignalConnected() {
        runOnUiThread(() -> {
            // 信令服务器连接/重连成功：恢复运行状态显示。
            updateUI(true);
        });
    }

    @Override
    public void onSignalDisconnected() {
        runOnUiThread(() -> {
            // 信令服务器短暂断开：保持服务运行，WebSocketClient 会自动重连。
            binding.tvStatus.setText("状态: 信令断开，正在重连...");
        });
    }

    @Override
    public void onControllerDisconnected(String name) {
        runOnUiThread(() -> {
            // 控制端断开但信令仍在线：更新状态文本提示，保持可重新连接。
            binding.tvStatus.setText("状态: 控制端（" + name + "）已断开");
        });
    }

    private void updateUI(boolean running) {
        isServiceRunning = running;
        binding.btnStart.setEnabled(!running);
        binding.btnStop.setEnabled(running);
        binding.etServerUrl.setEnabled(!running);
        binding.etDeviceId.setEnabled(!running);
        binding.spinnerResolution.setEnabled(running && isBound);
        binding.spinnerFps.setEnabled(running && isBound);
        binding.tvStatus.setText(running ? "状态: 运行中" : "状态: 已停止");
    }

    /** 分辨率预设（按长边像素描述，0/负数表示使用设备原生分辨率）。 */
    private static class ResolutionPreset {
        final String label;
        final int longEdge;

        ResolutionPreset(String label, int longEdge) {
            this.label = label;
            this.longEdge = longEdge;
        }

        @Override
        public String toString() {
            return label;
        }
    }

    /** 构建分辨率下拉框并在本地/远端切换时同步显示当前采集分辨率。 */
    private void setupResolutionSpinner() {
        if (screenCaptureService == null) return;

        int nativeLong = screenCaptureService.getNativeLongEdge();
        List<ResolutionPreset> presets = new ArrayList<>();
        presets.add(new ResolutionPreset("原始 (" + nativeLong + ")", nativeLong));
        presets.add(new ResolutionPreset("1080P", 1920));
        presets.add(new ResolutionPreset("720P", 1280));
        presets.add(new ResolutionPreset("480P", 854));

        ArrayAdapter<ResolutionPreset> adapter = new ArrayAdapter<>(
                this, android.R.layout.simple_spinner_item, presets);
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        binding.spinnerResolution.setAdapter(adapter);

        // 选中当前采集分辨率对应的预设
        int[] cur = screenCaptureService.getCurrentCaptureResolution();
        int curLong = Math.max(cur[0], cur[1]);
        int selectIdx = 0;
        int bestDiff = Integer.MAX_VALUE;
        for (int i = 0; i < presets.size(); i++) {
            int diff = Math.abs(presets.get(i).longEdge - curLong);
            if (diff < bestDiff) {
                bestDiff = diff;
                selectIdx = i;
            }
        }
        binding.spinnerResolution.setSelection(selectIdx);
        updateCurrentResolutionText(cur[0], cur[1], cur[2]);

        // 注册监听：本地或远端切换分辨率/帧率后刷新当前分辨率文本并同步帧率下拉框
        screenCaptureService.setResolutionListener((w, h, fps, fromRemote) ->
                runOnUiThread(() -> {
                    updateCurrentResolutionText(w, h, fps);
                    syncFpsSpinnerSelection(fps);
                }));

        // 注意：先 setSelection 再设置监听，避免初始化时触发一次多余的切换。
        binding.spinnerResolution.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                if (screenCaptureService == null) return;
                ResolutionPreset preset = (ResolutionPreset) parent.getItemAtPosition(position);
                int[] now = screenCaptureService.getCurrentCaptureResolution();
                int nowLong = Math.max(now[0], now[1]);
                // 与当前一致则不重复切换，避免无谓的提示与编码重启
                if (preset.longEdge == nowLong) return;
                screenCaptureService.changeResolutionByLongEdge(preset.longEdge);
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {
            }
        });
    }

    private void updateCurrentResolutionText(int w, int h, int fps) {
        binding.tvCurrentResolution.setText(
                String.format("当前: %dx%d @ %dfps", w, h, fps));
    }

    /** 帧率下拉框可选档位（由服务按屏幕刷新率给出）。 */
    private List<Integer> fpsSpinnerOptions;

    /** 构建帧率下拉框；本地选择后仅切换帧率（保持当前分辨率）。 */
    private void setupFpsSpinner() {
        if (screenCaptureService == null) return;

        List<Integer> options = screenCaptureService.getSupportedFpsList();
        if (options == null || options.isEmpty()) {
            options = new ArrayList<>();
            options.add(15);
            options.add(24);
            options.add(30);
        }
        fpsSpinnerOptions = options;

        List<String> labels = new ArrayList<>();
        for (int f : options) labels.add(f + " fps");
        ArrayAdapter<String> adapter = new ArrayAdapter<>(
                this, android.R.layout.simple_spinner_item, labels);
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        binding.spinnerFps.setAdapter(adapter);

        int[] cur = screenCaptureService.getCurrentCaptureResolution();
        syncFpsSpinnerSelection(cur[2]);

        // 注意：先 setSelection 再设置监听，避免初始化时触发一次多余的切换。
        binding.spinnerFps.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                if (screenCaptureService == null || fpsSpinnerOptions == null) return;
                int fps = fpsSpinnerOptions.get(position);
                int[] now = screenCaptureService.getCurrentCaptureResolution();
                // 与当前一致则不重复切换，避免无谓的提示与编码重启
                if (fps == now[2]) return;
                screenCaptureService.changeFps(fps);
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {
            }
        });
    }

    /** 将帧率下拉框选中项同步为最接近 fps 的档位（本地/远端切换后调用）。 */
    private void syncFpsSpinnerSelection(int fps) {
        if (fpsSpinnerOptions == null || fpsSpinnerOptions.isEmpty()) return;
        int idx = 0;
        int bestDiff = Integer.MAX_VALUE;
        for (int i = 0; i < fpsSpinnerOptions.size(); i++) {
            int diff = Math.abs(fpsSpinnerOptions.get(i) - fps);
            if (diff < bestDiff) {
                bestDiff = diff;
                idx = i;
            }
        }
        if (binding.spinnerFps.getSelectedItemPosition() != idx) {
            binding.spinnerFps.setSelection(idx);
        }
    }
}
