package com.ttstd.dialer.manager;

import android.annotation.SuppressLint;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.util.Log;

import com.tencent.mmkv.MMKV;
import com.ttstd.dialer.config.CommonConfig;
import com.ttstd.dialer.db.app.AppInfo;
import com.ttstd.dialer.db.app.AppRepository;
import com.ttstd.dialer.gson.GsonUtils;
import com.ttstd.dialer.utils.ApkUtils;

import java.text.Collator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.IntConsumer;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class AppManager {
    private static final String TAG = "AppManager";
    // 步骤常量定义，便于回调和日志统一管理
    private static final String STEP_FIRST_INIT = "首次初始化应用数据";
    private static final String STEP_REMOVE_UNINSTALLED = "移除未安装应用";
    private static final String STEP_ADD_NEW_APPS = "添加新安装应用";
    private static final String STEP_UPDATE_POSITION = "更新应用位置";
    private static final int TOTAL_STEPS_NORMAL = 3; // 正常流程总步骤
    private static final int TOTAL_STEPS_FIRST = 2;  // 首次初始化总步骤

    private MMKV mMMKV = MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE);

    @SuppressLint("StaticFieldLeak")
    private static AppManager INSTANCE;
    private Context mContext;
    private AppRepository mAppRepository;

    private Set<ProgressCallback> mProgressCallbacks = new CopyOnWriteArraySet<>();

    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
    private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
    private static final ExecutorService ASYNC_EXECUTOR = Executors.newFixedThreadPool(CORE_POOL_SIZE);

    public interface ProgressCallback {
        void onProgress(String step, int current, int total);

        void onCompleted(boolean success, String message);
    }

    public void addProgressCallback(ProgressCallback progressCallback) {
        if (progressCallback != null) {
            mProgressCallbacks.add(progressCallback);
        }
    }

    public void removeProgressCallback(ProgressCallback progressCallback) {
        mProgressCallbacks.remove(progressCallback);
    }

    public static final List<String> DEFAULT_APP_PACKAGES = new ArrayList<String>() {{
        this.add("com.android.settings");
        this.add("com.android.dialer");
        this.add("com.android.camera2");
        this.add("com.android.messaging");
        this.add("com.android.contacts");
        this.add("com.tencent.mm");
        this.add("com.jiangjia.gif");
        this.add("com.ss.android.ugc.aweme");
    }};

    public static void init(Context context) {
        if (INSTANCE == null) {
            INSTANCE = new AppManager(context);
        }
    }

    public static AppManager getInstance() {
        if (INSTANCE == null) {
            throw new IllegalStateException("You must be init AppManager first");
        }
        return INSTANCE;
    }

    private AppManager(Context context) {
        this.mContext = context.getApplicationContext();
        this.mAppRepository = new AppRepository(context);
        executeAppListProcessing();
    }

    // 通知进度回调
    private void notifyProgress(String step, int current, int total) {
        mProgressCallbacks.forEach(callback -> callback.onProgress(step, current, total));
    }

    // 通知完成回调
    private void notifyCompleted(boolean success, String message) {
        mProgressCallbacks.forEach(callback -> callback.onCompleted(success, message));
    }

    // 异步执行应用列表处理流程
    public void executeAppListProcessing() {
        CompletableFuture
                .supplyAsync(this::getAllDesktopSortApps, ASYNC_EXECUTOR)
                .thenComposeAsync(desktopApps -> {
                    // 根据应用列表是否为空，选择不同处理流程
                    if (desktopApps.isEmpty()) {
                        // 首次初始化流程：首次数据加载 -> 更新位置
                        return processFirstTimeApps()
                                .thenComposeAsync(unused -> {
                                    notifyProgress(STEP_UPDATE_POSITION, 2, TOTAL_STEPS_FIRST);
                                    return updatePosition();
                                }, ASYNC_EXECUTOR);
                    } else {
                        // 正常流程：移除未安装 -> 添加新应用 -> 更新位置
                        return processUninstalledApps(desktopApps)
                                .thenComposeAsync(unused -> {
                                    notifyProgress(STEP_ADD_NEW_APPS, 2, TOTAL_STEPS_NORMAL);
                                    return processNewApps();
                                }, ASYNC_EXECUTOR)
                                .thenComposeAsync(unused -> {
                                    notifyProgress(STEP_UPDATE_POSITION, 3, TOTAL_STEPS_NORMAL);
                                    return updatePosition();
                                }, ASYNC_EXECUTOR);
                    }
                }, ASYNC_EXECUTOR)
                .thenRun(() -> notifyCompleted(true, "应用列表处理完成"))
                .exceptionally(throwable -> {
                    Log.e(TAG, "异步处理失败", throwable);
                    notifyCompleted(false, "处理失败: " + throwable.getMessage());
                    return null;
                });
    }

    // 第一步：获取所有桌面应用（空值安全处理）
    private List<AppInfo> getAllDesktopSortApps() {
        try {
            List<AppInfo> result = mAppRepository.getAllApp();
            return result != null ? result : Collections.emptyList();
        } catch (Exception e) {
            Log.e(TAG, "获取桌面应用列表失败", e);
            return Collections.emptyList();
        }
    }

    // 首次初始化应用数据（针对首次获取为空的场景）
    private CompletableFuture<Void> processFirstTimeApps() {
        return CompletableFuture.runAsync(() -> {
            notifyProgress(STEP_FIRST_INIT, 1, TOTAL_STEPS_FIRST);
            Log.i(TAG, "进入首次应用数据初始化流程");

            try {
                // 获取所有可启动应用
                List<ResolveInfo> allLauncherApps = ApkUtils.getAllLauncherResolveInfo(mContext);
                if (allLauncherApps.isEmpty()) {
                    Log.w(TAG, "未获取到任何可启动应用，无法完成首次初始化");
                    return;
                }

                List<AppInfo> allFirstApps = allLauncherApps.stream()
                        .filter(Objects::nonNull)
                        .map(this::resolveInfoToDesktopApp)
                        .filter(Objects::nonNull)
                        .sorted((o1, o2) -> Boolean.compare(ApkUtils.isSystemApp(mContext, o2.getPackageName()), ApkUtils.isSystemApp(mContext, o1.getPackageName())))
                        .sorted(getAppComparator())
                        .collect(Collectors.toList());

                IntStream.range(0, allFirstApps.size())
                        .forEach(new IntConsumer() {
                            @Override
                            public void accept(int index) {
                                AppInfo appInfo = allFirstApps.get(index);
                                if (DEFAULT_APP_PACKAGES.contains(appInfo.getPackageName())) {
                                    appInfo.setOutside(1);
                                } else {
                                    appInfo.setOutside(0);
                                }
                                appInfo.setPosition(index);
                            }
                        });

                // 批量插入首次数据
                allFirstApps.forEach(app -> {
                    try {
                        mAppRepository.insert(app);
                    } catch (Exception e) {
                        Log.e(TAG, "首次初始化插入应用失败: " + app.getPackageName(), e);
                    }
                });

                Log.i(TAG, "首次初始化完成，插入默认应用: " + allFirstApps.size() + " 个");
            } catch (Exception e) {
                Log.e(TAG, "首次应用数据初始化失败", e);
                throw new RuntimeException("首次初始化失败", e); // 抛出异常触发回调
            }
        }, ASYNC_EXECUTOR);
    }

    // 处理未安装的应用（删除操作）
    private CompletableFuture<Void> processUninstalledApps(List<AppInfo> appInfos) {
        return CompletableFuture.runAsync(() -> {
            notifyProgress(STEP_REMOVE_UNINSTALLED, 1, TOTAL_STEPS_NORMAL);
            if (appInfos.isEmpty()) {
                Log.w(TAG, "桌面应用列表为空，跳过删除处理");
                return;
            }

            List<Integer> ids = appInfos.stream()
                    .filter(Objects::nonNull)
                    .filter(app -> !ApkUtils.isInstalled(mContext, app.getPackageName()))
                    .map(app -> {
                        try {
                            return mAppRepository.getIdByPackageAndClass(app.getPackageName(), app.getClassName());
                        } catch (Exception e) {
                            Log.e(TAG, "获取应用ID失败: " + app.getPackageName(), e);
                            return -1;
                        }
                    })
                    .filter(id -> id > 0)
                    .collect(Collectors.toList());

            if (!ids.isEmpty()) {
                ids.forEach(id -> {
                    try {
                        mAppRepository.deleteById(id);
                    } catch (Exception e) {
                        Log.e(TAG, "删除应用失败, ID: " + id, e);
                    }
                });
                Log.i(TAG, "成功删除 " + ids.size() + " 个未安装应用");
            }
        }, ASYNC_EXECUTOR);
    }

    // 处理新安装的应用（插入操作）- 非首次场景
    private CompletableFuture<Void> processNewApps() {
        return CompletableFuture.runAsync(() -> {
            try {
                List<ResolveInfo> resolveInfos = ApkUtils.getAllLauncherResolveInfo(mContext);
                if (resolveInfos.isEmpty()) {
                    Log.w(TAG, "未获取到启动器应用列表，跳过新应用处理");
                    return;
                }

                List<AppInfo> newApps = resolveInfos.stream()
                        .filter(Objects::nonNull)
                        .map(this::resolveInfoToDesktopApp)
                        .filter(Objects::nonNull)
                        .filter(app -> ApkUtils.isInstalled(mContext, app.getPackageName()))
                        .filter(app -> !isAppExists(app)) // 过滤已存在的应用
                        .sorted(getAppComparator())
                        .collect(Collectors.toList());

                if (!newApps.isEmpty()) {
                    newApps.forEach(app -> app.setPosition(mAppRepository.getTotalCount()));
                    newApps.forEach(app -> {
                        try {
                            mAppRepository.insert(app);
                        } catch (Exception e) {
                            Log.e(TAG, "插入新应用失败: " + app.getPackageName(), e);
                        }
                    });
                    Log.i(TAG, "成功插入 " + newApps.size() + " 个新应用");
                } else {
                    Log.i(TAG, "没有需要插入的新应用");
                }
            } catch (Exception e) {
                Log.e(TAG, "处理新应用时发生异常", e);
                throw new RuntimeException("新应用处理失败", e);
            }
        }, ASYNC_EXECUTOR);
    }

    // 更新应用位置
    private CompletableFuture<Void> updatePosition() {
        return CompletableFuture.runAsync(() -> {
            try {
                List<AppInfo> appInfos = getAllDesktopSortApps();
                if (appInfos.isEmpty()) {
                    Log.w(TAG, "无应用数据，跳过位置更新");
                    return;
                }

                List<AppInfo> sortedApps = appInfos.stream()
                        .filter(Objects::nonNull)
                        .sorted(Comparator.comparingInt(AppInfo::getPosition))
                        .collect(Collectors.toList());

                IntStream.range(0, sortedApps.size())
                        .forEach(index -> {
                            AppInfo app = sortedApps.get(index);
                            app.setPosition(index);
                            try {
                                mAppRepository.update(app);
                            } catch (Exception e) {
                                Log.e(TAG, "更新应用位置失败: " + app.getPackageName(), e);
                            }
                        });
                Log.i(TAG, "成功更新 " + sortedApps.size() + " 个应用的位置");
            } catch (Exception e) {
                Log.e(TAG, "更新应用位置时发生异常", e);
                throw new RuntimeException("位置更新失败", e);
            }
        }, ASYNC_EXECUTOR);
    }

    // 工具方法：ResolveInfo转换为DesktopSortApp
    private AppInfo resolveInfoToDesktopApp(ResolveInfo resolveInfo) {
        ComponentName component = new ComponentName(
                resolveInfo.activityInfo.packageName,
                resolveInfo.activityInfo.name
        );
        return new AppInfo(mContext, component);
    }

    // 工具方法：检查应用是否已存在
    private boolean isAppExists(AppInfo app) {
        try {
            return mAppRepository.checkAppInfoExists(app.getPackageName(), app.getClassName()) > 0;
        } catch (Exception e) {
            Log.e(TAG, "检查应用存在性失败: " + app.getPackageName(), e);
            return false;
        }
    }

    // 工具方法：获取应用排序器（统一排序逻辑）
    private Comparator<AppInfo> getAppComparator() {
        return Comparator.comparing(AppInfo::getLabel, Collator.getInstance(Locale.CHINESE));
    }

    public void updateApp(String packageName) {
        List<ResolveInfo> resolveInfos = ApkUtils.getResolveInfoByPackageName(mContext, packageName);
        if (resolveInfos.isEmpty()) return;

        resolveInfos.stream()
                .map(this::resolveInfoToDesktopApp)
                .filter(Objects::nonNull)
                .filter(app -> !isAppExists(app))
                .forEach(app -> {
                    app.setPosition(mAppRepository.getTotalCount());
                    try {
                        mAppRepository.insert(app);
                    } catch (Exception e) {
                        Log.e(TAG, "更新应用插入失败: " + app.getPackageName(), e);
                    }
                });
    }

    // 重构getAllApp方法，复用现有处理逻辑
    public void refreshAllApps() {
        CompletableFuture.runAsync(() -> {
            List<AppInfo> allApps = getAllDesktopSortApps();
            if (allApps.isEmpty()) {
                processFirstTimeApps().join();
            } else {
                processUninstalledApps(allApps).join();
                processNewApps().join();
            }
            updatePosition().join();
        }, ASYNC_EXECUTOR);
    }

    public String getDefaultAppList() {
        PackageManager pm = mContext.getPackageManager();
        List<ResolveInfo> resolveInfos = ApkUtils.getAllLauncherResolveInfo(mContext);

        List<AppInfo> defaultApps = resolveInfos.stream()
                .filter(ri -> DEFAULT_APP_PACKAGES.contains(ri.activityInfo.packageName))
                .sorted((o1, o2) -> Collator.getInstance(Locale.CHINESE)
                        .compare(o1.activityInfo.loadLabel(pm), o2.activityInfo.loadLabel(pm)))
                .map(ri -> new ComponentName(ri.activityInfo.packageName, ri.activityInfo.name))
                .map(component -> new AppInfo(mContext, component))
                .sorted((a, b) -> Boolean.compare(
                        ApkUtils.isSystemApp(mContext, b.getPackageName()),
                        ApkUtils.isSystemApp(mContext, a.getPackageName())))
                .collect(Collectors.toCollection(LinkedList::new));

        IntStream.range(0, defaultApps.size())
                .forEach(i -> defaultApps.get(i).setPosition(i));

        return GsonUtils.toJSONString(defaultApps);
    }
}