package com.ho.business.service.impl;

import cn.hutool.core.codec.Base64;
import com.ho.business.common.MinioNewUtil;
import com.ho.business.constant.DeviceTypeConstant;
import com.ho.business.vo.req.MesFileReqVo;
import com.ho.business.vo.req.StationReq;
import com.ho.business.vo.req.picture.PictureQueryReq;
import com.ho.common.tools.constant.RedisKeyConstant;
import com.ho.common.tools.entity.SimpleUser;
import com.ho.common.tools.entity.UserDetailRespVO;
import com.ho.common.tools.service.RedisService;
import com.ho.common.tools.util.CommonBytesUtil;
import com.ho.business.entity.Picture;
import com.ho.business.mapper.PictureMapper;
import com.ho.business.service.PictureService;
import com.ho.business.vo.req.StationPutReqVO;
import com.ho.business.vo.req.StationReqVO;
import com.ho.business.vo.resp.PictureRespVO;
import com.ho.common.tools.constant.CommonConstant;
import com.ho.common.tools.exception.BaseResponseCode;
import com.ho.common.tools.exception.BusinessException;
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.mock.web.MockMultipartFile;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileInputStream;
import java.io.FilterInputStream;
import java.io.InputStream;
import java.net.FileNameMap;
import java.net.URLConnection;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description 图片存储实现
 * Author yule
 * Date 2023/1/3 14:06
 */
@Service
@Slf4j
public class PictureServiceImpl implements PictureService {


    @Autowired
    PictureMapper pictureMapper;

    @Autowired
    CommonBytesUtil bytesUtil;

    @Autowired
    RedisService redisService;

    @Override
    public Picture insertPicture(String url) {

        //创建文件对象
        File file = new File(url);
        //把图片的地址转化为图片的实体类对象
        Picture picture = new Picture();
        picture.setUrl(url);
        picture.setCreateTime(new Date());
        picture.setFileName(file.getName());
        //将实体对象入库存储
        pictureMapper.insertSelective(picture);
        //根据url查询到返回的实体对象
        return picture;
    }

    @Override
    public Picture insertPicture(StationReq vo, HttpServletRequest request) {
        String downloadFileKey = vo.getStationId() + ":" + RedisKeyConstant.DOWNLOAD_FILE_ALL;
        Map<Object, Object> dataMap = redisService.hgetall(downloadFileKey);
        String fileName = (String) dataMap.get(RedisKeyConstant.FILE_NAME);
        String filePath = (String) dataMap.get(RedisKeyConstant.FILE_PATH);
        Picture picture = new Picture();
        File file = new File(filePath + File.separator + fileName);
        try {
            FileNameMap fileNameMap = URLConnection.getFileNameMap();
            String mimeType = fileNameMap.getContentTypeFor(file.getName());
            MultipartFile multipartFile = new MockMultipartFile(fileName, fileName, mimeType, new FileInputStream(file));
            String token = request.getHeader(RedisKeyConstant.User.ACCESS_TOKEN);
            SimpleUser user = redisService.getSimpleUserByToken(token);
            String bucket = DeviceTypeConstant.GROUP + user.getGroupId();
            String filePathName = DeviceTypeConstant.OTHER + "/" + vo.getStationId() + "/" + multipartFile.getOriginalFilename();
            String url = minioUtil.commonUploadMinio(multipartFile, bucket, filePathName);
            picture.setFileName(multipartFile.getOriginalFilename());
            picture.setFilePath(filePathName);
            picture.setUrl(url);
            picture.setSrcId(vo.getStationId());
            picture.setType(CommonConstant.PICTURE.FIlE);
            picture.setCreateTime(new Date());
            PictureQueryReq req = new PictureQueryReq();
            req.setStationId(vo.getStationId());
            req.setType(CommonConstant.PICTURE.FIlE);
            req.setUrl(url);
            List<Picture> pictures = pictureMapper.selectByParam(req);
            if (pictures == null || pictures.isEmpty()) {
                pictureMapper.insertSelective(picture);
            } else {
                picture.setId(pictures.get(0).getId());
                pictureMapper.updateByPrimaryKey(picture);
            }
        } catch (Exception e) {
            log.error("上传文件发生异常，{}", e.getMessage());
            e.printStackTrace();
        }
        return picture;
    }

    @Override
    public void insertSrcIdAndType(StationReqVO vo) {
        List<Integer> pictureIds = vo.getPictureIds();
        if (pictureIds != null && !pictureIds.isEmpty()) {
            if (pictureIds.size() > 3) {
                throw new BusinessException(BaseResponseCode.FILE_NOT_MORE_THAN_THREE);
            }

            for (Integer pictureId : pictureIds) {
                Picture picture = new Picture();
                picture.setId(pictureId);
                picture.setSrcId(vo.getId());
                picture.setType(CommonConstant.PICTURE.STATION);
                picture.setCreateTime(new Date());
                pictureMapper.updateByPrimaryKeySelective(picture);
            }
        }

    }

    @Override
    public void deletedBySrcIdsAndType(List<Integer> srcIds) {
        if (!srcIds.isEmpty()) {
            //先删除文件
            List<Picture> pictures = new ArrayList<>();
            for (Integer srcId : srcIds) {
                List<Picture> list = pictureMapper.selectBySrcIdAndType(srcId, CommonConstant.PICTURE.STATION);
                pictures.addAll(list);
            }
            for (Picture picture : pictures) {
                File file = new File(picture.getUrl());
                if (!file.exists()) {
                    file.delete();
                }
            }
            //再删除数据库文件数据
            pictureMapper.deletedBySrcIdsAndType(srcIds, CommonConstant.PICTURE.STATION);
        }
    }

    @Override
    public void updatePicture(StationPutReqVO vo) {

        //判断是否有图片更新
        if (vo.getPictureIds() != null) {
            if (!vo.getPictureIds().isEmpty()) {
                if (vo.getPictureIds().size() > 3) {
                    throw new BusinessException(BaseResponseCode.FILE_NOT_MORE_THAN_THREE);
                }
                //先对之前的图片srcid 进行赋空值
                List<Picture> pictures = pictureMapper.selectBySrcIdAndType(vo.getId(), CommonConstant.PICTURE.STATION);
                List<Integer> pictureIds = pictures.stream().map(Picture::getId).collect(Collectors.toList());
                if (!pictureIds.isEmpty()) {
                    pictureMapper.setUpSrcIdNUll(pictureIds);
                }
                //在新增
                StationReqVO stationReqVO = new StationReqVO();
                BeanUtils.copyProperties(vo, stationReqVO);
                insertSrcIdAndType(stationReqVO);
            } else {
                List<Picture> pictures = pictureMapper.selectBySrcIdAndType(vo.getId(), CommonConstant.PICTURE.STATION);
                List<Integer> pictureIds = pictures.stream().map(Picture::getId).collect(Collectors.toList());
                if (!pictureIds.isEmpty()) {
                    pictureMapper.setUpSrcIdNUll(pictureIds);
                }
            }
        }
        //判断是否有logo图片更新
        insertLogo(vo.getLogoPictureId(), vo.getId());
    }

    @Override
    public int insertLogo(Integer LogoPictureId, Integer stationId) {
        int result = CommonConstant.ZERO;
        Picture p = pictureMapper.selectByStationAndType(stationId, CommonConstant.PICTURE.LOGO);
        if (LogoPictureId != null) {
            if (p != null && !p.getId().equals(LogoPictureId)) {
                pictureMapper.deleteByPrimaryKey(p.getId());
            }
            Picture logoPicture = new Picture();
            logoPicture.setId(LogoPictureId);
            logoPicture.setSrcId(stationId);
            logoPicture.setType(CommonConstant.PICTURE.LOGO);
            logoPicture.setCreateTime(new Date());
            result = pictureMapper.updateByPrimaryKeySelective(logoPicture);
        } else {
            if (p != null) {
                result = pictureMapper.deleteByPrimaryKey(p.getId());
            }
        }
        return result;
    }

    @Override
    public List<PictureRespVO> selectBySrcId(Integer srcId) {
        List<Picture> list = pictureMapper.selectBySrcIdAndType(srcId, CommonConstant.PICTURE.STATION);

        List<PictureRespVO> pictureResps = getPictureRespVOS(list);
        return pictureResps;
    }

    private List<PictureRespVO> getPictureRespVOS(List<Picture> list) {
        List<PictureRespVO> pictureResps = list.stream().map(s -> {
            byte[] bytes = null;
            //读取图片字节
            try {
                bytes = bytesUtil.readBlock(s.getUrl(), 0);
            } catch (Exception e) {
                e.printStackTrace();
            }
            //获取文件类型
            File file = new File(s.getUrl());
            //文件后缀名
            String type = FilenameUtils.getExtension(file.getName());
            PictureRespVO pictureResp = new PictureRespVO();
            //图片才会设置base64
            if (CommonConstant.PICTURE_TYPE.contains(type)) {
                StringBuilder sb = new StringBuilder();
                String base64 = sb.append("data:image/").append(type).append(";base64,").append(Base64.encode(bytes)).toString();
                pictureResp.setBase(base64);
            }
            pictureResp.setPictureId(s.getId());
            pictureResp.setPictureType(type);
            pictureResp.setFileName(s.getFileName());
            return pictureResp;
        }).collect(Collectors.toList());
        return pictureResps;
    }

    @Override
    public Picture selectById(Integer id) {

        Picture picture = pictureMapper.selectByPrimaryKey(id);
        return picture;
    }

    @Override
    public void deletedById(Integer id) {
        pictureMapper.deleteByPrimaryKey(id);
    }

    @Override
    public List<Picture> selectAll() {
        return pictureMapper.selectAll();
    }

    @Override
    public void deletedByIds(List<Integer> picturesIds) {
        if (picturesIds != null && !picturesIds.isEmpty()) {
            pictureMapper.deletedByIds(picturesIds);
        }
    }

    @Autowired
    MinioNewUtil minioUtil;

    @Override
    public void deletedFile(String bucket, Integer groupId, Integer pictureId) {
        Picture picture = pictureMapper.selectByPrimaryKey(pictureId);
        //先删除minio中的文件
        if (picture != null) {
            boolean flag = minioUtil.deleteFile(bucket, DeviceTypeConstant.GROUP + groupId + "/" + picture.getFilePath());
            if (!flag) {
                throw new BusinessException(BaseResponseCode.DELETE_ERROR);
            }
        }
        //再删除数据库中数据
        pictureMapper.deleteByPrimaryKey(pictureId);
    }

    @Override
    public Picture uploadFile(MultipartFile file, String version, String updateLog, String ownerOrg, String bucket) {
        //判断该集团的bucket是否存在,不存在就创建
        boolean flag = minioUtil.bucketExists(bucket);
        if (!flag) {
            minioUtil.createBucketName(bucket);
        }
        String filePathName = DeviceTypeConstant.STATION + "/" + file.getOriginalFilename();
        String url = minioUtil.minioUpload(file, filePathName, bucket);
        Picture picture = new Picture();
        //上传apk包，默认给加个0,防止定时任务删除src_id为空的数据
        picture.setSrcId(CommonConstant.ZERO);
        picture.setFileName(file.getOriginalFilename());
        picture.setFilePath(filePathName);
        picture.setUrl(url);
        picture.setType(CommonConstant.PICTURE.FILE_JAR);
        picture.setCreateTime(new Date());
        picture.setVersion(version);
        picture.setOwnerOrg(ownerOrg);
        picture.setUpdateLog(updateLog);
        pictureMapper.insertSelective(picture);
        Integer pictureId = picture.getId();
        log.info("pictureId:" + pictureId);
        return picture;
    }

    @Override
    public Picture uploadLogoFile(MultipartFile file, String ownerOrg, String bucket) {
        //判断该集团的bucket是否存在,不存在就创建
        boolean flag = minioUtil.bucketExists(bucket);
        if (!flag) {
            minioUtil.createBucketName(bucket);
        }
        Calendar c = Calendar.getInstance(); // 创建Calendar对象
        int year = c.get(Calendar.YEAR); // 获取年
        int month = c.get(Calendar.MONTH) + 1; // 获取月份 0表示1月份
        int day = c.get(Calendar.DAY_OF_MONTH); // 获取日期
        int hour = c.get(Calendar.HOUR_OF_DAY); // 获取小时
        int minute = c.get(Calendar.MINUTE); // 获取分钟
        int second = c.get(Calendar.SECOND); // 获取秒
        String str = year + "/" + month + "/" + day + "/" + hour + "/" + minute + "/" + second;
        String filePathName = DeviceTypeConstant.STATION + "/" + str + "/" + file.getOriginalFilename();
        String url = minioUtil.minioUpload(file, filePathName, bucket);
        Picture picture = new Picture();
        //上传apk包，默认给加个0,防止定时任务删除src_id为空的数据
        picture.setSrcId(CommonConstant.ZERO);
        picture.setFileName(file.getOriginalFilename());
        picture.setFilePath(filePathName);
        picture.setUrl(url);
        picture.setType(CommonConstant.PICTURE.LOGO);
        picture.setCreateTime(new Date());
        picture.setOwnerOrg(ownerOrg);
        pictureMapper.insertSelective(picture);
        Integer pictureId = picture.getId();
        log.info("pictureId:" + pictureId);
        return picture;
    }

    @Override
    public Picture uploadPicture(MultipartFile file, Integer type, UserDetailRespVO user, Integer isPrivate) {
        String bucket = DeviceTypeConstant.GROUP;
        boolean flag = minioUtil.bucketExists(bucket);
        if (!flag) {
            minioUtil.createBucketName(bucket);
        }
        String filePathName = CommonConstant.CONFIG + "/" + user.getUsername() + "/" + file.getOriginalFilename();
        String url = minioUtil.minioUpload(file, filePathName, bucket);
        Picture picture = new Picture();
        picture.setSrcId(CommonConstant.ZERO);
        picture.setFileName(file.getOriginalFilename());
        picture.setFilePath(filePathName);
        picture.setUrl(url);
        picture.setType(type == null ? CommonConstant.PICTURE.THUMBNAIL : type);
        picture.setCreateTime(new Date());
        picture.setOwnerOrg(String.valueOf(user.getDeptId()));
        //isPrivate(1:私有 2:公有)
        if (CommonConstant.TWO.equals(isPrivate)) {
            //isPrivate(1:私有 2:公有)
            picture.setOwnerUser(" ");
        } else {
            picture.setOwnerUser(user.getUsername());
        }
        picture.setBucket(bucket);
        pictureMapper.insertSelective(picture);
        Integer pictureId = picture.getId();
        log.info("pictureId:" + pictureId);
        return picture;
    }

    @Override
    public Picture saveOrUpdatePicture(Picture picture) {
        PictureQueryReq req = new PictureQueryReq();
        req.setStationId(picture.getSrcId());
        req.setType(CommonConstant.PICTURE.FIlE);
        req.setUrl(picture.getUrl());
        List<Picture> pictures = pictureMapper.selectByParam(req);
        if (pictures == null || pictures.isEmpty()) {
            pictureMapper.insertSelective(picture);
        } else {
            picture.setId(pictures.get(0).getId());
            pictureMapper.updateByPrimaryKey(picture);
        }
        return picture;
    }

    @Override
    public void deletePicture(Integer pictureId) {
        Picture picture = pictureMapper.selectByPrimaryKey(pictureId);
        //先删除minio中的文件
        if (picture != null) {
            boolean flag = minioUtil.deleteFile(CommonConstant.BUCKET, picture.getBucket() + "/" + picture.getFilePath());
            if (!flag) {
                throw new BusinessException(BaseResponseCode.DELETE_ERROR);
            }
        }
        //再删除数据库中数据
        pictureMapper.deleteByPrimaryKey(pictureId);
    }

    @Override
    public Picture uploadPicture(MultipartFile file, Integer type) {
        String bucket = DeviceTypeConstant.GROUP;
        boolean flag = minioUtil.bucketExists(bucket);
        if (!flag) {
            minioUtil.createBucketName(bucket);
        }
        String filePathName = CommonConstant.MES_FILE +  "/" + file.getOriginalFilename();
        String url = minioUtil.minioUpload(file, filePathName, bucket);
        Picture picture = new Picture();
        picture.setSrcId(CommonConstant.ZERO);
        picture.setFileName(file.getOriginalFilename());
        picture.setFilePath(filePathName);
        picture.setUrl(url);
        //永康文件类型
        picture.setType(type == null ? CommonConstant.PICTURE.PACK_FILE : (type<CommonConstant.PICTURE.PACK_FILE?CommonConstant.PICTURE.PACK_FILE:type));
        picture.setCreateTime(new Date());
        picture.setBucket(bucket);
        pictureMapper.insertSelective(picture);
        Integer pictureId = picture.getId();
        log.info("pictureId:" + pictureId);
        return picture;
    }

    @Override
    public List<PictureRespVO> selectAllFile() {
        List<Picture> list = pictureMapper.selectBySrcIdAndType(null, CommonConstant.PICTURE.FILE_JAR);
        List<PictureRespVO> pictureRespVOS = list.stream().map(s -> {
            PictureRespVO pictureRespVO = new PictureRespVO();
            pictureRespVO.setPictureId(s.getId());
            String type = FilenameUtils.getExtension(s.getFileName());
            pictureRespVO.setPictureType(type);
            pictureRespVO.setUrl(s.getUrl());
            pictureRespVO.setFileName(s.getFileName());
            pictureRespVO.setOwnerOrg(s.getOwnerOrg());
            pictureRespVO.setUpdateLog(s.getUpdateLog());
            return pictureRespVO;
        }).collect(Collectors.toList());
        return pictureRespVOS;
    }

    @Override
    public List<Picture> selectAllFileByParams(PictureQueryReq picture) {
        List<Picture> list = pictureMapper.selectByParams(picture);
        return list;
    }

    @Override
    public List<Picture> selectAllFileByParam(PictureQueryReq picture) {
        List<Picture> list = new ArrayList<>();
        if (picture.getIsPrivate() == null) {
            throw new BusinessException(BaseResponseCode.ISPRIVATE_NOT);
        } else {
            if (CommonConstant.ONE.equals(picture.getIsPrivate())) {
                list = pictureMapper.selectByParam(picture);
            } else {
                picture.setOwnerUser(" ");
                list = pictureMapper.selectByParams(picture);
            }
        }

        return list;
    }

    @Override
    public PictureRespVO selectLastOne(String version) {
        Picture picture = pictureMapper.selectLastOne(CommonConstant.PICTURE.FILE_JAR);
        PictureRespVO pictureRespVO = new PictureRespVO();
        if (picture != null) {
            if (picture.getVersion().compareTo(version) > 0) {
                pictureRespVO.setPictureId(picture.getId());
                String type = FilenameUtils.getExtension(picture.getFileName());
                pictureRespVO.setPictureType(type);
                pictureRespVO.setUrl(picture.getUrl());
                pictureRespVO.setFileName(picture.getFileName());
                pictureRespVO.setVersion(picture.getVersion());
                pictureRespVO.setOwnerOrg(picture.getOwnerOrg());
                pictureRespVO.setUpdateLog(picture.getUpdateLog());
            }
        }
        return pictureRespVO;
    }


    @Override
    public Picture selectByStationAndType(Integer id, Integer type) {
        Picture picture = pictureMapper.selectByStationAndType(id, type);
        return picture;
    }
}

