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.KindConstitutionCheckReport;
import com.xinyilu.system.domain.dto.CheckReportDTO;
import com.xinyilu.system.domain.dto.ClassInfoDTO;
import com.xinyilu.system.domain.kindergartenCheckReport.KindergartenCheckReport;
import com.xinyilu.system.domain.kindergarteninfo.KindergartenInfo;
import com.xinyilu.system.domain.vo.ClassInfoVO;
import com.xinyilu.system.domain.vo.TestItemStudentScore.TestAllStudentScoresVO;
import com.xinyilu.system.domain.vo.averageHeightAndWeight.AverageHeightAndWeightVO;
import com.xinyilu.system.domain.vo.kinderPhysiqueAnalysis.KinderPhysiqueAnalysisVO;
import com.xinyilu.system.domain.vo.kindergartenSideAnalysis.KindergartenSideAnalysisVO;
import com.xinyilu.system.domain.vo.physicalActionAnalysis.PhysicalActionVO;
import com.xinyilu.system.domain.vo.testItemAvgScore.ClassAvgCategoryScoreVO;
import com.xinyilu.system.mapper.classinfo.ClassInfoMapper;
import com.xinyilu.system.mapper.kindergartenCheckReport.KindergartenCheckReportMapper;
import com.xinyilu.system.mapper.kindergarteninfo.KindergartenInfoMapper;
import com.xinyilu.system.service.checkreport.HeightAndWeightCheckReportService;
import com.xinyilu.system.service.checkreport.KindConstitutionService;
import com.xinyilu.system.service.checkreport.KindergartenShapeAnalysiService;
import com.xinyilu.system.service.checkreport.KindergartenSideAnalysisTestAllStudentScoreService;
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 javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

/**
 * 幼儿园报告分析
 *
 * @author wanghao
 * @date 2022/9/27 0027
 */
@Service
@Slf4j
public class KindConstitutionServiceImpl implements KindConstitutionService {

    @Resource
    private KindergartenInfoMapper kindergartenInfoMapper;
    @Resource
    private ClassInfoMapper classInfoMapper;
    @Resource
    private KindergartenShapeAnalysiService kindergartenShapeAnalysiService;
    @Resource
    private XinYiLuConfig xinYiLuConfig;
    @Resource
    private KindergartenCheckReportMapper kindergartenCheckReportMapper;
    @Resource
    private GenerateSystemCodeUtil generateSystemCodeUtil;
    @Resource
    KindergartenSideAnalysisTestAllStudentScoreService kindergartenSideAnalysisTestAllStudentScoreService;
    @Resource
    private HeightAndWeightCheckReportService heightAndWeightCheckReportService;

    @Override
    public AjaxResult getKinderPhysiqueAnalysis(Long kindergartenId, String batchCode) throws Exception {
        //根据幼儿园id获取幼儿园信息
        KindergartenInfo kindergartenInfo = kindergartenInfoMapper.selectKindergartenInfoById(kindergartenId);
        if (Objects.isNull(kindergartenInfo)) {
            return AjaxResult.error("幼儿园信息不存在！");
        }
        //获取综合体质分析报数据
        KinderPhysiqueAnalysisVO maleInfo = kindergartenShapeAnalysiService.getKindShapeAnalysiInfo(kindergartenId, batchCode, Constants.MALE);
        KinderPhysiqueAnalysisVO femaleInfo = kindergartenShapeAnalysiService.getKindShapeAnalysiInfo(kindergartenId, batchCode, Constants.FEMALE);
        //获取动作发展状况数据
        List<PhysicalActionVO> physicalActionList = new ArrayList<>();
        PhysicalActionVO largeClass = kindergartenShapeAnalysiService.getPhysicalActionAnalysis(kindergartenId, "LARGE_CLASS", batchCode);
        PhysicalActionVO middleClass = kindergartenShapeAnalysiService.getPhysicalActionAnalysis(kindergartenId, "MIDDLE_CLASS", batchCode);
        PhysicalActionVO smallClass = kindergartenShapeAnalysiService.getPhysicalActionAnalysis(kindergartenId, "SMALL_CLASS", batchCode);
        Collections.addAll(physicalActionList, largeClass, middleClass, smallClass);
        //获取班级体质分析
        ClassInfoDTO classInfoDTO = new ClassInfoDTO();
        classInfoDTO.setKindergartenId(kindergartenId);
        List<ClassInfoVO> classInfoList = classInfoMapper.selectClassInfoList(classInfoDTO);
        List<ClassAvgCategoryScoreVO> list = new ArrayList<>();
        if (classInfoList.size() > 0) {
            for (ClassInfoVO classInfo : classInfoList) {
                ClassAvgCategoryScoreVO classAvgCategoryScore = kindergartenShapeAnalysiService.selectTestItemAvgScoreList(classInfo.getId(), kindergartenId, batchCode);
                if (Objects.nonNull(classAvgCategoryScore)) {
                    list.add(classAvgCategoryScore);
                }
            }
        }
        //查询某个幼儿园下的某个测试项目所有学生的成绩信息以及其幼儿园信息
        List<KindergartenSideAnalysisVO> sideAnalysisList = kindergartenInfoMapper.getKindergartenSideAnalysis(kindergartenId, batchCode);
        //体侧概况分析
        TestAllStudentScoresVO testAllStudentScoreVO = kindergartenSideAnalysisTestAllStudentScoreService.selectAllStudentScoreList(kindergartenId, batchCode);
        // 体侧达标分析
        KindergartenSideAnalysisVO kindergartenSideAnalysisVO = kindergartenSideAnalysisTestAllStudentScoreService.getKindergartenSideAnalysis(sideAnalysisList, batchCode);
        //平均身高体重分析
        List<AverageHeightAndWeightVO> averageHeightAndWeightVO = heightAndWeightCheckReportService.generateStudentCheckReport(kindergartenId, batchCode);
        File checkReportNameFile = fileHandle(kindergartenId, batchCode, kindergartenInfo);
        //将PDF生成到本地硬盘中
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        //创建数据集合
        CheckReportDTO checkReport = CheckReportDTO.builder().maleInfo(maleInfo).femaleInfo(femaleInfo)
                .batchCode(batchCode).kindergartenName(kindergartenInfo
                        .getKindergartenName()).outputStream(outputStream)
                .physicalActionList(physicalActionList).categoryScoreList(list)
                .testAllStudentScoreVO(testAllStudentScoreVO)
                .kindergartenSideAnalysisVO(kindergartenSideAnalysisVO)
                .averageHeightAndWeightVO(averageHeightAndWeightVO).build();
        KindConstitutionCheckReport.createKindergartenCheckReportMale(checkReport);
        FileUtils.copyInputStreamToFile(new ByteArrayInputStream(outputStream.toByteArray()), checkReportNameFile);
        //将生成报告信息保存到数据库中
        String reportFileName = kindergartenInfo.getKindergartenName() + "_" + batchCode + "_幼儿园检测报告书.pdf";
        String downAddress = "/profile" + xinYiLuConfig.getKindergartenCheckReportUrl() + "/" + kindergartenId + "/" + batchCode + "/" + reportFileName;
        KindergartenCheckReport kindergartenCheckReport = buildStudentReportInfo(kindergartenId, batchCode, 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 kindergartenId 幼儿园id
     * @param batchCode      批次编号
     * @param reportName     报告名称
     * @param downAddress    报告下载地址
     * @return 个人报告信息结果
     */
    private KindergartenCheckReport buildStudentReportInfo(Long kindergartenId, String batchCode,
                                                           String reportName, String downAddress) {
        KindergartenCheckReport kindergartenCheckReport = new KindergartenCheckReport();
        kindergartenCheckReport.setKindergartenId(kindergartenId);
        kindergartenCheckReport.setBatchCode(batchCode);
        kindergartenCheckReport.setReportCode(Constants.KINDERGARTEN_CHECK_REPORT_PREFIX + generateSystemCodeUtil.generateSystemCode(Constants.KINDERGARTEN_CHECK_REPORT_PREFIX));
        kindergartenCheckReport.setReportName(reportName);
        kindergartenCheckReport.setDownloadAddress(downAddress);
        kindergartenCheckReport.setCheckStatus(CheckStatusEnum.NOT_CHECK.getStatus());
        kindergartenCheckReport.setDelFlag(0);
        kindergartenCheckReport.setCreateTime(LocalDateTime.now());
        kindergartenCheckReport.setCreateBy(SecurityUtils.getUsername());
        return kindergartenCheckReport;
    }

    /**
     * 构建个人幼儿园报告信息
     *
     * @param kindergartenId 幼儿园id
     * @param batchCode      批次编号
     * @return 个人报告信息结果
     */
    private File fileHandle(Long kindergartenId, String batchCode, KindergartenInfo kindergartenInfo) {
        //文件路径
        String checkReportPath = XinYiLuConfig.getProfile() + xinYiLuConfig.getKindergartenCheckReportUrl() + "/" + kindergartenId + "/" + batchCode;
        File checkReportFile = new File(checkReportPath);
        if (!checkReportFile.exists()) {
            //文件路径不存在，创建文件路径
            boolean createMkdirs = checkReportFile.mkdirs();
            if (BooleanUtils.isFalse(createMkdirs)) {
                throw new ServiceException("幼儿园检测报告文件目录创建失败！");
            }
        }
        String kindergartenName = StringUtils.isBlank(kindergartenInfo.getKindergartenName()) ? "" : kindergartenInfo.getKindergartenName();
        //报告名称
        String checkReportName = checkReportPath + "/" + kindergartenName + "_" + batchCode + "_幼儿园检测报告书.pdf";
        File checkReportNameFile = new File(checkReportName);
        if (checkReportNameFile.exists()) {
            //文件名称已存在，删除文件
            boolean delete = checkReportNameFile.delete();
            if (BooleanUtils.isFalse(delete)) {
                throw new ServiceException("幼儿园检测报告文件删除失败！");
            }
            //删除数据库报告信息
            int deleteKindergartenCount = kindergartenCheckReportMapper.deleteKindergartenReportInfo(kindergartenId, batchCode);
            if (deleteKindergartenCount <= 0) {
                throw new ServiceException("删除幼儿园检测报告信息失败，请联系管理员！");
            }
        }
        return checkReportNameFile;
    }
}
