package shop.alien.lawyer.util;

import com.alibaba.fastjson.JSONArray;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartRequest;
import shop.alien.entity.store.vo.StoreImgVo;
import shop.alien.lawyer.service.StoreImgService;
import shop.alien.util.ali.AliOSSUtil;
import shop.alien.util.common.RandomCreateUtil;
import shop.alien.util.common.VideoUtils;
import shop.alien.util.file.FileUtil;

import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;

/**
 * 二期-文件上传
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class FileUploadUtil {

    private final VideoUtils videoUtils;

    private final StoreImgService storeImgService;

    @Value("${spring.web.resources.static-locations}")
    private String uploadDir;

    private final AliOSSUtil aliOSSUtil;

    List<String> imageFileType = Arrays.asList("jpg", "jpeg", "png", "bmp", "webp", "gif", "svg");
    List<String> videoFileType = Arrays.asList("mp4", "avi", "flv", "mkv", "rmvb", "wmv", "3gp", "mov");
    List<String> appFileType = Arrays.asList("apk", "ipk", "wgt");

    /**
     * 上传文件
     *
     * @param multipartFile 文件名
     * @return 文件路径
     */
    public String uploadOneFile(MultipartFile multipartFile) {
        try {
            Map<String, String> fileNameAndType = FileUtil.getFileNameAndType(multipartFile);
            String prefix = "";
            if (imageFileType.contains(fileNameAndType.get("type").toLowerCase())) {
                prefix = "image/";
            } else if (videoFileType.contains(fileNameAndType.get("type").toLowerCase())) {
                prefix = "video/";
            }
            return aliOSSUtil.uploadFile(multipartFile, prefix + fileNameAndType.get("name") + RandomCreateUtil.getRandomNum(6) + "." + fileNameAndType.get("type"));
        } catch (Exception e) {
            log.error("FileUpload.uploadOneFile ERROR Msg={}", e.getMessage());
            throw new RuntimeException(e);
        }
    }

    /**
     * 上传app文件
     *
     * @param multipartFile 文件名
     * @return 文件路径
     */
    public String uploadApp(MultipartFile multipartFile) {
        try {
            Map<String, String> fileNameAndType = FileUtil.getFileNameAndType(multipartFile);
            if (!appFileType.contains(fileNameAndType.get("type").toLowerCase())) {
                log.error("FileUpload.uploadApp ERROR 该文件不是app格式文件");
                return null;
            }
            String prefix = "app/";
            return aliOSSUtil.uploadFile(multipartFile, prefix + fileNameAndType.get("name") + RandomCreateUtil.getRandomNum(6) + "." + fileNameAndType.get("type"));
        } catch (Exception e) {
            log.error("FileUpload.uploadApp ERROR Msg={}", e.getMessage());
            return null;
        }
    }

    /**
     * 上传多个文件
     *
     * @param multipartRequest 多文件
     * @return List<String>
     */
    public List<String> uploadMoreFile(MultipartRequest multipartRequest) {
        try {
            log.info("FileUpload.uploadMoreFile multipartRequest={}", multipartRequest.getFileNames());
            Set<String> fileNameSet = multipartRequest.getMultiFileMap().keySet();
            List<String> filePathList = new ArrayList<>();
            for (String s : fileNameSet) {
                MultipartFile multipartFile = multipartRequest.getFileMap().get(s);
                log.info("FileUpload.uploadMoreFile fileName={}", multipartFile.getOriginalFilename());
                String uploadDir = this.uploadDir.replace("file:///", "").replace("\\", "/");
                String prefix;
                Map<String, String> fileNameAndType = FileUtil.getFileNameAndType(multipartFile);
                //区分文件类型
                if (imageFileType.contains(fileNameAndType.get("type").toLowerCase())) {
                    uploadDir += "/image";
                    prefix = "image/";
                    log.info("FileUpload.uploadMoreFile 获取到图片文件准备复制 {} {} {}", uploadDir, prefix, multipartFile.getOriginalFilename());
                    filePathList.add(aliOSSUtil.uploadFile(multipartFile, prefix + fileNameAndType.get("name") + RandomCreateUtil.getRandomNum(6) + "." + fileNameAndType.get("type")));
                    ;
                } else if (videoFileType.contains(fileNameAndType.get("type").toLowerCase())) {
                    uploadDir += "/video/";
                    prefix = "video/";
                    //上传视频文件
                    log.info("FileUpload.uploadMoreFile 获取到视频文件准备复制 {} {} {}", uploadDir, prefix, multipartFile.getOriginalFilename());
                    String videoFileName = fileNameAndType.get("name") + RandomCreateUtil.getRandomNum(6);
                    String cacheVideoPath = copyFile(uploadDir, multipartFile);
                    filePathList.add(aliOSSUtil.uploadFile(multipartFile, prefix + videoFileName + "." + fileNameAndType.get("type")));
                    //缓存视频截图使用
                    File videoFile = new File(cacheVideoPath);
                    //获取视频某帧截图
                    log.info("FileUpload.uploadMoreFile 视频文件复制完毕, 获取第一秒图片 {}", videoFile.getName());
                    String videoPath = videoUtils.getImg(uploadDir + videoFile.getName());
                    log.info("FileUpload.uploadMoreFile 视频文件复制完毕, 图片位置 {}", videoPath);
                    if (!videoPath.isEmpty()) {
                        File videoImgFile = new File(videoPath);
                        Map<String, String> videoImg = FileUtil.getFileNameAndType(videoImgFile);
                        filePathList.add(aliOSSUtil.uploadFile(videoImgFile, prefix + videoFileName + "." + videoImg.get("type")));
                        videoImgFile.delete();
                        videoFile.delete();
                    } else {
                        throw new RuntimeException("视频截图失败");
                    }
                }
            }
            return filePathList;
        } catch (Exception e) {
            log.error("FileUpload.uploadMoreFile ERROR Msg={}", e.getMessage());
            throw new RuntimeException(e);
        }
    }

    /**
     * 上传图片
     *
     * @param multipartRequest 文件
     * @param list             图片List
     * @return 图片id
     */
    public List<Integer> uploadImg(MultipartRequest multipartRequest, String list) {
        JSONArray jsonArray = JSONArray.parseArray(list);
        List<StoreImgVo> storeImgList = jsonArray.toJavaList(StoreImgVo.class);
        List<Integer> resultList = new ArrayList<>();
        Set<String> fileNameSet = multipartRequest.getMultiFileMap().keySet();
        if (fileNameSet.size() != storeImgList.size()) {
            log.error("FileUpload.uploadImg ERROR 文件数量与参数数量不匹配 fileNameSet{}, storeImgList={}", fileNameSet.size(), storeImgList.size());
            throw new RuntimeException("文件数量与参数数量不匹配");
        }
        //匹配文件与数据
        for (String s : fileNameSet) {
            String[] split = s.split("_");
            int index = Integer.parseInt(split[1]);
            storeImgList.get(index).setName(s);
        }
        for (StoreImgVo storeImgVo : storeImgList) {
            //获取文件
            MultipartFile multipartFile = multipartRequest.getFileMap().get(storeImgVo.getName());
            Map<String, String> fileInfo = FileUtil.getFileNameAndType(multipartFile);
            String videoFileName = fileInfo.get("name") + RandomCreateUtil.getRandomNum(6);
            String prefix;
            String filePath = "";
            if (imageFileType.contains(fileInfo.get("type").toLowerCase())) {
                prefix = "image/";
                filePath = aliOSSUtil.uploadFile(multipartFile, prefix + videoFileName + "." + fileInfo.get("type"));
            } else if (videoFileType.contains(fileInfo.get("type").toLowerCase())) {
                prefix = "video/";
                filePath = aliOSSUtil.uploadFile(multipartFile, prefix + videoFileName + "." + fileInfo.get("type"));
            }
            storeImgVo.setImgUrl(filePath);
            storeImgService.save(storeImgVo);
            resultList.add(storeImgVo.getId());
        }
        return resultList;
    }

    /**
     * 复制文件, 返回url链接
     *
     * @param localFilePath 本地路径
     * @param file          文件
     * @return 访问url路径
     */
    private String copyFile(String localFilePath, MultipartFile file) {
        try {
            File cacheFilePath = new File(localFilePath);
            if (!cacheFilePath.exists()) {
                cacheFilePath.mkdirs();
            }
            String fileName = file.getOriginalFilename().substring(0, file.getOriginalFilename().lastIndexOf('.'));
            log.info("FileUpload.copyFile fileName={}", fileName);
            String fileType = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf('.'));
            log.info("FileUpload.copyFile fileType={}", fileType);
            System.out.println(file.getOriginalFilename());
            Path path = Paths.get(localFilePath, file.getOriginalFilename());
            Files.createDirectories(path.getParent());
            Files.write(path, file.getBytes());
            return localFilePath + file.getOriginalFilename();
        } catch (Exception e) {
            log.error("FileUpload.copyFile ERROR Msg={}", e.getMessage());
            return e.getMessage();
        }
    }

    private String copyFile(String localFilePath, String urlPath, MultipartFile file) {
        try {
            String fileName = file.getOriginalFilename().substring(0, file.getOriginalFilename().lastIndexOf('.'));
            log.info("FileUpload.copyFile fileName={}", fileName);
            String fileType = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf('.'));
            log.info("FileUpload.copyFile fileType={}", fileType);
            String newFileName = fileName + RandomCreateUtil.getRandomNum(6) + fileType;
            log.info("FileUpload.copyFile newFileName={}", newFileName);
            newFileName = newFileName.replaceAll(",", "");
            log.info("FileUpload.copyFile newFileName={}", newFileName);
            Path path = Paths.get(localFilePath, newFileName);
            Files.createDirectories(path.getParent());
            Files.write(path, file.getBytes());
            return urlPath + newFileName;
        } catch (Exception e) {
            log.error("FileUpload.copyFile ERROR Msg={}", e.getMessage());
            return e.getMessage();
        }
    }

}
