package com.ho.filecenter.controller;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.date.DateUtil;
import com.ho.business.entity.Picture;
import com.ho.common.tools.annotation.LogAnnotation;
import com.ho.common.tools.annotation.TokenIgnore;
import com.ho.common.tools.constant.CommonConstant;
import com.ho.common.tools.constant.ContextConstant;
import com.ho.common.tools.entity.WorkOrderPicture;
import com.ho.common.tools.exception.BaseResponseCode;
import com.ho.common.tools.exception.BusinessException;
import com.ho.common.tools.exception.DataResult;
import com.ho.common.tools.util.CommonBytesUtil;
import com.ho.filecenter.feignclient.BusinessFeignClient;
import com.ho.filecenter.feignclient.FileCenterFlowFeignClient;
import com.ho.filecenter.vo.currencyfile.CurrencyFileReqVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.Date;

/**
 * @Description 文件的上传, 下载以及预览
 * Author yule
 * Date 2022/12/30 16:12
 */
@RestController
@RequestMapping(ContextConstant.MEDIA_CONTEXT + "currencyFile")
@Api(tags = "多媒体-通用文件模块")
@Slf4j
public class CurrencyFileController {

    @Value("${files.upload.path}")
    String fileUploadPath;

    @Value("${files.format}")
    String fileFormat;

    @Value("${files.maxByte}")
    Long fileSize;

    @Autowired
    CommonBytesUtil bytesUtil;

    @Autowired
    BusinessFeignClient businessFeignClient;

    @Autowired
    FileCenterFlowFeignClient flowFeignClient;


    /**
     * 文件上传
     */
    @PostMapping("/upload")
    @ApiOperation(value = "文件上传")
    @LogAnnotation(title = "通用文件模块", action = "文件上传")
    public DataResult<Picture> upload(@RequestPart MultipartFile file, @RequestParam String type) {
        Picture picture = new Picture();
        //验证文件是否为空
        if (file.isEmpty()) {
            throw new BusinessException(BaseResponseCode.FILE_IS_EMPTY);
        }
        //验证文件不能超过10M
        if (file.getSize() >= fileSize) {
            throw new BusinessException(BaseResponseCode.FILE_IS_TO_MORE);
        }

        //获取文件名
        String originalFilename = file.getOriginalFilename();
        //获取文件后缀名
        String suffix = originalFilename.substring(originalFilename.lastIndexOf(".")).toLowerCase();

        //符合要求的文件类型后缀名数组
        String[] splits = fileFormat.split(",");


        //判断文件格式是否符合要求
        boolean flag = false;
        for (String split : splits) {
            if (split.equals(suffix)) {
                flag = true;
                break;
            }
        }
        if (flag) {
            String timeFileName = DateUtil.format(new Date(), CommonConstant.DATE_PATH);
            String fileName = timeFileName + "/" + originalFilename;    //设置新文件名
            File uploadFile =
                    new File(fileUploadPath + "/" + fileName);
            if (!uploadFile.exists()) {    //判断是否存在该路径
                uploadFile.mkdirs();    //如果不存在直接创建
            }
            try {
                file.transferTo(uploadFile);    //将上传文件读取到服务器路径，参数为绝对路径
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (CommonConstant.WORK_ORDER.equals(type)) {
                WorkOrderPicture workOrderPicture = flowFeignClient.addPicture(fileUploadPath + fileName);
                BeanUtils.copyProperties(workOrderPicture, picture);
            }  else  {
                picture = businessFeignClient.addPicture(fileUploadPath + fileName);
            }
        } else {
            throw new BusinessException(BaseResponseCode.FILE_FORMAT_ONLY);
        }
        return DataResult.success(picture);
    }

    /**
     * 文件预览
     */
    @PostMapping("/preview")
    @ApiOperation(value = "文件预览")
    public String preview(@RequestBody CurrencyFileReqVO currencyFileReqVO) {
        //根据id查询通用文件对象
        Picture picture = businessFeignClient.selectPicture(currencyFileReqVO.getId());

        String base64 = null;
        try {
            //读取文件
            byte[] bytes = bytesUtil.readBlock(picture.getUrl(), 0);
            //文件后缀名
            String type = FilenameUtils.getExtension(new File(picture.getUrl()).getName());
            StringBuilder sb = new StringBuilder();
            base64 = sb.append("data:image/").append(type).append(";base64,").append(Base64.encode(bytes)).toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return base64;
    }

    @PostMapping("/previewData")
    @ApiOperation(value = "文件返回二进制流")
    public DataResult previewData(@RequestBody CurrencyFileReqVO currencyFileReqVO) {
        return DataResult.success(preview(currencyFileReqVO));
    }

    /**
     * 文件下载
     */
    @PostMapping("/download")
    @ApiOperation(value = "文件下载")
    public void download(@RequestBody CurrencyFileReqVO currencyFileReqVO, HttpServletResponse response) {
        Picture picture = new Picture();
        //根据id查询通用文件对象
        if (CommonConstant.WORK_ORDER.equals(currencyFileReqVO.getFileType())){
           WorkOrderPicture workOrderPicture = flowFeignClient.selectPictureById(currencyFileReqVO.getId());
           BeanUtils.copyProperties(workOrderPicture,picture);
        }else {
            picture = businessFeignClient.selectPicture(currencyFileReqVO.getId());
        }
        OutputStream os = null;
        FileInputStream fis = null;
        try {
            //获取文件后缀名
            String suffix = picture.getFileName().substring(picture.getFileName().lastIndexOf("."));
            // 响应图片
            response.setContentType("file/" + suffix);
            os = response.getOutputStream();
            fis = new FileInputStream(picture.getUrl());
            byte[] buffer = new byte[(int) bytesUtil.getFileSize(picture.getUrl())];
            int b = 0;
            while ((b = fis.read(buffer)) != -1) {
                os.write(buffer, 0, b);
            }
        } catch (Exception e) {
            log.error("下载文件失败");
        } finally {
            try {
                if (fis != null) {
                    fis.close();
                }
                if (os != null) {
                    os.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }


    /**
     * app文件下载
     */
    @GetMapping("/appDownload/{type}/{id}")
    @ApiOperation(value = "app文件下载")
    @TokenIgnore
    public void appDownload(@PathVariable("type") String type,@PathVariable("id") Integer id, HttpServletResponse response) {
        Picture picture = new Picture();
        //根据id查询通用文件对象
        if (CommonConstant.WORK_ORDER.equals(type)){
            WorkOrderPicture workOrderPicture = flowFeignClient.selectPictureById(id);
            BeanUtils.copyProperties(workOrderPicture,picture);
        }else {
            picture = businessFeignClient.selectPicture(id);
        }
        OutputStream os = null;
        FileInputStream fis = null;
        try {
            //获取文件后缀名
            String suffix = picture.getFileName().substring(picture.getFileName().lastIndexOf("."));

           String fileName = URLEncoder. encode(picture.getFileName(), "UTF-8");
            // 响应图片
            response.setContentType("application/octet-stream");
            response.addHeader("Content-disposition", "attachment;filename=" + fileName);
            os = response.getOutputStream();
            fis = new FileInputStream(picture.getUrl());
            byte[] buffer = new byte[(int) bytesUtil.getFileSize(picture.getUrl())];
            int b = 0;
            while ((b = fis.read(buffer)) != -1) {
                os.write(buffer, 0, b);
            }
        } catch (Exception e) {
            log.error("下载文件失败");
        } finally {
            try {
                if (fis != null) {
                    fis.close();
                }
                if (os != null) {
                    os.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }

    /**
     * 文件删除
     */
    @PostMapping("/delete")
    @ApiOperation(value = "文件删除")
    @LogAnnotation(title = "通用文件模块", action = "文件删除")
    public DataResult delete(@RequestBody CurrencyFileReqVO currencyFileReqVO) {


        businessFeignClient.deletePicture(currencyFileReqVO.getId());

        return DataResult.success();
    }


}
