package com.yeechart.dotMatrix.oss;


import com.yeechart.dotMatrix.signage.bean.mizilzo.BitmapDataVo;
import com.yeechart.dotMatrix.signage.bean.mizilzo.MiniLZOVo;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

/**
 * OSS 上传文件
 */
@Component
@Slf4j
public class LatticeOSSUpload {

    @Autowired
    private OSSUpload ossUpload;
        @javax.annotation.Resource
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;
    private Map<String, ConcurrentHashMap<String, CompletableFuture<String>>> deviceConcurrentHashMap = new HashMap<>();
    private Map<String, Map<String, BitmapDataVo>> bitmapDataVoMap = new HashMap<>();


    /**
     * 批量文件上传
     *
     * @param deID
     * @throws InterruptedException
     */
    public CompletableFuture<Void> uploadImages(String deID, List<BitmapDataVo> bitmapDataVoList) {
        if (bitmapDataVoList == null || bitmapDataVoList.isEmpty()) {
            return CompletableFuture.completedFuture(null);
        }

        ConcurrentHashMap<String, CompletableFuture<String>> imageUploadFutures = new ConcurrentHashMap<>();

        Map<String, BitmapDataVo> bitmapDataVoMap1 = new HashMap<>();

        for (BitmapDataVo bitmapDataVo : bitmapDataVoList) {

            Map<String, MiniLZOVo> miniLZOVoList = bitmapDataVo.getMiniLZOVoList();

            String path = bitmapDataVo.getPath();

            for (Map.Entry<String, MiniLZOVo> entry : miniLZOVoList.entrySet()) {
                String fileName = entry.getKey();
                MiniLZOVo miniLZOVo = entry.getValue();
                byte[] data = miniLZOVo.getData();

                String finalFileName = path + "/" + fileName;

                CompletableFuture<String> future = new CompletableFuture<>();
                imageUploadFutures.put(finalFileName, future);

                threadPoolTaskExecutor.execute(() -> {
                    try {
                        ossUpload.enqueueUploadWithRetryAndCallback(data, finalFileName,
                                future::complete,
                                future::completeExceptionally);
                    } catch (Exception e) {
                        future.completeExceptionally(e);
                    }
                });

            }


            bitmapDataVoMap1.put(path, bitmapDataVo);


        }

        deviceConcurrentHashMap.put(deID, imageUploadFutures);
        bitmapDataVoMap.put(deID, bitmapDataVoMap1);
//        System.out.println("总共要传输的次数 " + imageUploadFutures.size() );
        // 等待所有上传完成并处理结果
        CompletableFuture<Void> allUploadsFuture = CompletableFuture.allOf(imageUploadFutures.values().toArray(new CompletableFuture[0]))
                .thenAcceptAsync(v -> handleAllUploadsCompleted(deID), threadPoolTaskExecutor); // 使用线程池执行handleAllUploadsCompleted
        //.thenAcceptAsync(unused -> { /* 这里可以添加处理完成后的其他逻辑，如果有的话 */ }, threadPoolTaskExecutor);

        return allUploadsFuture;
    }

    private void handleAllUploadsCompleted(String deID) {
        // 收集所有成功的URL
        List<String> successfulUris = new ArrayList<>();
        ConcurrentHashMap<String, CompletableFuture<String>> imageUploadFutures = deviceConcurrentHashMap.get(deID);

        for (Map.Entry<String, CompletableFuture<String>> entry : imageUploadFutures.entrySet()) {
            String imageName = entry.getKey();
            CompletableFuture<String> future = entry.getValue();
            try {
                String url = future.get();
                successfulUris.add(url);
            } catch (Exception e) {
                // 处理失败的情况
                System.out.println("上传文件失败:" + imageName + " 异常为:" + e);

            }
        }

        // 处理成功URIs
        List<String> basePaths = successfulUris.stream()
//                .map(uri -> uri
//                {
//                    String afterDevice = uri.substring(uri.indexOf("device"));
//                    afterDevice = afterDevice.substring(0, afterDevice.lastIndexOf('/'));
//                    return afterDevice;
//                }
//                )
                .distinct() // 去重，确保每个path只更新一次
                .collect(Collectors.toList());

        // 更新BitmapDataVo的path属性
        Map<String, BitmapDataVo> bitmapDataVoMapForDeID = bitmapDataVoMap.get(deID);
        if (bitmapDataVoMapForDeID != null) {
            basePaths.forEach(basePath -> {

                try {

                    URL url = new URL(basePath);
                    String fullPath = url.getPath(); // 获取完整路径
                    fullPath = fullPath.substring(1);//去掉前面的"/"

                    int lastSlashIndex = fullPath.lastIndexOf('/');
                    String directoryPath = fullPath.substring(0, lastSlashIndex); // +1则保留末尾的 "/"
                    BitmapDataVo bitmapDataVo = bitmapDataVoMapForDeID.get(directoryPath);
                    if (bitmapDataVo != null && !bitmapDataVo.getPath().startsWith("http")) {
                        String afterDevice = basePath.substring(0, basePath.indexOf("device"));
                        bitmapDataVo.setPath(afterDevice + directoryPath);
                    }

                } catch (MalformedURLException e) {
                    System.out.println("uri转换异常 basePath：" + basePath);
                }


            });
        }


        //然后清除数据
        deviceConcurrentHashMap.remove(deID);
        bitmapDataVoMap.remove(deID);

    }


    /**
     * 删除指定文件夹及其子文件夹中的所有文件
     *
     * @param folderPath 文件夹路径前缀
     */
    public void deleteFolderAndSubFolders(String folderPath) {
        // 列出指定前缀的所有文件
        CompletableFuture<Map<String, byte[]>> fileContentsFuture = listFilesByPath(folderPath);

        fileContentsFuture.thenAcceptAsync(fileContents -> {
            // 遍历所有文件并逐个删除
            for (String filePath : fileContents.keySet()) {
                ossUpload.deleteFile(folderPath+filePath);
            }
        }, threadPoolTaskExecutor);
    }

    /**
     * 删除指定设备ID下的所有已上传文件
     */
    public void deleteFilePaths(List<String> filePaths) {
        for (String filePath : filePaths) {
            ossUpload.deleteFile(filePath);
        }
    }

    /**
     * 查询指定路径下的所有文件内容
     *
     * @param path 文件路径前缀
     * @return 匹配该路径前缀的所有文件内容 < 原始文件大小/文件名 , 文件内容 >
     */
    public CompletableFuture<Map<String, byte[]>> listFilesByPath(String path) {

        // 假设ossUpload有一个方法listFilesByPrefix用于列出指定前缀的所有文件
        try {
            URL url = new URL(path);
            String fullPath = url.getPath(); // 获取完整路径
//            int lastSlashIndex = fullPath.lastIndexOf('/');
//            String directoryPath = fullPath.substring(0, lastSlashIndex + 1); // 保留末尾的 "/"
            String directoryPath = fullPath.substring(1);//去掉前面的"/"


            // 假设ossUpload有一个异步方法用于列出指定前缀的所有文件内容
            CompletableFuture<Map<String, byte[]>> fileContentsFuture = ossUpload.getFileContentsByPrefix(directoryPath);

            // 使用thenApply处理成功情况，直接返回结果
            return fileContentsFuture.thenApply(future -> future);


        } catch (Exception e) {
            System.out.println("获取指定文件路径 " + path + " 下的所有文件出现异常: " + e.getMessage());

        }
        return CompletableFuture.completedFuture(null);
    }


}
