package cc.winboll.studio.powerbell.utils;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.media.ExifInterface;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.text.TextUtils;
import androidx.core.content.FileProvider;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.ToastUtils;
import cc.winboll.studio.powerbell.BuildConfig;
import cc.winboll.studio.powerbell.R;
import cc.winboll.studio.powerbell.models.BackgroundBean;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;

/**
 * @Author ZhanGSKen<zhangsken@qq.com>
 * @Date 2024/07/18 12:07:20
 * @Describe 背景图片工具集（精简版：复用FileUtils，聚焦业务逻辑）
 */
public class BackgroundSourceUtils {

    public static final String TAG = "BackgroundSourceUtils";
    // 裁剪相关常量（统一定义，避免硬编码）
    private static final String CROP_CACHE_DIR_NAME = "cache";
    private static final String CROP_TEMP_FILE_NAME = "SourceCropTemp.jpg";
    private static final String CROP_RESULT_FILE_NAME = "SourceCropped.jpg";
    public static final String FILE_PROVIDER_AUTHORITY = BuildConfig.APPLICATION_ID + ".fileprovider";
    // 图片操作基础目录
    private static final String PICTURE_BASE_DIR = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + File.separator + "PowerBell";
    private static final String SOURCE_DIR_NAME = "BackgroundSource";
    private static final String COMPRESS_DIR_NAME = "BackgroundCompress";

    // 单例相关
    private static volatile BackgroundSourceUtils sInstance;
    private Context mContext;
    private File currentBackgroundBeanFile;
    private BackgroundBean currentBackgroundBean;
    private File previewBackgroundBeanFile;
    private BackgroundBean previewBackgroundBean;

    // 目录文件相关
    private File fPictureBaseDir;
    private File fCropCacheDir;
    private File fBackgroundSourceDir;
    private File fBackgroundCompressDir;
    private File fUtilsDir;
    private File fModelDir;
    private File mCropSourceFile;
    private File mCropResultFile;

    // 双重校验锁单例
    private BackgroundSourceUtils(Context context) {
        if (sInstance != null) {
            throw new RuntimeException("BackgroundSourceUtils 是单例类，禁止重复创建！");
        }
        this.mContext = context.getApplicationContext();
        initNecessaryDirs();
        initAllFiles();
        loadSettings();
    }

    public static BackgroundSourceUtils getInstance(Context context) {
        if (sInstance == null) {
            synchronized (BackgroundSourceUtils.class) {
                if (sInstance == null) {
                    sInstance = new BackgroundSourceUtils(context);
                }
            }
        }
        return sInstance;
    }

    /**
     * 统一初始化所有必要目录
     */
    private void initNecessaryDirs() {
        LogUtils.d(TAG, "【目录初始化】开始创建所有必要目录");
        initPictureDirs();
        initJsonDirs();
        LogUtils.d(TAG, "【目录初始化】所有必要目录创建完成");
    }

    /**
     * 初始化图片操作目录
     */
    private void initPictureDirs() {
        fPictureBaseDir = new File(PICTURE_BASE_DIR);
        fBackgroundSourceDir = new File(fPictureBaseDir, SOURCE_DIR_NAME);
        fCropCacheDir = new File(fPictureBaseDir, CROP_CACHE_DIR_NAME);
        fBackgroundCompressDir = new File(fPictureBaseDir, COMPRESS_DIR_NAME);

        createDirWithPermission(fPictureBaseDir, "图片基础目录");
        createDirWithPermission(fBackgroundSourceDir, "图片存储目录");
        createDirWithPermission(fCropCacheDir, "裁剪缓存目录");
        createDirWithPermission(fBackgroundCompressDir, "压缩图存储目录");

        validatePictureDirs();
    }

    /**
     * 初始化JSON配置目录
     */
    private void initJsonDirs() {
        fUtilsDir = mContext.getExternalFilesDir(TAG);
        if (fUtilsDir == null) {
            LogUtils.e(TAG, "应用外置存储不可用，切换到应用内部缓存目录");
            fUtilsDir = mContext.getDataDir();
        }
        fModelDir = new File(fUtilsDir, "ModelDir");
        createDirWithPermission(fModelDir, "JSON配置目录");

        currentBackgroundBeanFile = new File(fModelDir, "currentBackgroundBean.json");
        previewBackgroundBeanFile = new File(fModelDir, "previewBackgroundBean.json");
    }

    /**
     * 创建目录并校验
     */
    private void createDirWithPermission(File dir, String dirDesc) {
        if (dir == null) {
            LogUtils.e(TAG, dirDesc + "创建失败：目录对象为null");
            return;
        }
        if (!dir.exists()) {
            LogUtils.d(TAG, dirDesc + "不存在，开始创建：" + dir.getAbsolutePath());
            dir.mkdirs();
        }
    }

    /**
     * 校验图片目录是否就绪
     */
    private void validatePictureDirs() {
        boolean allReady = fPictureBaseDir.exists() && fBackgroundSourceDir.exists()
			&& fCropCacheDir.exists() && fBackgroundCompressDir.exists();
        if (allReady) {
            LogUtils.d(TAG, "所有图片目录均已就绪");
        } else {
            LogUtils.e(TAG, "部分图片目录未就绪，可能影响后续功能");
        }
    }

    /**
     * 初始化所有文件
     */
    private void initAllFiles() {
        clearCropTempFiles();
        LogUtils.d(TAG, "文件初始化完成");
    }

    /**
     * 将File转为ContentUri
     */
    public Uri getFileProviderUri(File file) {
        LogUtils.d(TAG, "【getFileProviderUri调用】文件路径：" + file.getAbsolutePath());
        Uri contentUri = null;
        try {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                contentUri = FileProvider.getUriForFile(mContext, FILE_PROVIDER_AUTHORITY, file);
                LogUtils.d(TAG, "7.0+ 生成ContentUri：" + contentUri.toString());
            } else {
                contentUri = Uri.fromFile(file);
                LogUtils.d(TAG, "7.0以下 生成FileUri：" + contentUri.toString());
            }
        } catch (IllegalArgumentException e) {
            LogUtils.e(TAG, "生成Uri失败：" + e.getMessage(), e);
            contentUri = null;
        }
        return contentUri;
    }

    /**
     * 检查背景是否为空并创建空白背景Bean
     */
    public boolean checkEmptyBackgroundAndCreateBlankBackgroundBean(BackgroundBean checkBackgroundBean) {
        LogUtils.d(TAG, "【checkEmptyBackgroundAndCreateBlankBackgroundBean调用】开始检查背景Bean");
        File fCheckBackgroundFile = new File(checkBackgroundBean.getBackgroundFilePath());
        if (!fCheckBackgroundFile.exists()) {
            return createBlankBackgroundBean(checkBackgroundBean.getPixelColor());
        }
        LogUtils.d(TAG, "背景Bean文件存在，无需创建空白背景");
        return false;
    }

	public boolean createBlankBackgroundBean(int nBackgroundPixelColor) {
        String newCropFileName = genNewCropFileName();
		String fileSuffix = "png";
		mCropSourceFile = new File(fCropCacheDir, newCropFileName + "." + fileSuffix);
		mCropResultFile = new File(fCropCacheDir, "SelectCompress_" + newCropFileName + "." + fileSuffix);

		AssetsCopyUtils.copyAssetsFileToDir(mContext, "images/blank100x100.png", mCropSourceFile.getAbsolutePath());
		try {
			mCropResultFile.createNewFile();
		} catch (IOException e) {
			LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
		}

		loadSettings();
		previewBackgroundBean.setPixelColor(nBackgroundPixelColor);
		previewBackgroundBean.setIsUseBackgroundFile(true);
		previewBackgroundBean.setIsUseBackgroundScaledCompressFile(false);
		previewBackgroundBean.setBackgroundFileName(mCropSourceFile.getName());
		previewBackgroundBean.setBackgroundFilePath(mCropSourceFile.getAbsolutePath());
		previewBackgroundBean.setBackgroundScaledCompressFileName(mCropResultFile.getName());
		previewBackgroundBean.setBackgroundScaledCompressFilePath(mCropResultFile.getAbsolutePath());
		saveSettings();
		LogUtils.d(TAG, "背景Bean为空，已创建空白背景并更新配置");
		return true;
    }

	String genNewCropFileName() {
		return UUID.randomUUID().toString() + System.currentTimeMillis();
	}

    /**
     * 创建并更新预览剪裁环境
     */
    public boolean createAndUpdatePreviewEnvironmentForCropping(BackgroundBean oldPreviewBackgroundBean) {
        LogUtils.d(TAG, "【createAndUpdatePreviewEnvironmentForCropping调用】开始初始化预览剪裁环境");
        InputStream is = null;
        FileOutputStream fos = null;
        try {
            clearCropTempFiles();
            if (checkEmptyBackgroundAndCreateBlankBackgroundBean(oldPreviewBackgroundBean)) {
                LogUtils.d(TAG, "空白背景创建成功，直接返回");
                return true;
            }

            Uri uri = UriUtils.getUriForFile(mContext, oldPreviewBackgroundBean.getBackgroundFilePath());
			LogUtils.d(TAG, String.format("createAndUpdatePreviewEnvironmentForCropping: uri %s", uri));
			String fileSuffix = UriUtils.getSuffixFromUri(mContext, uri);
			LogUtils.d(TAG, String.format("createAndUpdatePreviewEnvironmentForCropping: fileSuffix = %s", fileSuffix));
            String newCropFileName = genNewCropFileName();
            mCropSourceFile = new File(fCropCacheDir, newCropFileName + "." + fileSuffix);
            mCropResultFile = new File(fCropCacheDir, "SelectCompress_" + newCropFileName + ".png");

            if (FileUtils.isFileExists(oldPreviewBackgroundBean.getBackgroundScaledCompressFilePath())) {
                FileUtils.copyFile(new File(oldPreviewBackgroundBean.getBackgroundScaledCompressFilePath()), mCropResultFile);
            } else {
                mCropResultFile.createNewFile();
            }

            if (FileUtils.isFileExists(oldPreviewBackgroundBean.getBackgroundFilePath())) {
                FileUtils.copyFile(new File(oldPreviewBackgroundBean.getBackgroundFilePath()), mCropSourceFile);
            } else {
                mCropSourceFile.createNewFile();
                is = mContext.getContentResolver().openInputStream(uri);
                if (is == null) {
                    LogUtils.e(TAG, "ContentResolver打开Uri失败：" + uri.toString());
                    return false;
                }
                fos = new FileOutputStream(mCropSourceFile);
                byte[] buffer = new byte[1024 * 8];
                int readLen;
                while ((readLen = is.read(buffer)) != -1) {
                    fos.write(buffer, 0, readLen);
                }
                fos.flush();
                try {
                    fos.getFD().sync();
                } catch (IOException e) {
                    LogUtils.w(TAG, "文件同步到磁盘失败，flush兜底：" + e.getMessage());
                    fos.flush();
                }
            }

            loadSettings();
            previewBackgroundBean.setBackgroundFileName(mCropSourceFile.getName());
            previewBackgroundBean.setBackgroundFilePath(mCropSourceFile.getAbsolutePath());
            previewBackgroundBean.setBackgroundScaledCompressFileName(mCropResultFile.getName());
            previewBackgroundBean.setBackgroundScaledCompressFilePath(mCropResultFile.getAbsolutePath());
            saveSettings();

            LogUtils.d(TAG, "预览剪裁环境初始化成功");
            LogUtils.d(TAG, "→ 原Uri：" + uri.toString());
            LogUtils.d(TAG, "→ 剪裁数据源：" + mCropSourceFile.getAbsolutePath());
            LogUtils.d(TAG, "→ 剪裁结果文件：" + mCropResultFile.getAbsolutePath());
            return true;
        } catch (Exception e) {
            LogUtils.e(TAG, "预览剪裁环境初始化异常：" + e.getMessage(), e);
            clearCropTempFiles();
            return false;
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    LogUtils.e(TAG, "输入流关闭失败：" + e.getMessage());
                }
            }
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    LogUtils.e(TAG, "输出流关闭失败：" + e.getMessage());
                }
            }
        }
    }

    /**
     * 加载背景配置
     */
    public void loadSettings() {
        currentBackgroundBean = BackgroundBean.loadBeanFromFile(currentBackgroundBeanFile.getAbsolutePath(), BackgroundBean.class);
        if (currentBackgroundBean == null) {
            currentBackgroundBean = new BackgroundBean();
            BackgroundBean.saveBeanToFile(currentBackgroundBeanFile.getAbsolutePath(), currentBackgroundBean);
            LogUtils.d(TAG, "正式背景Bean不存在，已创建新实例");
        }

        previewBackgroundBean = BackgroundBean.loadBeanFromFile(previewBackgroundBeanFile.getAbsolutePath(), BackgroundBean.class);
        if (previewBackgroundBean == null) {
            previewBackgroundBean = new BackgroundBean();
            BackgroundBean.saveBeanToFile(previewBackgroundBeanFile.getAbsolutePath(), previewBackgroundBean);
            LogUtils.d(TAG, "预览背景Bean不存在，已创建新实例");
        }
    }

    // ------------------------------ 对外提供的核心方法 ------------------------------
    public BackgroundBean getCurrentBackgroundBean() {
        return currentBackgroundBean;
    }

    public BackgroundBean getPreviewBackgroundBean() {
        return previewBackgroundBean;
    }

    public String getPreviewBackgroundScaledCompressFilePath() {
        String compressFileName = previewBackgroundBean.getBackgroundScaledCompressFileName();
        if (TextUtils.isEmpty(compressFileName)) {
            LogUtils.e(TAG, "预览压缩背景文件名为空");
            return "";
        }
        File file = new File(fBackgroundCompressDir, compressFileName);
        return file.getAbsolutePath();
    }

    public String getCurrentBackgroundScaledCompressFilePath() {
        String compressFileName = currentBackgroundBean.getBackgroundScaledCompressFileName();
        if (TextUtils.isEmpty(compressFileName)) {
            LogUtils.e(TAG, "正式压缩背景文件名为空");
            return "";
        }
        File file = new File(fBackgroundCompressDir, compressFileName);
        return file.getAbsolutePath();
    }

    /**
     * 保存配置
     */
    public void saveSettings() {
        if (currentBackgroundBean != null && previewBackgroundBean != null) {
            BackgroundBean.saveBeanToFile(currentBackgroundBeanFile.getAbsolutePath(), currentBackgroundBean);
            BackgroundBean.saveBeanToFile(previewBackgroundBeanFile.getAbsolutePath(), previewBackgroundBean);
            LogUtils.d(TAG, "两份背景配置保存成功");
        } else {
            LogUtils.e(TAG, "配置保存失败：current/preview Bean存在空值");
        }
    }

    public String getBackgroundSourceDirPath() {
        return fBackgroundSourceDir.getAbsolutePath();
    }

    public String getBackgroundCompressDirPath() {
        return fBackgroundCompressDir.getAbsolutePath();
    }

    public String getCropCacheDir() {
        return fCropCacheDir.getAbsolutePath();
    }

    public String getFileProviderAuthority() {
        return FILE_PROVIDER_AUTHORITY;
    }

    // ------------------------------ 核心业务方法 ------------------------------
    /**
     * 保存裁剪结果图到预览Bean
     */
    public BackgroundBean saveFileToPreviewBean(File sourceFile, String fileInfo) {
        LogUtils.d(TAG, "【saveFileToPreviewBean调用】源文件路径：" + (sourceFile != null ? sourceFile.getAbsolutePath() : "null"));
        if (sourceFile == null || !sourceFile.exists() || sourceFile.length() <= 0) {
            LogUtils.e(TAG, "源文件无效，拒绝保存");
            return previewBackgroundBean;
        }

        String originalImageDir = mContext.getExternalFilesDir(Environment.DIRECTORY_PICTURES).getAbsolutePath();
        if (sourceFile.getAbsolutePath().contains(originalImageDir)) {
            LogUtils.w(TAG, "禁止复制原图，跳过保存");
            return previewBackgroundBean;
        }

        if (!fBackgroundSourceDir.exists() && !fBackgroundSourceDir.mkdirs()) {
            LogUtils.e(TAG, "BackgroundSource目录创建失败");
            return previewBackgroundBean;
        }

        String uniqueFileName = "bg_" + System.currentTimeMillis() + "_" + sourceFile.getName();
        File targetFile = new File(fBackgroundSourceDir, uniqueFileName);
        if (FileUtils.copyFile(sourceFile, targetFile)) {
            LogUtils.d(TAG, "裁剪结果图保存成功：" + targetFile.getAbsolutePath());
            previewBackgroundBean.setBackgroundFileName(uniqueFileName);
            previewBackgroundBean.setBackgroundFilePath(targetFile.getAbsolutePath());
            previewBackgroundBean.setBackgroundFileInfo(fileInfo);
            previewBackgroundBean.setIsUseBackgroundFile(true);
            saveSettings();
        } else {
            LogUtils.e(TAG, "裁剪结果图复制失败");
        }
        return previewBackgroundBean;
    }

    /**
     * 提交预览背景到正式背景
     */
    public void commitPreviewSourceToCurrent() {
        LogUtils.d(TAG, "【commitPreviewSourceToCurrent调用】开始深拷贝预览Bean到正式Bean");
		//ToastUtils.show("【commitPreviewSourceToCurrent调用】开始深拷贝预览Bean到正式Bean");
        currentBackgroundBean = new BackgroundBean();
        currentBackgroundBean.setBackgroundFileName(previewBackgroundBean.getBackgroundFileName());
        currentBackgroundBean.setBackgroundFilePath(previewBackgroundBean.getBackgroundFilePath());
        currentBackgroundBean.setBackgroundFileInfo(previewBackgroundBean.getBackgroundFileInfo());
        currentBackgroundBean.setIsUseBackgroundFile(previewBackgroundBean.isUseBackgroundFile());
        currentBackgroundBean.setBackgroundScaledCompressFileName(previewBackgroundBean.getBackgroundScaledCompressFileName());
        currentBackgroundBean.setBackgroundScaledCompressFilePath(previewBackgroundBean.getBackgroundScaledCompressFilePath());
        currentBackgroundBean.setIsUseBackgroundScaledCompressFile(previewBackgroundBean.isUseBackgroundScaledCompressFile());
        currentBackgroundBean.setBackgroundWidth(previewBackgroundBean.getBackgroundWidth());
        currentBackgroundBean.setBackgroundHeight(previewBackgroundBean.getBackgroundHeight());
        currentBackgroundBean.setPixelColor(previewBackgroundBean.getPixelColor());

        String previewFileName = previewBackgroundBean.getBackgroundFileName();
        String previewCropFileName = previewBackgroundBean.getBackgroundScaledCompressFileName();
        File previewFile = new File(previewBackgroundBean.getBackgroundFilePath());
        File previewCropFile = new File(previewBackgroundBean.getBackgroundScaledCompressFilePath());
        File currentFile = new File(fBackgroundSourceDir, previewFileName);
        File currentCropFile = new File(fBackgroundCompressDir, previewCropFileName);
        FileUtils.copyFile(previewFile, currentFile);
        FileUtils.copyFile(previewCropFile, currentCropFile);
        currentBackgroundBean.setBackgroundFilePath(currentFile.getAbsolutePath());
        currentBackgroundBean.setBackgroundScaledCompressFilePath(currentCropFile.getAbsolutePath());

        saveSettings();
        LogUtils.d(TAG, "预览背景提交到正式背景成功，两份实例完全独立");
        ToastUtils.show("背景图片应用成功");
    }

    /**
     * 将正式背景同步到预览背景
     */
    public void setCurrentSourceToPreview() {
        LogUtils.d(TAG, "【setCurrentSourceToPreview调用】开始深拷贝正式Bean到预览Bean");
        previewBackgroundBean = new BackgroundBean();
        previewBackgroundBean.setBackgroundFileName(currentBackgroundBean.getBackgroundFileName());
        previewBackgroundBean.setBackgroundFilePath(currentBackgroundBean.getBackgroundFilePath());
        previewBackgroundBean.setBackgroundFileInfo(currentBackgroundBean.getBackgroundFileInfo());
        previewBackgroundBean.setIsUseBackgroundFile(currentBackgroundBean.isUseBackgroundFile());
        previewBackgroundBean.setBackgroundScaledCompressFileName(currentBackgroundBean.getBackgroundScaledCompressFileName());
        previewBackgroundBean.setBackgroundScaledCompressFilePath(currentBackgroundBean.getBackgroundScaledCompressFilePath());
        previewBackgroundBean.setIsUseBackgroundScaledCompressFile(currentBackgroundBean.isUseBackgroundScaledCompressFile());
        previewBackgroundBean.setBackgroundWidth(currentBackgroundBean.getBackgroundWidth());
        previewBackgroundBean.setBackgroundHeight(currentBackgroundBean.getBackgroundHeight());
        previewBackgroundBean.setPixelColor(currentBackgroundBean.getPixelColor());

        saveSettings();
        LogUtils.d(TAG, "正式背景同步到预览背景成功");
    }

    /**
     * 清理单个旧文件
     */
    private void clearOldFile(File file, String fileDesc) {
        if (file == null) {
            return;
        }
        if (file.exists()) {
            file.delete();
            LogUtils.d(TAG, fileDesc + "已删除");
        }
    }

    /**
     * 清理裁剪临时文件
     */
    void clearCropTempFiles() {
        File[] files = fCropCacheDir.listFiles();
        if (files == null) {
            return;
        }
        for (File file : files) {
            clearOldFile(file, "旧裁剪缓存文件：" + file.getAbsolutePath());
        }
        mCropSourceFile = null;
        mCropResultFile = null;
    }

    /**
     * 复制文件
     */
    public boolean copyFile(File source, File target) {
        LogUtils.d(TAG, "【copyFile调用】源文件：" + (source != null ? source.getAbsolutePath() : "null") + " 目标：" + (target != null ? target.getAbsolutePath() : "null"));
        if (source == null || TextUtils.isEmpty(source.getPath()) || (source.exists() && source.length() <= 0)) {
            if (target == null) {
                LogUtils.e(TAG, "目录创建失败：目标对象为null");
                return false;
            }
            File targetDir = target.isFile() ? target.getParentFile() : target;
            createDirWithPermission(targetDir, "空源文件场景-目录创建");
            LogUtils.d(TAG, "空源文件场景，目录创建完成");
            return true;
        }
        return FileUtils.copyFile(source, target);
    }

    /**
     * 获取目录类型描述
     */
    public String getDirTypeDesc(File dir) {
        if (dir == null) {
            return "未知目录（null）";
        }
        String dirPath = dir.getAbsolutePath();
        String publicPicturePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsolutePath();
        String externalFilesPath = mContext.getExternalFilesDir(null) != null ? mContext.getExternalFilesDir(null).getAbsolutePath() : "";
        String cachePath = mContext.getCacheDir().getAbsolutePath();

        if (!TextUtils.isEmpty(publicPicturePath)) {
            if (dirPath.contains(publicPicturePath + File.separator + "PowerBell" + File.separator + COMPRESS_DIR_NAME)) {
                return "系统公共图片目录（/Pictures/PowerBell/BackgroundCompress，压缩图统一存储目录）";
            } else if (dirPath.contains(publicPicturePath + File.separator + "PowerBell")) {
                return "系统公共图片目录（/Pictures/PowerBell，图片存储/裁剪目录）";
            }
        } else if (!TextUtils.isEmpty(externalFilesPath) && dirPath.contains(externalFilesPath)) {
            return "应用私有外部目录（getExternalFilesDir()，JSON配置目录）";
        } else if (dirPath.contains(cachePath)) {
            return "应用内部缓存目录（getCacheDir()，兜底目录）";
        } else {
            return "外部存储目录（非应用私有，权限受限）";
        }
        return "未知目录";
    }

    /**
     * 迁移旧压缩图路径到新目录
     */
    private void migrateCompressPathToNewDir(BackgroundBean bean, boolean isCurrentBean) {
        LogUtils.d(TAG, "【migrateCompressPathToNewDir调用】开始迁移" + (isCurrentBean ? "正式" : "预览") + "Bean压缩路径");
        String oldCompressPath = bean.getBackgroundScaledCompressFilePath();
        String beanType = isCurrentBean ? "正式Bean" : "预览Bean";

        if (TextUtils.isEmpty(oldCompressPath) || oldCompressPath.contains(fBackgroundCompressDir.getAbsolutePath())) {
            LogUtils.d(TAG, beanType + "无需迁移：旧路径为空或已在目标目录");
            return;
        }

        File oldCompressFile = new File(oldCompressPath);
        if (!oldCompressFile.exists() || !oldCompressFile.isFile() || oldCompressFile.length() <= 0) {
            LogUtils.w(TAG, beanType + "旧压缩文件无效，无需迁移：" + oldCompressPath);
            String compressFileName = bean.getBackgroundScaledCompressFileName();
            if (!TextUtils.isEmpty(compressFileName)) {
                File newCompressFile = new File(fBackgroundCompressDir, compressFileName);
                bean.setBackgroundScaledCompressFilePath(newCompressFile.getAbsolutePath());
                saveSettings();
                LogUtils.d(TAG, beanType + "压缩路径已重置到目标目录");
            }
            return;
        }

        String compressFileName = bean.getBackgroundScaledCompressFileName();
        if (TextUtils.isEmpty(compressFileName)) {
            compressFileName = "ScaledCompress_" + System.currentTimeMillis() + ".jpg";
        }
        File newCompressFile = new File(fBackgroundCompressDir, compressFileName);

        boolean copySuccess = FileUtils.copyFile(oldCompressFile, newCompressFile);
        if (copySuccess) {
            bean.setBackgroundScaledCompressFilePath(newCompressFile.getAbsolutePath());
            saveSettings();
            clearOldFile(oldCompressFile, beanType + "旧压缩文件（迁移后清理）");
            LogUtils.d(TAG, beanType + "压缩路径迁移成功：" + oldCompressPath + " → " + newCompressFile.getAbsolutePath());
        } else {
            LogUtils.e(TAG, beanType + "压缩文件复制失败，迁移终止");
        }
    }

    /**
     * 获取图片旋转角度
     */
    public int getImageRotateAngle(String imagePath) {
        LogUtils.d(TAG, "【getImageRotateAngle调用】图片路径：" + imagePath);
        if (TextUtils.isEmpty(imagePath)) {
            LogUtils.e(TAG, "图片路径为空");
            return 0;
        }
        File imageFile = new File(imagePath);
        if (!imageFile.exists() || !imageFile.isFile() || imageFile.length() <= 0) {
            LogUtils.e(TAG, "图片文件无效：" + imagePath);
            return 0;
        }

        InputStream inputStream = null;
        try {
            inputStream = new FileInputStream(imageFile);
            ExifInterface exifInterface = new ExifInterface(inputStream);
            int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
            switch (orientation) {
                case ExifInterface.ORIENTATION_ROTATE_90:
                    return 90;
                case ExifInterface.ORIENTATION_ROTATE_180:
                    return 180;
                case ExifInterface.ORIENTATION_ROTATE_270:
                    return 270;
                default:
                    return 0;
            }
        } catch (IOException e) {
            LogUtils.w(TAG, "读取EXIF异常：" + e.getMessage());
            return 0;
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    LogUtils.e(TAG, "流关闭失败：" + e.getMessage());
                }
            }
        }
    }

    /**
     * 压缩图片并保存（默认路径）
     */
    public void compressQualityToRecivedPicture(Bitmap bitmap) {
        LogUtils.d(TAG, "【compressQualityToRecivedPicture调用】使用默认路径压缩图片");
        String defaultCompressPath = getPreviewBackgroundScaledCompressFilePath();
        compressQualityToRecivedPicture(bitmap, defaultCompressPath);
    }

    /**
     * 压缩图片并保存（指定路径）
     */
    public void compressQualityToRecivedPicture(Bitmap bitmap, String targetCompressPath) {
        LogUtils.d(TAG, "【compressQualityToRecivedPicture调用】指定路径压缩图片，目标路径：" + targetCompressPath);
        if (bitmap == null || bitmap.isRecycled()) {
            ToastUtils.show("压缩失败：图片为空");
            LogUtils.e(TAG, "Bitmap为空或已回收");
            return;
        }

        OutputStream outStream = null;
        FileOutputStream fos = null;
        try {
            LogUtils.d(TAG, "Bitmap原始大小：" + bitmap.getByteCount() / 1024 + "KB");
            File targetCompressFile = new File(targetCompressPath);
            if (targetCompressFile.exists()) {
                targetCompressFile.delete();
            }
            targetCompressFile.createNewFile();

            fos = new FileOutputStream(targetCompressFile);
            outStream = new BufferedOutputStream(fos);
            boolean compressSuccess = bitmap.compress(Bitmap.CompressFormat.JPEG, 80, outStream);
            outStream.flush();
            try {
                fos.getFD().sync();
                LogUtils.d(TAG, "图片已强制同步到磁盘");
            } catch (IOException e) {
                LogUtils.w(TAG, "sync失败，flush兜底：" + e.getMessage());
                outStream.flush();
            }

            LogUtils.d(TAG, "图片压缩" + (compressSuccess ? "成功" : "失败") + "，大小：" + targetCompressFile.length() / 1024 + "KB");
            ToastUtils.show(compressSuccess ? "图片压缩成功" : "图片压缩失败");
        } catch (IOException e) {
            LogUtils.e(TAG, "图片压缩IO异常：" + e.getMessage(), e);
            ToastUtils.show("图片压缩失败");
        } finally {
            if (outStream != null) {
                try {
                    outStream.close();
                } catch (IOException e) {
                    LogUtils.e(TAG, "BufferedOutputStream关闭失败：" + e.getMessage());
                }
            }
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    LogUtils.e(TAG, "FileOutputStream关闭失败：" + e.getMessage());
                }
            }
            if (bitmap != null && !bitmap.isRecycled()) {
                bitmap.recycle();
            }
        }
    }
}

