package com.xinyilu.system.service.kindergartenCheckReport.impl;

import com.xinyilu.common.config.XinYiLuConfig;
import com.xinyilu.common.constant.Constants;
import com.xinyilu.common.core.domain.AjaxResult;
import com.xinyilu.common.enums.CheckStatusEnum;
import com.xinyilu.common.exception.ServiceException;
import com.xinyilu.common.utils.SecurityUtils;
import com.xinyilu.common.utils.StringUtils;
import com.xinyilu.common.utils.codes.GenerateSystemCodeUtil;
import com.xinyilu.common.utils.file.FileUploadUtils;
import com.xinyilu.common.utils.file.FileUtils;
import com.xinyilu.common.utils.file.MimeTypeUtils;
import com.xinyilu.system.domain.dto.KindergartenCheckReportDTO;
import com.xinyilu.system.domain.dto.KindergartenExamineAndApproveDTO;
import com.xinyilu.system.domain.dto.UploadKindergartenCheckReportDTO;
import com.xinyilu.system.domain.kindergartenCheckReport.KindergartenCheckReport;
import com.xinyilu.system.domain.vo.personalcheckreport.ExistCheckReportVO;
import com.xinyilu.system.mapper.kindergartenCheckReport.KindergartenCheckReportMapper;
import com.xinyilu.system.service.kindergartenCheckReport.IKindergartenCheckReportService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 幼儿园检测报告Service业务层处理
 *
 * @author xinyilu
 * @date 2022-09-22
 */
@Slf4j
@Service
public class KindergartenCheckReportServiceImpl implements IKindergartenCheckReportService {
    @Resource
    private KindergartenCheckReportMapper kindergartenCheckReportMapper;
    @Resource
    private XinYiLuConfig xinYiLuConfig;
    @Resource
    private GenerateSystemCodeUtil generateSystemCodeUtil;

    /**
     * 查询幼儿园检测报告
     *
     * @param id 幼儿园检测报告主键
     * @return 幼儿园检测报告
     */
    @Override
    public KindergartenCheckReport selectKindergartenCheckReportById(Long id) {
        return kindergartenCheckReportMapper.selectKindergartenCheckReportById(id);
    }

    /**
     * 查询幼儿园检测报告列表
     *
     * @param kindergartenCheckReport 幼儿园检测报告
     * @return 幼儿园检测报告
     */
    @Override
    public List<KindergartenCheckReportDTO> selectKindergartenCheckReportList(KindergartenCheckReportDTO kindergartenCheckReport) {
        return kindergartenCheckReportMapper.selectKindergartenCheckReportList(kindergartenCheckReport);
    }

    /**
     * 查询幼儿园未审批监测报告
     *
     * @param batchCode 批次编号
     * @return 幼儿园检测报告
     */
    @Override
    public List<KindergartenExamineAndApproveDTO> selectKindergartenCheckReportListAll(String batchCode) {
        List<KindergartenExamineAndApproveDTO> kindergartenCheckReportDTOS = kindergartenCheckReportMapper.selectKindergartenCheckReportListAll(batchCode);
        List<KindergartenExamineAndApproveDTO> kindergartenCheckReport = kindergartenCheckReportMapper.selectKindergartenCheckReportPass(batchCode, CheckStatusEnum.CHECK.getStatus());
        //求出差集,返回数据
        Collection<KindergartenExamineAndApproveDTO> collect = CollectionUtils.subtract(kindergartenCheckReportDTOS, kindergartenCheckReport);
        return collect.stream().filter(Objects::nonNull).peek(s -> s.setCheckReportType(Constants.KINDERGARTEN)).collect(Collectors.toList());
    }

    /**
     * 新增幼儿园检测报告
     *
     * @param kindergartenCheckReport 幼儿园检测报告
     * @return 结果
     */
    @Override
    public int insertKindergartenCheckReport(KindergartenCheckReport kindergartenCheckReport) {
        kindergartenCheckReport.setCreateTime(LocalDateTime.now());
        return kindergartenCheckReportMapper.insertKindergartenCheckReport(kindergartenCheckReport);
    }

    /**
     * 修改幼儿园检测报告
     *
     * @param kindergartenCheckReport 幼儿园检测报告
     * @return 结果
     */
    @Override
    public AjaxResult updateKindergartenCheckReport(KindergartenCheckReport kindergartenCheckReport) {
        //修改时间，修改时间，审核人，审核时间
        kindergartenCheckReport.setUpdateTime(LocalDateTime.now());
        kindergartenCheckReport.setUpdateBy(SecurityUtils.getUsername());
        kindergartenCheckReport.setCheckUserId(SecurityUtils.getUserId());
        kindergartenCheckReport.setCheckTime(LocalDateTime.now());
        int updateCount = kindergartenCheckReportMapper.updateKindergartenCheckReport(kindergartenCheckReport);
        if (updateCount <= 0) {
            return AjaxResult.error("审核失败，请联系管理员！");
        }
        return AjaxResult.success();
    }

    /**
     * 批量删除幼儿园检测报告
     *
     * @param ids 需要删除的幼儿园检测报告主键
     * @return 结果
     */
    @Override
    public int deleteKindergartenCheckReportByIds(Long[] ids) {
        return kindergartenCheckReportMapper.deleteKindergartenCheckReportByIds(ids);
    }

    /**
     * 下载幼儿园检测报告
     *
     * @param id       需要下载的幼儿园检测报告
     * @param response 响应信息
     * @return 结果
     */
    @Override
    public void downloadReport(Long id, HttpServletResponse response) {
        KindergartenCheckReport kindergartenCheckReport = kindergartenCheckReportMapper.selectKindergartenCheckReportById(id);
        if (Objects.isNull(kindergartenCheckReport) || StringUtils.isBlank(kindergartenCheckReport.getDownloadAddress())) {
            throw new ServiceException("当前报告信息不存在！");
        }
        //检验文件是否可以下载
        String reportName = StringUtils.isBlank(kindergartenCheckReport.getReportName()) ? "" : kindergartenCheckReport.getReportName();
        if (FileUtils.checkAllowDownload(reportName)) {
            throw new ServiceException(StringUtils.format("文件名称({})非法，不允许下载。 ", reportName));
        }
        //文件路径
        String filePath = XinYiLuConfig.getProfile() + kindergartenCheckReport.getDownloadAddress().replaceAll("/profile", "");
        try {
            //下载
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            FileUtils.setAttachmentResponseHeader(response, reportName);
            FileUtils.writeBytes(filePath, response.getOutputStream());
        } catch (Exception exception) {
            log.error("幼儿园检测报告下载异常，报告名称：{}, 异常信息为：{}", reportName, exception.getMessage());
            throw new ServiceException("幼儿园检测报告下载异常，请联系管理员！");
        }
    }

    /**
     * 删除幼儿园检测报告信息
     *
     * @param id 幼儿园检测报告主键
     * @return 结果
     */
    @Override
    public int deleteKindergartenCheckReportById(Long id) {
        return kindergartenCheckReportMapper.deleteKindergartenCheckReportById(id);
    }

    /**
     * 判断幼儿园检测报告是否存在
     *
     * @param kindergartenId 幼儿园id
     * @param batchCode      批次编号
     * @return 是否存在结果
     */
    @Override
    public AjaxResult existKindergartenCheckReport(Long kindergartenId, String batchCode) {
        ExistCheckReportVO vo = kindergartenCheckReportMapper.getKindergartenCheckReportInfo(kindergartenId, batchCode);
        if (Objects.isNull(vo)) {
            ExistCheckReportVO reportVO = new ExistCheckReportVO();
            reportVO.setExistFlag(false);
            return AjaxResult.success(reportVO);
        }
        vo.setExistFlag(true);
        return AjaxResult.success(vo);
    }

    /**
     * 幼儿园检测报告上传接口
     *
     * @param checkReportDTO 输入参数
     * @return 上传结果
     * @throws Exception 异常信息
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public AjaxResult uploadKindergartenCheckReport(UploadKindergartenCheckReportDTO checkReportDTO) throws Exception {
        //文件路径
        String checkReportPath = XinYiLuConfig.getProfile() + xinYiLuConfig.getKindergartenCheckReportUrl() + "/" + checkReportDTO.getKindergartenId() + "/" + checkReportDTO.getBatchCode();
        File checkReportFile = new File(checkReportPath);
        if (!checkReportFile.exists()) {
            //文件路径不存在，创建文件路径
            boolean createMkdirs = checkReportFile.mkdirs();
            if (BooleanUtils.isFalse(createMkdirs)) {
                throw new ServiceException("幼儿园检测报告文件目录创建失败！");
            }
        }
        //报告名称
        String checkReportName = checkReportPath + "/" + checkReportDTO.getKindergartenName() + "_" + checkReportDTO.getBatchCode() + "_幼儿园检测报告书.pdf";
        File checkReportNameFile = new File(checkReportName);
        if (checkReportNameFile.exists()) {
            //文件名称已存在，删除文件
            boolean delete = checkReportNameFile.delete();
            if (BooleanUtils.isFalse(delete)) {
                throw new ServiceException("幼儿园检测报告文件删除失败！");
            }
            //删除数据库报告信息
            int deleteKindergartenCount = kindergartenCheckReportMapper.deleteKindergartenReportInfo(checkReportDTO.getKindergartenId(), checkReportDTO.getBatchCode());
            if (deleteKindergartenCount <= 0) {
                throw new ServiceException("删除幼儿园检测报告信息失败，请联系管理员！");
            }
        }
        //文件保存到本地路径中
        FileUploadUtils.uploadCheckReport(checkReportName, checkReportDTO.getKindergartenFile(), MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
        //将生成报告信息保存到数据库中
        String reportFileName = checkReportDTO.getKindergartenName() + "_" + checkReportDTO.getBatchCode() + "_幼儿园检测报告书.pdf";
        String downAddress = "/profile" + xinYiLuConfig.getKindergartenCheckReportUrl() + "/" + checkReportDTO.getKindergartenId() + "/" + checkReportDTO.getBatchCode() + "/" + reportFileName;
        KindergartenCheckReport kindergartenCheckReport = buildStudentReportInfo(checkReportDTO, reportFileName, downAddress);
        int insertStudentReportCount = kindergartenCheckReportMapper.insertKindergartenCheckReport(kindergartenCheckReport);
        if (insertStudentReportCount <= 0) {
            throw new ServiceException("保存幼儿园检测报告信息失败，请联系管理员！");
        }
        //将报告信息返回
        KindergartenCheckReport kindergartenCheckReportRe = new KindergartenCheckReport();
        kindergartenCheckReportRe.setId(kindergartenCheckReport.getId());
        kindergartenCheckReportRe.setDownloadAddress(downAddress);
        return AjaxResult.success(kindergartenCheckReportRe);
    }

    /**
     * 构建个人幼儿园报告信息
     *
     * @param checkReportDTO 输入参数
     * @param reportName     报告名称
     * @param downAddress    报告下载地址
     * @return 个人报告信息结果
     */
    private KindergartenCheckReport buildStudentReportInfo(UploadKindergartenCheckReportDTO checkReportDTO,
                                                           String reportName, String downAddress) {
        KindergartenCheckReport kindergartenCheckReport = new KindergartenCheckReport();
        kindergartenCheckReport.setKindergartenId(checkReportDTO.getKindergartenId());
        kindergartenCheckReport.setBatchCode(checkReportDTO.getBatchCode());
        kindergartenCheckReport.setReportCode(Constants.KINDERGARTEN_CHECK_REPORT_PREFIX + generateSystemCodeUtil.generateSystemCode(Constants.KINDERGARTEN_CHECK_REPORT_PREFIX));
        kindergartenCheckReport.setReportName(reportName);
        kindergartenCheckReport.setDownloadAddress(downAddress);
        kindergartenCheckReport.setCheckStatus(checkReportDTO.getCheckStatus());
        kindergartenCheckReport.setCheckUserId(SecurityUtils.getUserId());
        kindergartenCheckReport.setCheckTime(LocalDateTime.now());
        kindergartenCheckReport.setDelFlag(0);
        kindergartenCheckReport.setCreateTime(LocalDateTime.now());
        kindergartenCheckReport.setCreateBy(SecurityUtils.getUsername());
        return kindergartenCheckReport;
    }
}
