package cc.winboll.studio.libappbase;

/**
 * @Author ZhanGSKen@QQ.COM
 * @Date 2024/08/12 13:44:06
 * @Describe LogUtils
 * @Describe 应用日志类（补全所有日志重载方法，适配不同调试场景）
 */
import android.content.Context;
import android.widget.Toast;
import cc.winboll.studio.libappbase.GlobalApplication;
import dalvik.system.DexFile;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;


public class LogUtils {

    public static final String TAG = "LogUtils";

    public static enum LOG_LEVEL { Off, Error, Warn, Info, Debug, Verbose }

    static volatile boolean _IsInited = false;
    static Context _mContext;
    // 日志显示时间格式
    static SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat("[yyyyMMdd_HHmmss_SSS]", Locale.getDefault());
    // 应用日志文件夹
    static File _mfLogCacheDir;
    static File _mfLogDataDir;
    // 应用日志文件
    static File _mfLogCatchFile;
    static File _mfLogUtilsBeanFile;
    static LogUtilsBean _mLogUtilsBean;
    public static Map<String, Boolean> mapTAGList = new HashMap<String, Boolean>();

    //
    // 初始化函数
    //
    public static void init(Context context) {
        _mContext = context;
        init(context, LOG_LEVEL.Off);
    }

    //
    // 初始化函数
    //
    public static void init(Context context, LOG_LEVEL logLevel) {
        if (GlobalApplication.isDebugging()) {
            // 初始化日志缓存文件路径（debug模式：外部存储）
            _mfLogCacheDir = new File(context.getApplicationContext().getExternalCacheDir(), TAG);
            if (!_mfLogCacheDir.exists()) {
                _mfLogCacheDir.mkdirs();
            }
            _mfLogCatchFile = new File(_mfLogCacheDir, "log.txt");

            // 初始化日志配置文件路径
            _mfLogDataDir = context.getApplicationContext().getExternalFilesDir(TAG);
            if (!_mfLogDataDir.exists()) {
                _mfLogDataDir.mkdirs();
            }
            _mfLogUtilsBeanFile = new File(_mfLogDataDir, TAG + ".json");
        } else {
            // 初始化日志缓存文件路径（release模式：内部存储）
            _mfLogCacheDir = new File(context.getApplicationContext().getCacheDir(), TAG);
            if (!_mfLogCacheDir.exists()) {
                _mfLogCacheDir.mkdirs();
            }
            _mfLogCatchFile = new File(_mfLogCacheDir, "log.txt");

            // 初始化日志配置文件路径
            _mfLogDataDir = new File(context.getApplicationContext().getFilesDir(), TAG);
            if (!_mfLogDataDir.exists()) {
                _mfLogDataDir.mkdirs();
            }
            _mfLogUtilsBeanFile = new File(_mfLogDataDir, TAG + ".json");
        }

        _mLogUtilsBean = LogUtilsBean.loadBeanFromFile(_mfLogUtilsBeanFile.getPath(), LogUtilsBean.class);
        if (_mLogUtilsBean == null) {
            _mLogUtilsBean = new LogUtilsBean();
            _mLogUtilsBean.saveBeanToFile(_mfLogUtilsBeanFile.getPath(), _mLogUtilsBean);
        }

        // 加载当前应用下的所有类的 TAG
        addClassTAGList();
        loadTAGBeanSettings();
        checkAndTrimLogFileSize();
        _IsInited = true;
        LogUtils.d(TAG, String.format("mapTAGList : %s", mapTAGList.toString()));
    }

    private static void checkAndTrimLogFileSize() {
        if (_mfLogCatchFile == null || !_mfLogCatchFile.exists()) {
            return;
        }

        final long MAX_FILE_SIZE = 6291456L;
        final long KEEP_FILE_SIZE = 3145728L;

        long fileSize = _mfLogCatchFile.length();
        if (fileSize <= MAX_FILE_SIZE) {
            return;
        }

        long needSkip = fileSize - KEEP_FILE_SIZE;

        try (FileInputStream fis = new FileInputStream(_mfLogCatchFile);
             BufferedReader reader = new BufferedReader(new InputStreamReader(fis));
             FileOutputStream fos = new FileOutputStream(_mfLogCatchFile);
             BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(fos))) {

            StringBuilder sb = new StringBuilder();
            String line;
            long skippedTotal = 0;
            final String lineBreak = System.lineSeparator();

            while ((line = reader.readLine()) != null) {
                byte[] lineBytes = line.getBytes();
                skippedTotal += lineBytes.length + lineBreak.getBytes().length;

                if (skippedTotal > needSkip) {
                    sb.append(line).append(lineBreak);
                }
            }

            writer.write(sb.toString());

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static Map<String, Boolean> getMapTAGList() {
        return mapTAGList;
    }

    static void loadTAGBeanSettings() {
        ArrayList<LogUtilsClassTAGBean> list = new ArrayList<LogUtilsClassTAGBean>();
        LogUtilsClassTAGBean.loadBeanList(_mContext, list, LogUtilsClassTAGBean.class);
        for (int i = 0; i < list.size(); i++) {
            LogUtilsClassTAGBean beanSetting = list.get(i);
            for (Map.Entry<String, Boolean> entry : mapTAGList.entrySet()) {
                if (entry.getKey().equals(beanSetting.getTag())) {
                    entry.setValue(beanSetting.getEnable());
                }
            }
        }
    }

    static void saveTAGBeanSettings() {
        ArrayList<LogUtilsClassTAGBean> list = new ArrayList<LogUtilsClassTAGBean>();
        for (Map.Entry<String, Boolean> entry : mapTAGList.entrySet()) {
            list.add(new LogUtilsClassTAGBean(entry.getKey(), entry.getValue()));
        }
        LogUtilsClassTAGBean.saveBeanList(_mContext, list, LogUtilsClassTAGBean.class);
    }

    static void addClassTAGList() {
        try {
            // 包名前缀（过滤当前应用的类）
            String packageNamePrefix = "cc.winboll.studio";
            List<String> classNames = new ArrayList<>();
            String apkPath = _mContext.getPackageCodePath();
            LogUtils.d(TAG, String.format("apkPath : %s", apkPath));

            DexFile dexfile = new DexFile(apkPath);
            int countTemp = 0;
            Enumeration<String> entries = dexfile.entries();
            while (entries.hasMoreElements()) {
                countTemp++;
                String className = entries.nextElement();
                if (className.startsWith(packageNamePrefix)) {
                    classNames.add(className);
                }
            }

            LogUtils.d(TAG, String.format("countTemp : %d\nClassNames size : %d", countTemp, classNames.size()));

            for (String className : classNames) {
                try {
                    Class<?> clazz = Class.forName(className);
                    Field[] fields = clazz.getDeclaredFields();
                    for (Field field : fields) {
                        // 过滤静态、公共、String类型的 TAG 字段
                        if (Modifier.isStatic(field.getModifiers()) 
							&& Modifier.isPublic(field.getModifiers()) 
							&& field.getType() == String.class 
							&& "TAG".equals(field.getName())) {
                            String tagValue = (String) field.get(null);
                            mapTAGList.put(tagValue, false); // 默认禁用，可通过设置开启
                        }
                    }
                } catch (NoClassDefFoundError | ClassNotFoundException | IllegalAccessException e) {
                    LogUtils.d(TAG, e.getMessage(), Thread.currentThread().getStackTrace());
                }
            }
        } catch (IOException e) {
            LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
        }
    }

    public static void setTAGListEnable(String tag, boolean isEnable) {
        Iterator<Map.Entry<String, Boolean>> iterator = mapTAGList.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, Boolean> entry = iterator.next();
            if (tag.equals(entry.getKey())) {
                entry.setValue(isEnable);
                break;
            }
        }
        saveTAGBeanSettings();
        LogUtils.d(TAG, String.format("mapTAGList : %s", mapTAGList.toString()));
    }

    public static void setALlTAGListEnable(boolean isEnable) {
        Iterator<Map.Entry<String, Boolean>> iterator = mapTAGList.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, Boolean> entry = iterator.next();
            entry.setValue(isEnable);
        }
        saveTAGBeanSettings();
        LogUtils.d(TAG, String.format("mapTAGList : %s", mapTAGList.toString()));
    }

    public static void setLogLevel(LOG_LEVEL logLevel) {
        LogUtils._mLogUtilsBean.setLogLevel(logLevel);
        _mLogUtilsBean.saveBeanToFile(_mfLogUtilsBeanFile.getPath(), _mLogUtilsBean);
    }

    public static LOG_LEVEL getLogLevel() {
        return LogUtils._mLogUtilsBean.getLogLevel();
    }

    static boolean isLoggable(String tag, LOG_LEVEL logLevel) {
        if (!_IsInited) {
            return false;
        } 
        // TAG 未配置或禁用时，不打印日志
        if (mapTAGList.get(tag) == null || !mapTAGList.get(tag)) {
            return false;
        } 
        // 日志级别不符合时，不打印日志
        if (!isInTheLevel(logLevel)) {
            return false;
        }
        return true;
    }

    static boolean isInTheLevel(LOG_LEVEL logLevel) {
        // 当前日志级别 >= 目标级别时，允许打印（级别顺序：Off < Error < Warn < Info < Debug < Verbose）
        return LogUtils._mLogUtilsBean.getLogLevel().ordinal() >= logLevel.ordinal();
    }

    //
    // 获取应用日志文件夹
    //
    public static File getLogCacheDir() {
        return _mfLogCacheDir;
    }

    // ================================= 补全所有日志重载方法（Error 级别） =================================
    /**
     * Error 级别日志（仅消息）
     * @param szTAG 标签
     * @param szMessage 日志消息
     */
    public static void e(String szTAG, String szMessage) {
        if (isLoggable(szTAG, LogUtils.LOG_LEVEL.Error)) {
            saveLog(szTAG, LogUtils.LOG_LEVEL.Error, szMessage);
        }
    }

    /**
     * Error 级别日志（消息 + 异常）
     * @param szTAG 标签
     * @param szMessage 日志消息
     * @param e 异常对象
     */
    public static void e(String szTAG, String szMessage, Exception e) {
        if (isLoggable(szTAG, LogUtils.LOG_LEVEL.Error)) {
            StringBuilder sb = new StringBuilder(szMessage);
            sb.append("\n【异常信息】: ").append(getExceptionInfo(e));
            saveLog(szTAG, LogUtils.LOG_LEVEL.Error, sb.toString());
        }
    }

    /**
     * Error 级别日志（仅异常）
     * @param szTAG 标签
     * @param e 异常对象
     */
    public static void e(String szTAG, Exception e) {
        if (isLoggable(szTAG, LogUtils.LOG_LEVEL.Error)) {
            String message = "【异常信息】: " + getExceptionInfo(e);
            saveLog(szTAG, LogUtils.LOG_LEVEL.Error, message);
        }
    }

    /**
     * Error 级别日志（消息 + 异常 + 堆栈）
     * @param szTAG 标签
     * @param szMessage 日志消息
     * @param e 异常对象
     * @param listStackTrace 堆栈信息
     */
    public static void e(String szTAG, String szMessage, Exception e, StackTraceElement[] listStackTrace) {
        if (isLoggable(szTAG, LogUtils.LOG_LEVEL.Error)) {
            StringBuilder sb = new StringBuilder(szMessage);
            sb.append("\n【异常信息】: ").append(getExceptionInfo(e));
            sb.append("\n【堆栈信息】: ").append(getStackTraceInfo(listStackTrace));
            saveLog(szTAG, LogUtils.LOG_LEVEL.Error, sb.toString());
        }
    }

    // ================================= 补全所有日志重载方法（Warn 级别） =================================
    /**
     * Warn 级别日志（仅消息）
     * @param szTAG 标签
     * @param szMessage 日志消息
     */
    public static void w(String szTAG, String szMessage) {
        if (isLoggable(szTAG, LogUtils.LOG_LEVEL.Warn)) {
            saveLog(szTAG, LogUtils.LOG_LEVEL.Warn, szMessage);
        }
    }

    /**
     * Warn 级别日志（消息 + 异常）
     * @param szTAG 标签
     * @param szMessage 日志消息
     * @param e 异常对象
     */
    public static void w(String szTAG, String szMessage, Exception e) {
        if (isLoggable(szTAG, LogUtils.LOG_LEVEL.Warn)) {
            StringBuilder sb = new StringBuilder(szMessage);
            sb.append("\n【异常信息】: ").append(getExceptionInfo(e));
            saveLog(szTAG, LogUtils.LOG_LEVEL.Warn, sb.toString());
        }
    }

    /**
     * Warn 级别日志（仅异常）
     * @param szTAG 标签
     * @param e 异常对象
     */
    public static void w(String szTAG, Exception e) {
        if (isLoggable(szTAG, LogUtils.LOG_LEVEL.Warn)) {
            String message = "【异常信息】: " + getExceptionInfo(e);
            saveLog(szTAG, LogUtils.LOG_LEVEL.Warn, message);
        }
    }

    // ================================= 补全所有日志重载方法（Info 级别） =================================
    /**
     * Info 级别日志（仅消息）
     * @param szTAG 标签
     * @param szMessage 日志消息
     */
    public static void i(String szTAG, String szMessage) {
        if (isLoggable(szTAG, LogUtils.LOG_LEVEL.Info)) {
            saveLog(szTAG, LogUtils.LOG_LEVEL.Info, szMessage);
        }
    }

    /**
     * Info 级别日志（消息 + 数据对象）
     * @param szTAG 标签
     * @param szMessage 日志消息
     * @param obj 数据对象（自动转为字符串）
     */
    public static void i(String szTAG, String szMessage, Object obj) {
        if (isLoggable(szTAG, LogUtils.LOG_LEVEL.Info)) {
            String objStr = obj == null ? "null" : obj.toString();
            StringBuilder sb = new StringBuilder(szMessage);
            sb.append("\n【数据对象】: ").append(objStr);
            saveLog(szTAG, LogUtils.LOG_LEVEL.Info, sb.toString());
        }
    }

    // ================================= 补全所有日志重载方法（Debug 级别） =================================
    /**
     * Debug 级别日志（仅消息）
     * @param szTAG 标签
     * @param szMessage 日志消息
     */
    public static void d(String szTAG, String szMessage) {
        if (isLoggable(szTAG, LogUtils.LOG_LEVEL.Debug)) {
            saveLog(szTAG, LogUtils.LOG_LEVEL.Debug, szMessage);
        }
    }

    /**
     * Debug 级别日志（消息 + 堆栈）
     * @param szTAG 标签
     * @param szMessage 日志消息
     * @param listStackTrace 堆栈信息
     */
    public static void d(String szTAG, String szMessage, StackTraceElement[] listStackTrace) {
        if (isLoggable(szTAG, LogUtils.LOG_LEVEL.Debug)) {
            StringBuilder sbMessage = new StringBuilder(szMessage);
            sbMessage.append("\n【调用堆栈】: ").append(getStackTraceInfo(listStackTrace));
            saveLog(szTAG, LogUtils.LOG_LEVEL.Debug, sbMessage.toString());
        }
    }

    /**
     * Debug 级别日志（消息 + 异常）
     * @param szTAG 标签
     * @param szMessage 日志消息
     * @param e 异常对象
     */
    public static void d(String szTAG, String szMessage, Exception e) {
        if (isLoggable(szTAG, LogUtils.LOG_LEVEL.Debug)) {
            StringBuilder sb = new StringBuilder(szMessage);
            sb.append("\n【异常信息】: ").append(getExceptionInfo(e));
            saveLog(szTAG, LogUtils.LOG_LEVEL.Debug, sb.toString());
        }
    }

    /**
     * Debug 级别日志（异常 + 堆栈）
     * @param szTAG 标签
     * @param e 异常对象
     * @param listStackTrace 堆栈信息
     */
    public static void d(String szTAG, Exception e, StackTraceElement[] listStackTrace) {
        if (isLoggable(szTAG, LogUtils.LOG_LEVEL.Debug)) {
            StringBuilder sbMessage = new StringBuilder();
            sbMessage.append("【异常信息】: ").append(getExceptionInfo(e));
            sbMessage.append("\n【调用堆栈】: ").append(getStackTraceInfo(listStackTrace));
            saveLog(szTAG, LogUtils.LOG_LEVEL.Debug, sbMessage.toString());
        }
    }

    /**
     * Debug 级别日志（消息 + 数据对象）
     * @param szTAG 标签
     * @param szMessage 日志消息
     * @param obj 数据对象（自动转为字符串）
     */
	public static void d(String szTAG, String szMessage, Object obj) {
        if (isLoggable(szTAG, LogUtils.LOG_LEVEL.Debug)) {
            String objStr = obj == null ? "null" : obj.toString();
            StringBuilder sb = new StringBuilder(szMessage);
            sb.append("\n【数据对象】: ").append(objStr);
            saveLog(szTAG, LogUtils.LOG_LEVEL.Debug, sb.toString());
        }
    }

    /**
     * Debug 级别日志（仅数据对象）
     * @param szTAG 标签
     * @param obj 数据对象（自动转为字符串）
     */
    public static void d(String szTAG, Object obj) {
        if (isLoggable(szTAG, LogUtils.LOG_LEVEL.Debug)) {
            String objStr = obj == null ? "null" : obj.toString();
            String message = "【数据对象】: " + objStr;
            saveLog(szTAG, LogUtils.LOG_LEVEL.Debug, message);
        }
    }

    // ================================= 补全所有日志重载方法（Verbose 级别） =================================
    /**
     * Verbose 级别日志（仅消息）
     * @param szTAG 标签
     * @param szMessage 日志消息
     */
    public static void v(String szTAG, String szMessage) {
        if (isLoggable(szTAG, LogUtils.LOG_LEVEL.Verbose)) {
            saveLog(szTAG, LogUtils.LOG_LEVEL.Verbose, szMessage);
        }
    }

    /**
     * Verbose 级别日志（消息 + 数据对象）
     * @param szTAG 标签
     * @param szMessage 日志消息
     * @param obj 数据对象（自动转为字符串）
     */
    public static void v(String szTAG, String szMessage, Object obj) {
        if (isLoggable(szTAG, LogUtils.LOG_LEVEL.Verbose)) {
            String objStr = obj == null ? "null" : obj.toString();
            StringBuilder sb = new StringBuilder(szMessage);
            sb.append("\n【数据对象】: ").append(objStr);
            saveLog(szTAG, LogUtils.LOG_LEVEL.Verbose, sb.toString());
        }
    }

    /**
     * Verbose 级别日志（仅数据对象）
     * @param szTAG 标签
     * @param obj 数据对象（自动转为字符串）
     */
    public static void v(String szTAG, Object obj) {
        if (isLoggable(szTAG, LogUtils.LOG_LEVEL.Verbose)) {
            String objStr = obj == null ? "null" : obj.toString();
            String message = "【数据对象】: " + objStr;
            saveLog(szTAG, LogUtils.LOG_LEVEL.Verbose, message);
        }
    }

    // ================================= 新增：通用日志工具方法（补充调试能力） =================================
    /**
     * 打印当前线程信息（Debug 级别）
     * @param szTAG 标签
     * @param szMessage 日志消息
     */
    public static void printThreadInfo(String szTAG, String szMessage) {
        if (isLoggable(szTAG, LogUtils.LOG_LEVEL.Debug)) {
            Thread currentThread = Thread.currentThread();
            StringBuilder sb = new StringBuilder(szMessage);
            sb.append("\n【线程信息】: ")
				.append("线程名=").append(currentThread.getName())
				.append(", 线程ID=").append(currentThread.getId())
				.append(", 线程状态=").append(currentThread.getState().name());
            saveLog(szTAG, LogUtils.LOG_LEVEL.Debug, sb.toString());
        }
    }

    /**
     * 打印 Map 数据（Debug 级别，格式化输出，便于查看）
     * @param szTAG 标签
     * @param szMessage 日志消息
     * @param map 要打印的 Map 数据
     */
    public static <K, V> void printMap(String szTAG, String szMessage, Map<K, V> map) {
        if (isLoggable(szTAG, LogUtils.LOG_LEVEL.Debug) && map != null) {
            StringBuilder sb = new StringBuilder(szMessage);
            sb.append("\n【Map 数据】（size=").append(map.size()).append("）:");
            for (Map.Entry<K, V> entry : map.entrySet()) {
                String keyStr = entry.getKey() == null ? "null" : entry.getKey().toString();
                String valueStr = entry.getValue() == null ? "null" : entry.getValue().toString();
                sb.append("\n  ").append(keyStr).append(" = ").append(valueStr);
            }
            saveLog(szTAG, LogUtils.LOG_LEVEL.Debug, sb.toString());
        }
    }

    /**
     * 打印 List 数据（Debug 级别，格式化输出）
     * @param szTAG 标签
     * @param szMessage 日志消息
     * @param list 要打印的 List 数据
     */
    public static <T> void printList(String szTAG, String szMessage, List<T> list) {
        if (isLoggable(szTAG, LogUtils.LOG_LEVEL.Debug) && list != null) {
            StringBuilder sb = new StringBuilder(szMessage);
            sb.append("\n【List 数据】（size=").append(list.size()).append("）:");
            for (int i = 0; i < list.size(); i++) {
                T item = list.get(i);
                String itemStr = item == null ? "null" : item.toString();
                sb.append("\n  索引").append(i).append(" = ").append(itemStr);
            }
            saveLog(szTAG, LogUtils.LOG_LEVEL.Debug, sb.toString());
        }
    }

    // ================================= 私有工具方法（异常/堆栈信息格式化） =================================
    /**
     * 格式化异常信息（提取异常类型、消息、简化堆栈）
     * @param e 异常对象
     * @return 格式化后的异常字符串
     */
    private static String getExceptionInfo(Exception e) {
        if (e == null) {
            return "异常对象为null";
        }
        StringBuilder sb = new StringBuilder();
        // 异常类型 + 异常消息
        sb.append(e.getClass().getSimpleName()).append(" : ").append(e.getMessage() == null ? "无异常消息" : e.getMessage());
        // 简化堆栈（取前5行，避免日志过长）
        StackTraceElement[] stackTrace = e.getStackTrace();
        if (stackTrace != null && stackTrace.length > 0) {
            sb.append("\n  简化堆栈（前5行）:");
            int limit = Math.min(stackTrace.length, 5);
            for (int i = 0; i < limit; i++) {
                sb.append("\n    ").append(stackTrace[i].toString());
            }
        }
        return sb.toString();
    }

    /**
     * 格式化堆栈信息（提取关键调用链路）
     * @param stackTrace 堆栈数组
     * @return 格式化后的堆栈字符串
     */
    private static String getStackTraceInfo(StackTraceElement[] stackTrace) {
        if (stackTrace == null || stackTrace.length == 0) {
            return "堆栈信息为空";
        }
        StringBuilder sb = new StringBuilder();
        // 过滤 LogUtils 内部调用，取真实业务调用链路（前8行）
        int count = 0;
        for (StackTraceElement element : stackTrace) {
            // 跳过 LogUtils 自身的堆栈（避免冗余）
            if (element.getClassName().contains("cc.winboll.studio.libappbase.LogUtils")) {
                continue;
            }
            sb.append("\n    ").append(element.getClassName()).append(".")
				.append(element.getMethodName()).append("(")
				.append(element.getFileName()).append(":").append(element.getLineNumber()).append(")");
            count++;
            if (count >= 8) { // 限制堆栈长度，避免日志过大
                break;
            }
        }
        return sb.toString();
    }

    // ================================= 原有核心方法（保留并优化） =================================
    /**
     * 日志文件保存函数（优化：增加异常捕获完整性，避免流泄漏）
     * @param szTAG 标签
     * @param logLevel 日志级别
     * @param szMessage 日志消息
     */
    static void saveLog(String szTAG, LogUtils.LOG_LEVEL logLevel, String szMessage) {
        BufferedWriter out = null;
        try {
            // 确保日志文件存在（创建父目录 + 文件）
            if (!_mfLogCatchFile.exists()) {
                File parentDir = _mfLogCatchFile.getParentFile();
                if (parentDir != null && !parentDir.exists()) {
                    parentDir.mkdirs();
                }
                _mfLogCatchFile.createNewFile();
            }
            // 追加写入日志（UTF-8编码，避免中文乱码）
            out = new BufferedWriter(new OutputStreamWriter(
										 new FileOutputStream(_mfLogCatchFile, true), "UTF-8"));
            String logLine = "[" + logLevel + "]  " 
				+ mSimpleDateFormat.format(System.currentTimeMillis()) 
				+ "  [" + szTAG + "]\n" 
				+ szMessage + "\n\n"; // 增加空行，区分不同日志
            out.write(logLine);
            out.flush(); // 强制刷新，确保日志及时写入
        } catch (IOException e) {
            // 日志写入失败时，打印系统日志（避免递归调用）
            android.util.Log.e(TAG, "日志写入失败: " + e.getMessage());
        } finally {
            // 关闭流，避免资源泄漏（Java 7 手动关闭，无 try-with-resources）
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    android.util.Log.e(TAG, "流关闭失败: " + e.getMessage());
                }
            }
        }
    }

    /**
     * 历史日志加载函数（优化：增加流关闭，避免内存泄漏）
     * @return 日志内容字符串（空串表示无日志）
     */
    public static String loadLog() {
        if (_mfLogCatchFile == null || !_mfLogCatchFile.exists()) {
            return "日志文件不存在";
        }
        StringBuffer sb = new StringBuffer();
        BufferedReader in = null;
        try {
            in = new BufferedReader(new InputStreamReader(
										new FileInputStream(_mfLogCatchFile), "UTF-8"));
            String line = "";
            while ((line = in.readLine()) != null) {
                sb.append(line);
                sb.append("\n");
            }
        } catch (IOException e) {
            sb.append("日志加载失败: ").append(e.getMessage());
            LogUtils.e(TAG, "日志加载异常", e);
        } finally {
            // 关闭流，避免资源泄漏
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    LogUtils.e(TAG, "流关闭异常", e);
                }
            }
        }
        return sb.toString();
    }

    /**
     * 清理日志函数（优化：支持清空日志，避免文件过大）
     */
    public static void cleanLog() {
        if (_mfLogCatchFile == null) {
            LogUtils.d(TAG, "日志文件未初始化，无需清理");
            return;
        }
        try {
            // 清空文件内容（覆盖写入空字符串）
            BufferedWriter out = new BufferedWriter(new OutputStreamWriter(
														new FileOutputStream(_mfLogCatchFile, false), "UTF-8"));
            out.write("");
            out.flush();
            out.close();
            LogUtils.d(TAG, "日志已清空，文件路径: " + _mfLogCatchFile.getPath());
        } catch (IOException e) {
            LogUtils.e(TAG, "日志清空失败", e);
        }
    }

    /**
     * 检查日志文件大小（新增：避免日志文件过大占用内存）
     * @param maxSizeMB 最大允许大小（MB）
     * @return true：文件超过限制；false：文件大小正常
     */
    public static boolean checkLogFileSize(int maxSizeMB) {
        if (_mfLogCatchFile == null || !_mfLogCatchFile.exists()) {
            return false;
        }
        // 转换为字节（1MB = 1024*1024 字节）
        long maxSizeByte = maxSizeMB * 1024 * 1024;
        long fileSize = _mfLogCatchFile.length();
        LogUtils.d(TAG, String.format("日志文件大小: %.2f MB（限制: %d MB）", 
									  fileSize / (1024.0 * 1024), maxSizeMB));
        return fileSize > maxSizeByte;
    }

    /**
     * 初始化检查（新增：快速判断 LogUtils 是否初始化完成）
     * @return true：已初始化；false：未初始化
     */
    public static boolean isInited() {
        return _IsInited;
    }

    /**
     * 显示短提示（新增：日志+Toast联动，调试时快速提示）
     * @param context 上下文
     * @param message 提示内容
     */
    public static void showShortToast(final Context context, final String message) {
        if (context == null || message == null) {
            return;
        }
        // 主线程显示Toast，避免子线程崩溃
        if (Thread.currentThread().getId() == android.os.Process.myTid()) {
            Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
        } else {
            ((android.app.Activity) context).runOnUiThread(new Runnable() {
					@Override
					public void run() {
						Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
					}
				});
        }
        // 同时写入日志
        LogUtils.d(TAG, "Toast提示: " + message);
    }
}

