package com.scpyun.platform.jilinsscgsdp.service.impl;

import cn.hutool.json.JSONUtil;
import com.obs.services. ObsClient;
import com.obs.services.model.ObsObject;
import com.obs.services.model.PutObjectRequest;
import com.obs.services.model.PutObjectResult;
import com.scpyun.base.core.annotation.Api;
import com.scpyun.base.core.annotation.ApiOperation;
import com.scpyun.base.core.exception.CustomException;
import com.scpyun.base.core.utils.Global;
import com.scpyun.base.core.utils.StringUtils;
import com.scpyun.base.db.service.CommonService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @Author liu
 * @Date 2024/6/18 13:22
 * @PackageName:com.scpyun.platform.jilinsscgsdp.service.impl
 * @ClassName: UploadServiceImpl
 * @Description: TODO
 * @Version 1.0
 */
@Api("文件上传")
@Service("uploadService")
public class UploadServiceImpl {

    private String localUrl = Global.getConfig("obs.upload.local.path");
    private String showPoint = Global.getConfig("obs.showPoint");
    private String bucketName = Global.getConfig("obs.bucketName");

    @Autowired
    CommonService commonService;

    private String nameSpace = "com.scpyun.platform.standard.jilinsscgsdp.attach.";

    @Autowired
    private ObsClient obsClient;

    public static final DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");

    /**
     * 上传文件到obs 流上传
     *
     * @param file 文件
     * @return obs上传记录
     */
    @ApiOperation(value = "文件上传（首选）", desc = "文件上传（首选）")
    public Map<String, Object> uploadFile(Map<String, Object> map, MultipartFile file) {
        String filename = file.getOriginalFilename();
        String suffix = filename.substring(filename.lastIndexOf(".") + 1);
        String fileSize = String.format("%.2f", (double) file.getSize() / 1024 / 1024) + "MB";
        String fileUuid = UUID.randomUUID().toString();
//        PutObjectRequest request = new PutObjectRequest(bucketName, fileUuid.concat(".").concat(suffix));
        PutObjectRequest request = new PutObjectRequest(bucketName, fileUuid);
        InputStream inputStream = null;
        try {
            inputStream = file.getInputStream();
        } catch (IOException e) {
            throw new CustomException("获取文件流失败");
        }
        request.setInput(inputStream);
        PutObjectResult putObjectResult = obsClient.putObject(request);
        String objectUrl = putObjectResult.getObjectUrl();
        //替换obs下载地址ip
        Pattern pattern = Pattern.compile("/");
        Matcher findMatcher = pattern.matcher(objectUrl);
        int number = 0;
        while (findMatcher.find()) {
            number++;
            //当“/”第二次出现时停止
            if (number == 3) {
                break;
            }
        }
        int i = findMatcher.start();
        String downloadUrl = showPoint + objectUrl.substring(i);
        Map<String, Object> returnMap = new HashMap<>();
        returnMap.put("url", downloadUrl);
        returnMap.put("originalFilename", file.getOriginalFilename());
        returnMap.put("bucketName", bucketName);
        returnMap.put("fileSize", fileSize);
        returnMap.put("suffix", suffix);
        returnMap.put("uploadStatus", "1");
        returnMap.put("uuid", fileUuid);
        returnMap.put("business_type", map.get("business_type"));
        if (commonService.insert(nameSpace + "insertObsUploadRecord",returnMap) != 1){
            throw new CustomException("图片上传失败！");
        }
        return returnMap;
    }

    public Map<String, Object> uploadFileForInputStream(Map<String, Object> map, String base64, String fileName) {
        byte[] decodedBytes = Base64.getDecoder().decode(base64);
        InputStream inputStream = new ByteArrayInputStream(decodedBytes);
        String suffix = fileName.substring(fileName.lastIndexOf(".") + 1);
        String fileUuid = UUID.randomUUID().toString();
        PutObjectRequest request = new PutObjectRequest(bucketName, fileUuid);
        request.setInput(inputStream);
        PutObjectResult putObjectResult = obsClient.putObject(request);
        String objectUrl = putObjectResult.getObjectUrl();
        //替换obs下载地址ip
        Pattern pattern = Pattern.compile("/");
        Matcher findMatcher = pattern.matcher(objectUrl);
        int number = 0;
        while (findMatcher.find()) {
            number++;
            if (number == 3) {
                break;
            }
        }
        int i = findMatcher.start();
        String downloadUrl = showPoint + objectUrl.substring(i);
        Map<String, Object> returnMap = new HashMap<>();
        returnMap.put("url", downloadUrl);
        returnMap.put("originalFilename", fileName);
        returnMap.put("bucketName", bucketName);
        returnMap.put("suffix", suffix);
        returnMap.put("uploadStatus", "1");
        returnMap.put("uuid", fileUuid);
        returnMap.put("business_type", map.get("business_type"));
        if (commonService.insert(nameSpace + "insertObsUploadRecord",returnMap) != 1){
            throw new CustomException("图片上传失败！");
        }
        return returnMap;
    }


    /**
     * 上传文件到obs 先到本地服务器 在上传 上传后删除本地服务器数据
     *
     * @param file 文件
     * @return obs上传记录
     */
    @ApiOperation(value = "文件上传（备选）", desc = "文件上传（备选）")
    public Map<String, Object> uploadLocal(Map<String, Object> map, MultipartFile file) {
        String filename = file.getOriginalFilename();
        String suffix = filename.substring(filename.lastIndexOf(".") + 1);
        /* int mbSize
        if (file.getSize() > mbSize * 1024 * 1024) {
            throw new RuntimeException("文件不得大于" + mbSize + "MB");
        }*/
        String fileSize = String.format("%.2f", (double) file.getSize() / 1024 / 1024) + "MB";
        String fileUuid = UUID.randomUUID().toString();
        String url = putFileToLocal(file, fileUuid.concat(".").concat(suffix));
//        PutObjectRequest request = new PutObjectRequest(bucketName, fileUuid.concat(".").concat(suffix));
        PutObjectRequest request = new PutObjectRequest(bucketName, fileUuid);
        request.setFile(new File(url));
        PutObjectResult putObjectResult = obsClient.putObject(request);
        String objectUrl = putObjectResult.getObjectUrl();
        //替换obs下载地址ip
        Pattern pattern = Pattern.compile("/");
        Matcher findMatcher = pattern.matcher(objectUrl);
        int number = 0;
        while (findMatcher.find()) {
            number++;
            //当“/”第二次出现时停止
            if (number == 3) {
                break;
            }
        }
        int i = findMatcher.start();
        String downloadUrl = showPoint + objectUrl.substring(i);
        Map<String, Object> returnMap = new HashMap<>();
        returnMap.put("url", downloadUrl);
        returnMap.put("originalFilename", file.getOriginalFilename());
        returnMap.put("bucketName", bucketName);
        returnMap.put("fileSize", fileSize);
        returnMap.put("suffix", suffix);
        returnMap.put("uploadStatus", "1");
        returnMap.put("uuid", fileUuid);
        deleteFile(url);
        return returnMap;
    }

    @ApiOperation(value = "读取图片uuid变成流返回前端", desc = "读取图片uuid变成流返回前端")
    public List<InputStream> selectObsFileList(Map<String, Object> map) {
        List<InputStream> listStream = new ArrayList<>();
        List<Map<String, Object>> photoList = commonService.findList(nameSpace + "selectEventIdByAttachList", map);
        if (!CollectionUtils.isEmpty(photoList)) {
            try {
                for (Map<String, Object> sub : photoList) {
                    ObsObject obsObject = obsClient.getObject(bucketName, StringUtils.toStr(sub.get("attach_uuid")));
                    //ObsObject.getObjectContent获取的对象输入流一定要显式关闭，否则会造成资源泄露。
                    InputStream obsStream = obsObject.getObjectContent();
                    listStream.add(obsStream);
                    obsStream.close();
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return listStream;
    }

    /*@ApiOperation(value = "读取图片uuid变成流返回前端", desc = "读取图片uuid变成流返回前端",nologin = true)
    public InputStream getViewFile(Map<String, Object> map,HttpServletResponse response) {
        InputStream listStream =null;
        Map<String, Object> selectDisputeResolutionFileInfo = commonService.getObject(nameSpace + "selectDisputeResolutionFileInfo", map);
        try {
            ObsObject obsObject = obsClient.getObject(bucketName, StringUtils.toStr(selectDisputeResolutionFileInfo.get("obs_key")));
            //ObsObject.getObjectContent获取的对象输入流一定要显式关闭，否则会造成资源泄露。
            InputStream obsStream = obsObject.getObjectContent();
            listStream=obsStream;
            obsStream.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return listStream;
    }*/

    @ApiOperation(value = "读取图片uuid变成流返回前端", desc = "读取图片uuid变成流返回前端", nologin = true)
    public void getViewFile(Map<String, Object> map, HttpServletResponse response) {
        Map<String, Object> selectDisputeResolutionFileInfo = commonService.getObject(nameSpace + "selectDisputeResolutionFileInfo", map);
        String obsKey = StringUtils.toStr(selectDisputeResolutionFileInfo.get("obs_key"));

        // 设置响应内容类型为图片类型（例如，JPEG格式）
        response.setContentType("image/jpeg"); // 需要根据实际图片类型进行调整
        response.setHeader("Content-Disposition", "attachment; filename=\"" + selectDisputeResolutionFileInfo.get("file_name") + "\""); // 指定文件名，下载时提示

        try  {
            ObsObject obsObject = obsClient.getObject(bucketName, obsKey);
            InputStream obsStream = obsObject.getObjectContent();
            OutputStream outStream = response.getOutputStream();
            // 将输入流中的数据写入输出流
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = obsStream.read(buffer)) != -1) {
                outStream.write(buffer, 0, bytesRead);
            }
            outStream.flush(); // 确保输出流中的数据被写入
        } catch (IOException e) {
            throw new RuntimeException("Error while downloading the image", e);
        }
    }

    @ApiOperation(value = "桶信息", desc = "桶信息", nologin = true)
    public Object selectObsObjectList() {
        return obsClient.listObjects(bucketName);
    }

    private static final Logger log = LoggerFactory.getLogger(UploadServiceImpl.class);
    private final String TYPE = "jpg,jepg,gif,png";

    @ApiOperation(value = "桶信息", desc = "桶信息")
    public void getObsObject(Map<String, Object> map, HttpServletResponse response) throws IOException {
        ServletOutputStream out = null;
        InputStream obsStream = null;
        ByteArrayOutputStream bos = null;
        if (StringUtils.isEmpty(map.get("uuid"))) {
            throw new CustomException("id不可为空！");
        }
        if (StringUtils.isEmpty(map.get("suffix"))) {
            throw new CustomException("文件类型不可为空！");
        }
        String fileType = StringUtils.toStr(map.get("suffix"));
        try {
            log.info("进入方法 获取uuid=" + map.get("uuid"));
            ObsObject obsObject = obsClient.getObject(bucketName, StringUtils.toStr(map.get("uuid")));
            log.info("进入方法 obs中获取obsObjectJson===" + JSONUtil.toJsonStr(obsObject));
//            obsClient.getObjectMetadata(bucketName, StringUtils.toStr(map.get("uuid")));
            //ObsObject.getObjectContent获取的对象输入流一定要显式关闭，否则会造成资源泄露。
            if (TYPE.contains(fileType)) {
                //图片类型
                response.setContentType("image/" + fileType);
            } else if ("pdf".contains(fileType)) {
                //pdf类型
                response.setContentType("application/pdf");
            } else {
                //自动判断下载文件类型
                response.setContentType("multipart/form-data");
            }
            obsStream = obsObject.getObjectContent();
//            BufferedImage bufferedImage = ImageIO.read(obsStream);
            byte[] b = new byte[1024];
            bos = new ByteArrayOutputStream();
            int len;
            while ((len = obsStream.read(b)) != -1) {
                bos.write(b, 0, len);
            }
            log.info("进入方法ByteArrayOutputStream=======" + bos.toByteArray());
            out = response.getOutputStream();
            out.write(bos.toByteArray());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            obsStream.close();
            bos.flush();
            bos.close();
            out.flush();
            out.close();
        }
    }

    /**
     * 删除OBS文件
     */
    @ApiOperation(value = "文件删除", desc = "文件删除")
    public void deleteObsFile(Map<String, Object> map) {
        obsClient.deleteObject(bucketName, StringUtils.toStr(map.get("uuid")));
    }

    private void deleteFile(String filePath) {
        File file = new File(filePath);
        if (file.exists()) {
            file.delete();
        }
    }

    private String putFileToLocal(MultipartFile file, String fileUuid) {
        String url = localUrl + File.separator + LocalDateTime.now().format(format) + fileUuid;
        String fileRealName = file.getOriginalFilename();
        int pointIndex = fileRealName.lastIndexOf(".");
        String fileSuffix = fileRealName.substring(pointIndex);
        String fileNewName = url.concat(fileSuffix);
        String filePath = "upload";
        File path = new File(filePath);

        if (!path.exists()) {
            path.mkdirs();
        }
        File savedFile = new File(fileNewName);
        try {
            boolean isCreateSuccess = savedFile.createNewFile();
            if (isCreateSuccess) {
                FileUtils.copyInputStreamToFile(file.getInputStream(), savedFile);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return fileNewName;
    }

    /**
     * 获取文件详情
     *
     * @param uniUuid 文件唯一标识
     * @return OBS上传记录
     */
   /* @Override
    public ObsUploadRecord getInfo(String uniUuid) {
        LambdaQueryWrapper<ObsUploadRecord> uploadRecordLambdaQueryWrapper = new QueryWrapper<ObsUploadRecord>()
                .lambda()
                .eq(ObsUploadRecord::getUniUuid, uniUuid)
                .last("LIMIT 1");
        return uploadRecordService.getOne(uploadRecordLambdaQueryWrapper);
    }*/

}
