package com.ruoyi.framework.recovery.service.impl;

import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.ConvertToMultipartFile;
import com.ruoyi.common.utils.FTPUtil;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.common.utils.uuid.UUID;
import com.ruoyi.framework.recovery.domain.RecCommodity;
import com.ruoyi.framework.recovery.domain.RecStores;
import com.ruoyi.framework.recovery.mapper.RecCommodityMapper;
import com.ruoyi.framework.recovery.mapper.RecStoresMapper;
import com.ruoyi.framework.recovery.service.ICommonService;
import lombok.extern.slf4j.Slf4j;
import net.coobird.thumbnailator.Thumbnails;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Objects;

@Service
@Slf4j
public class CommonServiceImpl implements ICommonService {
    @Autowired
    private FTPUtil ftpUtil;

    @Autowired
    private RecCommodityMapper commodityMapper;

    @Autowired
    private RecStoresMapper storesMapper;


    /**
     * 时间格式化
     */
    private final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");

    @Override
    public AjaxResult uploadFile(MultipartFile file, String type, Long id) throws Exception {
        // 高清文件目录，以当天时间为目录
        String filePath = "recovery-hd/" + simpleDateFormat.format(new Date()) + "/";
        // 缩略图文件目录
        String fileThu = "";
        String suffix = Objects.requireNonNull(file.getOriginalFilename()).substring(file.getOriginalFilename().lastIndexOf("."));
        boolean isImg = suffix.equalsIgnoreCase(".jpg") || suffix.equalsIgnoreCase(".jpeg")
                || suffix.equalsIgnoreCase(".png") || suffix.equalsIgnoreCase(".gif");
        if (isImg) {
            fileThu = "recovery-thum/" + simpleDateFormat.format(new Date()) + "/";
        }
        // 生成新的文件名
        String newFileName = UUID.randomUUID() + suffix;
        File toFile = multipartFileToFile(file);
        // 上传至ftp服务器
        if (ftpUtil.uploadToFtp(filePath, newFileName, toFile)) {
            log.info("上传至ftp服务器！");
        } else {
            log.info("上传至ftp服务器失败!");
        }
        // 如果是图片，就上传缩略图
        if (isImg) {
            BufferedImage image = Thumbnails.of(file.getInputStream()).scale(0.7f).outputFormat(suffix.substring(1)).outputQuality(0.5).asBufferedImage();
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            ImageIO.write(image, suffix.substring(1), out);
            // ByteArrayOutputStream 转化为 byte[]
            byte[] byteArray = out.toByteArray();
            //将 byte[] 转为 MultipartFile
            MultipartFile multipartFile = new ConvertToMultipartFile(byteArray, newFileName, file.getOriginalFilename(), suffix.substring(1), byteArray.length);
            File thuFile = multipartFileToFile(multipartFile);
            ftpUtil.uploadToFtp(fileThu, newFileName, thuFile);
        }
        // 新增由前端拼接
        if (null != id) {
            updateDb(filePath + newFileName, fileThu + newFileName, type, id);
        }
        AjaxResult ajax = AjaxResult.success();
        ajax.put("thuUrl", fileThu + newFileName);
        ajax.put("hdUrl", filePath + newFileName);
        ajax.put("fileName", file.getOriginalFilename());
        ajax.put("newFileName", FileUtils.getName(newFileName));
        ajax.put("originalFilename", file.getOriginalFilename());
        return ajax;
    }

    @Override
    public ResponseEntity<Resource> downloadFile(String fileName) throws IOException {
        log.info("开始下载:{}", fileName);
        // 解析远程路径和文件名
        String remotePath = fileName.substring(0, fileName.lastIndexOf("/") + 1);
        String localFileName = fileName.substring(fileName.lastIndexOf("/") + 1);
        try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()){
            ftpUtil.downloadFile(remotePath, localFileName, outputStream);
            log.info("访问ftp服务完成");
            byte[] fileContent = outputStream.toByteArray();
            InputStreamResource resource = new InputStreamResource(new ByteArrayInputStream(fileContent));
            HttpHeaders headers = new HttpHeaders();
            headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + localFileName + "\"");
            headers.setContentType(MediaType.valueOf(getFileContentType(fileName)));
            headers.setContentLength(fileContent.length);
            log.info("下载完成");
            return new ResponseEntity<>(resource, headers, HttpStatus.OK);
        } catch (Exception e) {
            return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }


    private static File multipartFileToFile(MultipartFile file) throws Exception {

        File toFile = null;
        if (file.equals("") || file.getSize() <= 0) {
            file = null;
        } else {
            InputStream ins = null;
            ins = file.getInputStream();
            toFile = new File(file.getOriginalFilename());
            inputStreamToFile(ins, toFile);
            ins.close();
        }
        return toFile;
    }

    //获取流文件
    private static void inputStreamToFile(InputStream ins, File file) {
        try {
            OutputStream os = new FileOutputStream(file);
            int bytesRead = 0;
            byte[] buffer = new byte[8192];
            while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            os.close();
            ins.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 更新数据库内容
     *
     * @param hdUrl  高清图地址，若不是图片就文件地址
     * @param thuUrl 缩略图地址
     * @param type   更新到哪个表中
     */
    private void updateDb(String hdUrl, String thuUrl, String type, Long id) {
        switch (type) {
            case "commodity":
                RecCommodity commodity = new RecCommodity();
                commodity.setId(id);
                commodity.setImages(hdUrl + ";" + thuUrl);
                commodity.setUpdateDate(new Date());
                commodityMapper.updateRecCommodity(commodity);
                break;
            case "store":
                RecStores stores = new RecStores();
                stores.setId(id);
                stores.setImages(hdUrl + ";" + thuUrl);
                stores.setUpdateDate(new Date());
                storesMapper.updateRecStores(stores);
                break;
            default:
                break;
        }
    }

    /**
     * 根据文件名判断响应头部类型
     */
    private static String getFileContentType(String name) {
        String result = "";
        String fileType = name.toLowerCase();
        if (fileType.endsWith(".png")) {
            result = "image/png";
        } else if (fileType.endsWith(".gif")) {
            result = "image/gif";
        } else if (fileType.endsWith(".jpg") || fileType.endsWith(".jpeg")) {
            result = "image/jpeg";
        } else if (fileType.endsWith(".svg")) {
            result = "image/svg+xml";
        } else if (fileType.endsWith(".doc")) {
            result = "application/msword";
        } else if (fileType.endsWith(".xls")) {
            result = "application/x-excel";
        } else if (fileType.endsWith(".zip")) {
            result = "application/zip";
        } else if (fileType.endsWith(".pdf")) {
            result = "application/pdf";
        } else {
            result = "application/octet-stream";
        }
        return result;
    }
}
