package com.xinyilu.system.service.checkreport.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.codes.GenerateSystemCodeUtil;
import com.xinyilu.system.checkreport.GenerateStudentCheckReport;
import com.xinyilu.system.domain.checkreport.StudentPersonalReportDTO;
import com.xinyilu.system.domain.personalcheckreport.PersonalCheckReport;
import com.xinyilu.system.domain.vo.BodyShapeAnalysisVO;
import com.xinyilu.system.domain.vo.TestBodyScoreInfoVO;
import com.xinyilu.system.domain.vo.childrenRanking.ChildrenRankingVO;
import com.xinyilu.system.domain.vo.physiqueAnalysis.PhysiqueAnalysisVO;
import com.xinyilu.system.domain.vo.testActionDevelopment.TestActionDevelopmentVO;
import com.xinyilu.system.mapper.checkreport.CheckReportMapper;
import com.xinyilu.system.mapper.personalcheckreport.PersonalCheckReportMapper;
import com.xinyilu.system.mapper.studentInfo.StudentInfoMapper;
import com.xinyilu.system.service.checkreport.CheckReportService;
import com.xinyilu.system.service.checkreport.PhysicalSubstanceTestService;
import com.xinyilu.system.service.checkreport.PhysiqueBodyShapeAnalysisService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;

/**
 * @Description 检测报告业务层实现类
 * @Author 纪寒
 * @Date 2022-09-23 13:34:21
 * @Version 1.0
 */
@Service
@Slf4j
public class CheckReportServiceImpl implements CheckReportService {

    @Resource
    private StudentInfoMapper studentInfoMapper;
    @Resource
    private PhysiqueBodyShapeAnalysisService physiqueBodyShapeAnalysisService;
    @Resource
    private PhysicalSubstanceTestService physicalSubstanceTestService;
    @Resource
    private XinYiLuConfig xinYiLuConfig;
    @Resource
    private CheckReportMapper checkReportMapper;
    @Resource
    private GenerateSystemCodeUtil generateSystemCodeUtil;
    @Resource
    private PersonalCheckReportMapper personalCheckReportMapper;

    /**
     * 根据学生id和批次编号生成学生检测报告
     *
     * @param studentId 学生id
     * @param batchCode 批次编号
     * @return 检测报告
     * @throws Exception 异常信息
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public AjaxResult generateStudentCheckReport(Long studentId, String batchCode) throws Exception {
        //查询学生基本信息
        PhysiqueAnalysisVO studentInfo = studentInfoMapper.getStudentInfoById(studentId);
        if (Objects.isNull(studentInfo)) {
            return AjaxResult.error("学生信息不存在！");
        }
        //学生个人综合分析
        PhysiqueAnalysisVO physiqueAnalysis = physiqueBodyShapeAnalysisService.getStudentPhysiqueAnalysis(studentInfo, studentId, batchCode);
        //身体形态分析
        BodyShapeAnalysisVO bodyShapeAnalysis = physiqueBodyShapeAnalysisService.getStudentBodyShapeAnalysis(studentInfo, studentId, batchCode);
        //身体素质分析
        List<TestBodyScoreInfoVO> physicalSubstanceTestList = physicalSubstanceTestService.getPhysicalSubstanceTestInfo(studentId, batchCode);
        //动作发展检测
        List<TestActionDevelopmentVO> actionDevelopTestList = physicalSubstanceTestService.getActionDevelopTestInfo(studentId, batchCode);
        //综合体质分析
        ChildrenRankingVO childrenRankingTestInfo = physicalSubstanceTestService.getChildrenRankingTestInfo(studentId, StringUtils.isBlank(studentInfo.getStudentName()) ? "" : studentInfo.getStudentName(), batchCode);
        //文件路径
        String checkReportPath = XinYiLuConfig.getProfile() + xinYiLuConfig.getCheckReportUrl() + "/" + studentId + "/" + batchCode;
        File checkReportFile = new File(checkReportPath);
        if (!checkReportFile.exists()) {
            //文件路径不存在，创建文件路径
            boolean createMkdirs = checkReportFile.mkdirs();
            if (BooleanUtils.isFalse(createMkdirs)) {
                throw new ServiceException("个人检测报告文件目录创建失败！");
            }
        }
        String studentName = StringUtils.isBlank(studentInfo.getStudentName()) ? "" : studentInfo.getStudentName();
        //报告名称
        String checkReportName = checkReportPath + "/" + studentName + "_" + batchCode + "_幼儿体质检测报告书.pdf";
        File checkReportNameFile = new File(checkReportName);
        if (checkReportNameFile.exists()) {
            //文件名称已存在，删除文件
            boolean delete = checkReportNameFile.delete();
            if (BooleanUtils.isFalse(delete)) {
                throw new ServiceException("个人检测报告文件删除失败！");
            }
            //删除数据库报告信息
            int deleteStudentReportCount = checkReportMapper.deleteStudentPersonReportInfo(studentId, batchCode);
            if (deleteStudentReportCount <= 0) {
                throw new ServiceException("删除个人检测报告信息失败，请联系管理员！");
            }
        }
        //将PDF生成到本地硬盘中
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        GenerateStudentCheckReport.createStudentCheckReport(outputStream, physiqueAnalysis, bodyShapeAnalysis,
                physicalSubstanceTestList, actionDevelopTestList, childrenRankingTestInfo);
        FileUtils.copyInputStreamToFile(new ByteArrayInputStream(outputStream.toByteArray()), checkReportNameFile);
        //将生成报告信息保存到数据库中
        String reportFileName = studentName + "_" + batchCode + "_幼儿体质检测报告书.pdf";
        String downAddress = "/profile" + xinYiLuConfig.getCheckReportUrl() + "/" + studentId + "/" + batchCode + "/" + reportFileName;
        StudentPersonalReportDTO dto = buildStudentReportInfo(studentId, batchCode, reportFileName, downAddress);
        int insertStudentReportCount = checkReportMapper.insertStudentPersonReportInfo(dto);
        if (insertStudentReportCount <= 0) {
            throw new ServiceException("保存个人检测报告信息失败，请联系管理员！");
        }
        //将报告信息返回
        PersonalCheckReport createCheckReportInfo = new PersonalCheckReport();
        createCheckReportInfo.setId(dto.getId());
        createCheckReportInfo.setDownloadAddress(downAddress);
        return AjaxResult.success(createCheckReportInfo);
    }

    /**
     * 构建个人学生报告信息
     *
     * @param studentId   学生id
     * @param batchCode   批次编号
     * @param reportName  报告名称
     * @param downAddress 报告下载地址
     * @return 个人报告信息结果
     */
    private StudentPersonalReportDTO buildStudentReportInfo(Long studentId, String batchCode,
                                                            String reportName, String downAddress) {
        return StudentPersonalReportDTO.builder()
                .studentId(studentId).batchCode(batchCode)
                .reportCode(Constants.STUDENT_CHECK_REPORT_PREFIX + generateSystemCodeUtil.generateSystemCode(Constants.STUDENT_CHECK_REPORT_PREFIX))
                .reportName(reportName).downloadAddress(downAddress).checkStatus(CheckStatusEnum.NOT_CHECK.getStatus())
                .delFlag(0).createTime(LocalDateTime.now()).createBy(SecurityUtils.getUsername())
                .build();
    }
}
