package com.yida.data.school.smart.service.impl;

import cc.mrbird.febs.common.redis.service.RedisService;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yida.data.common.core.entity.CurrentUser;
import com.yida.data.common.core.entity.constant.CachePrefixConstant;
import com.yida.data.common.core.entity.smart.EduSmartWelcomeGuideClassRecord;
import com.yida.data.common.core.entity.smart.EduSmartWelcomeGuideDormRecord;
import com.yida.data.common.core.entity.smart.EduSmartWelcomeGuideRoster;
import com.yida.data.common.core.entity.smart.EduSmartWelcomeGuideRosterRelation;
import com.yida.data.common.core.entity.smart.EduSmartWelcomeGuideRosterRelationStep;
import com.yida.data.common.core.entity.smart.EduSmartWelcomeGuideStep;
import com.yida.data.common.core.entity.system.SystemUser;
import com.yida.data.common.core.entity.user.EduParent;
import com.yida.data.common.core.entity.user.EduStudent;
import com.yida.data.common.core.enums.*;
import com.yida.data.common.core.file.common.DownloadFileChunk;
import com.yida.data.common.core.exception.FebsException;
import com.yida.data.common.core.utils.*;
import com.yida.data.school.dto.smart.*;
import com.yida.data.school.smart.config.ExportGuidePicClient;
import com.yida.data.school.smart.excel.GuideRosterExcelListener;
import com.yida.data.school.smart.excel.SelectGuidePicExportData;
import com.yida.data.school.smart.mapper.EduSmartWelcomeGuideRosterMapper;
import com.yida.data.school.smart.service.*;
import com.yida.data.school.vo.smart.*;
import com.yida.data.system.feign.RemoteUserService;
import com.yida.data.user.feign.RemoteStudentService;

import java.util.stream.Collectors;
import java.util.stream.Stream;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StopWatch;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.util.*;

/**
 * 智慧迎新指南花名册表Service实现
 *
 * @author ZYJ
 * @date 2023-05-16 15:06:19
 */
@Slf4j
@Service
@RequiredArgsConstructor
@Transactional(rollbackFor = Exception.class)
public class EduSmartWelcomeGuideRosterServiceImpl extends ServiceImpl
        <EduSmartWelcomeGuideRosterMapper, EduSmartWelcomeGuideRoster> implements EduSmartWelcomeGuideRosterService {

    @Lazy
    @Resource
    private ImportGuideRosterService importGuideRosterService;

    private final EduSmartWelcomeGuideStepService eduSmartWelcomeGuideStepService;
    private final EduSmartWelcomeGuideRosterRelationService eduSmartWelcomeGuideRosterRelationService;
    private final EduSmartWelcomeGuideRosterRelationStepService eduSmartWelcomeGuideRosterRelationStepService;

    private final RemoteUserService remoteUserService;
    private final RemoteStudentService remoteStudentService;
    private final EduSmartWelcomeGuideStepClassService eduSmartWelcomeGuideStepClassService;
    private final EduSmartWelcomeGuideClassRecordService eduSmartWelcomeGuideClassRecordService;
    private final EduSmartWelcomeGuideStepDormService eduSmartWelcomeGuideStepDormService;
    private final EduSmartWelcomeGuideDormRecordService eduSmartWelcomeGuideDormRecordService;

    private final RedisService redisService;

    @Autowired
    ApplicationContext applicationContext;

    @Value("${febs.uploadUrl}")
    private String uploadUrl;

    @Lazy
    @Resource
    private ExportGuidePicClient exportGuidePicClient;

    @Override
    public void saveGuideFillInfo(GuideFillInfoSaveDTO dto) {
        // 查询花名册基础信息
        EduSmartWelcomeGuideRoster guideRoster = getOne(Wrappers.lambdaQuery(new EduSmartWelcomeGuideRoster())
                .eq(EduSmartWelcomeGuideRoster::getDeptId, dto.getDeptId())
                .eq(EduSmartWelcomeGuideRoster::getGuideId, dto.getGuideId())
                .eq(EduSmartWelcomeGuideRoster::getFullName, dto.getName())
                .eq(EduSmartWelcomeGuideRoster::getIdNumber, dto.getIdNumber())
                .eq(EduSmartWelcomeGuideRoster::getAdmittedMajor, dto.getAdmittedMajor())
        );
        if (Objects.isNull(guideRoster)) {
            throw new FebsException("您填写的信息与教育系统内不一致，请修改后再试");
        }
        // 判断是否绑定过当前指南的信息
        EduSmartWelcomeGuideRosterRelation exist = eduSmartWelcomeGuideRosterRelationService
                .getOne(Wrappers.lambdaQuery(new EduSmartWelcomeGuideRosterRelation())
                        .eq(EduSmartWelcomeGuideRosterRelation::getGuideId, dto.getGuideId())
                        .eq(EduSmartWelcomeGuideRosterRelation::getOpenId, dto.getOpenId())
                );
        if (Objects.nonNull(exist)) {
            throw new FebsException("当前账号已经绑定过信息！");
        }
        // 判断是否绑定过
        EduSmartWelcomeGuideRosterRelation relation = eduSmartWelcomeGuideRosterRelationService
                .getOne(Wrappers.lambdaQuery(new EduSmartWelcomeGuideRosterRelation())
                                .eq(EduSmartWelcomeGuideRosterRelation::getRosterId, guideRoster.getId())
//                .eq(EduSmartWelcomeGuideRosterRelation::getOpenId, dto.getOpenId())
                );
        if (Objects.nonNull(relation)) {
            if (Objects.nonNull(guideRoster.getDormitoryId()) || Objects.nonNull(guideRoster.getClassId())) {
                throw new FebsException("该信息已被绑定！请联系工作人员");
            } else {
                // 清除绑定数据
                EduSmartWelcomeGuideRosterServiceImpl bean = applicationContext
                        .getBean(EduSmartWelcomeGuideRosterServiceImpl.class);
                bean.deleteRosterInfo(guideRoster.getId());
            }
        }
        // 判断是否需要添加登录用户信息
        SystemUser user = remoteUserService.getInfoByUsernameNoPermission(guideRoster.getMobile()).getData();
        if (Objects.isNull(user)) {
            user = new SystemUser();
            user.setDeptId(dto.getDeptId());
            user.setUsername(guideRoster.getMobile());
            user.setNickname(guideRoster.getMobile());
            user.setMobile(guideRoster.getMobile());
            user.setSex(ObjectUtil.isNull(dto.getSex()) ? null : String.valueOf(dto.getSex()));
            user.setAvatar(dto.getAvatar());
            user.setUserOrigin(0);
            user = remoteUserService.addUser(user).getData();
        }
        // 添加关联关系
        relation = new EduSmartWelcomeGuideRosterRelation();
        BeanUtils.copyProperties(dto, relation);
        relation.setRosterId(guideRoster.getId());
        relation.setUserId(user.getUserId());
        eduSmartWelcomeGuideRosterRelationService.saveOrUpdate(relation);

        //变更花名册信息
        guideRoster.setAdmissionLetter(dto.getAdmissionLetter());
        guideRoster.setAdmittedDepartment(dto.getAdmittedDepartment());
        guideRoster.setAdmittedDepartmentId(dto.getAdmittedDepartmentId());
        guideRoster.setAdmittedMajor(dto.getAdmittedMajor());
        guideRoster.setAdmittedMajorId(dto.getAdmittedMajorId());
        guideRoster.setIdCardReverse(dto.getIdCardReverse());
        guideRoster.setIdCardRight(dto.getIdCardRight());
        updateById(guideRoster);
    }

    @Override
    public void deleteRosterInfo(Long rosterId) {
        // 删除绑定人员步骤信息
        eduSmartWelcomeGuideRosterRelationStepService.remove(Wrappers.lambdaQuery(new EduSmartWelcomeGuideRosterRelationStep())
                .eq(EduSmartWelcomeGuideRosterRelationStep::getRosterId, rosterId));
        // 删除绑定关系
        eduSmartWelcomeGuideRosterRelationService.remove(Wrappers.lambdaQuery(new EduSmartWelcomeGuideRosterRelation())
                .eq(EduSmartWelcomeGuideRosterRelation::getRosterId, rosterId));
    }

    @Override
    public IPage<Map<String, String>> listGuideRoster(GuideRosterSelectPageDTO dto) {
        if (ObjectUtil.isNotNull(dto.getPassStepId())) {
            // 查询出完成步骤的人员信息
            List<EduSmartWelcomeGuideRosterRelationStep> relationStepList = eduSmartWelcomeGuideRosterRelationStepService
                    .list(Wrappers.lambdaQuery(new EduSmartWelcomeGuideRosterRelationStep())
                            .eq(EduSmartWelcomeGuideRosterRelationStep::getGuideId, dto.getGuideId())
                            .eq(EduSmartWelcomeGuideRosterRelationStep::getStatus, AuditStatusEnum.PASS_STATUS.getStatus())
                            .eq(EduSmartWelcomeGuideRosterRelationStep::getStepId, dto.getPassStepId()));
            if (CollUtil.isNotEmpty(relationStepList)) {
                dto.setPassRosterIdList(relationStepList.stream().map(EduSmartWelcomeGuideRosterRelationStep::getRosterId)
                        .collect(Collectors.toList()));
            }
        }
        IPage<GuideRosterSelectPageVO> page = baseMapper.listGuideRoster(dto.toPage(), dto);
        // 实际返回的分页数据
        Page<Map<String, String>> returnPage = new Page<>();
        BeanUtils.copyProperties(page, returnPage);
        List<Map<String, String>> returnList = new ArrayList<>();

        for (GuideRosterSelectPageVO vo : page.getRecords()) {
            Map<String, String> map = JSONObject
                    .parseObject(JSONObject.toJSONString(vo), new TypeReference<Map<String, String>>() {
                    });
            EduSmartWelcomeGuideRosterRelation relation = eduSmartWelcomeGuideRosterRelationService
                    .getOne(Wrappers.lambdaQuery(new EduSmartWelcomeGuideRosterRelation())
                            .eq(EduSmartWelcomeGuideRosterRelation::getRosterId, vo.getRosterId())
                    );
            // 处理步骤信息
            List<EduSmartWelcomeGuideStep> stepList = eduSmartWelcomeGuideStepService.
                    listStepInfo(Objects.nonNull(relation) ? relation.getId() : null, dto.getGuideId());
            if (CollUtil.isNotEmpty(stepList)) {
                stepList.forEach(step -> map.put(step.getId().toString(), step.getStatus().toString()));
            }
            returnList.add(map);
        }
        returnPage.setRecords(returnList);
        return returnPage;
    }

    @Override
    public List<StatisticsGuideRosterVO> statisticsGuideRoster(Long guideId) {
        List<StatisticsGuideRosterVO> list = new ArrayList<>();
        // 查询花名册数量
        long totalNumber = count(Wrappers.lambdaQuery(new EduSmartWelcomeGuideRoster())
                .eq(EduSmartWelcomeGuideRoster::getGuideId, guideId));
        // 查询报到成功人数
        long successNumber = count(Wrappers.lambdaQuery(new EduSmartWelcomeGuideRoster())
                .eq(EduSmartWelcomeGuideRoster::getGuideId, guideId)
                .eq(EduSmartWelcomeGuideRoster::getRegistrationStatus, RegistrationStatusEnum.REGISTRATION_SUCCESS.getStatus())
        );
        list.add(StatisticsGuideRosterVO.builder()
                .cardName("报到完成")
                .totalNumber(Math.toIntExact(totalNumber))
                .executeNumber(Math.toIntExact(successNumber))
                .build());
        // 查询需要审核的步骤信息
        List<EduSmartWelcomeGuideStep> stepList = eduSmartWelcomeGuideStepService
                .list(Wrappers.lambdaQuery(new EduSmartWelcomeGuideStep())
                        .eq(EduSmartWelcomeGuideStep::getGuideId, guideId)
                        .in(EduSmartWelcomeGuideStep::getStepType,
                                Arrays.asList(GuideStepTypeEnum.EXAMINE_TYPE.getType(),
                                        GuideStepTypeEnum.MATCH_FACE.getType(),
                                        GuideStepTypeEnum.CLASS.getType(),
                                        GuideStepTypeEnum.DORM.getType()
                                )
                        )
                );
        for (EduSmartWelcomeGuideStep step : stepList) {
            long executeNumber = 0;
            // 花名册信息不为0
            if (totalNumber != 0) {
                // 查询步骤通过数量
                executeNumber = eduSmartWelcomeGuideRosterRelationStepService
                        .count(Wrappers.lambdaQuery(new EduSmartWelcomeGuideRosterRelationStep())
                                .eq(EduSmartWelcomeGuideRosterRelationStep::getStepId, step.getId())
                                .eq(EduSmartWelcomeGuideRosterRelationStep::getStatus, AuditStatusEnum.PASS_STATUS.getStatus())
                        );
            }
            list.add(StatisticsGuideRosterVO.builder()
                    .cardName(step.getStepName())
                    .totalNumber(Math.toIntExact(totalNumber))
                    .executeNumber(Math.toIntExact(executeNumber))
                    .build());
        }
        return list;
    }

    @Override
    public GuideRosterInfoVO getGuideRosterInfo(Long rosterId) {
        GuideRosterInfoVO vo = new GuideRosterInfoVO();
        EduSmartWelcomeGuideRoster guideRoster = getById(rosterId);
        if (Objects.nonNull(guideRoster)) {
            BeanUtils.copyProperties(guideRoster, vo);
            vo.setRosterId(guideRoster.getId());
            // 处理步骤信息
            List<EduSmartWelcomeGuideStep> stepList =
                    eduSmartWelcomeGuideStepService.listStepDetailInfo(rosterId, guideRoster.getGuideId());
            vo.setStepList(stepList);
            // 查询关联关系
            EduSmartWelcomeGuideRosterRelation relation = eduSmartWelcomeGuideRosterRelationService
                    .getOne(Wrappers.lambdaQuery(new EduSmartWelcomeGuideRosterRelation())
                            .eq(EduSmartWelcomeGuideRosterRelation::getRosterId, rosterId));
            if (Objects.nonNull(relation)) {
                vo.setAvatar(relation.getAvatar());
                vo.setSex(relation.getSex());
            }
        }
        return vo;
    }

    @Override
    public void importGuideRoster(String fileUrl, Long guideId, CurrentUser currentUser, String uuid) {
        // 上传的excel文件
        File file = null;
        // 错误信息文件excel
        File errorFile = null;
        try {
            StopWatch stopWatch = new StopWatch();
            stopWatch.start();
            // 调用导入方法
            List<GuideRosterErrorExportDTO> errorList = new ArrayList<>();
            file = new File(fileUrl);
            EasyExcel.read(file, GuideRosterImportDTO.class,
                            new GuideRosterExcelListener(importGuideRosterService, errorList, guideId, uuid, currentUser))
                    .sheet().headRowNumber(1).doRead();
            stopWatch.stop();
            log.info("导入指南花名册数据总共耗时: {}", stopWatch.getTotalTimeSeconds() + "秒");
            // 判断是否有错误数据
            if (CollUtil.isNotEmpty(errorList)) {
                // 错误信息文件名称
                String fileName = FileUtil.getLocalUploadAddress() + uuid + ".xlsx";
                EasyExcel.write(fileName, GuideRosterErrorExportDTO.class)
                        .sheet("错误信息")
                        .doWrite(errorList);
                // 上传到媒资
                errorFile = new File(fileName);
                String url = FileUtil.uploadFileToMediaServer(uploadUrl, errorFile);
                // 保存导入不成功的数据和原因
                redisService.set(CachePrefixConstant.IMPORT_GUIDE_ROSTER_KEY + uuid,
                        ImportRosterDataVO.builder().percent(100).finish(1).key(uuid).filePath(url)
                                .build());
            } else {
                redisService.set(CachePrefixConstant.IMPORT_GUIDE_ROSTER_KEY + uuid,
                        ImportRosterDataVO.builder().percent(100).finish(1).key(uuid)
                                .build());
            }
        } catch (Exception e) {
            log.error("导入指南花名册数据失败: {}", e.getMessage(), e);
            throw new FebsException("导入失败！请重新操作");
        } finally {
            if (Objects.nonNull(file)) {
                cn.hutool.core.io.FileUtil.del(file);
            }
            if (Objects.nonNull(errorFile)) {
                cn.hutool.core.io.FileUtil.del(errorFile);
            }
        }
    }

    @Override
    public void downloadGuideTemplate(HttpServletResponse response) {
        try {
            String fileName = "花名册导入模板.xls";
            // 获取导入文件模板
            ClassPathResource classPathResource = new ClassPathResource("template/" + fileName);
            InputStream inputStream = classPathResource.getInputStream();
            FileUtil.download(FileUtil.inputStreamToFile(inputStream), fileName, false, response);
        } catch (Exception e) {
            throw new FebsException("下载指南花名册导入模板失败！");
        }
    }

    @Override
    public EduSmartWelcomeGuideRosterRelation getRosterInfo(Long rosterId, Long staffId) {
        EduSmartWelcomeGuideRoster guideRoster = getById(rosterId);
        if (Objects.isNull(guideRoster)) {
            throw new FebsException("人员信息错误！");
        }
        EduSmartWelcomeGuideRosterRelation relation = eduSmartWelcomeGuideRosterRelationService
                .getOne(Wrappers.lambdaQuery(new EduSmartWelcomeGuideRosterRelation())
                        .eq(EduSmartWelcomeGuideRosterRelation::getRosterId, rosterId));
        if (Objects.isNull(relation)) {
            throw new FebsException("人员信息错误！");
        }
        relation.setGuideRoster(guideRoster);
        // 查询步骤信息
        List<EduSmartWelcomeGuideStep> stepList = eduSmartWelcomeGuideStepService
                .listExamineStepInfo(guideRoster.getId(), guideRoster.getGuideId(), staffId);
        relation.setStepList(stepList);
        return relation;
    }

    @Override
    public void passStep(StaffPassStepDTO dto) {
        EduSmartWelcomeGuideRoster guideRoster = (EduSmartWelcomeGuideRoster) redisService
                .hget(CachePrefixConstant.WELCOME_ROSTER, dto.getRosterId().toString());

        if (ObjectUtil.isNull(guideRoster)) {
            guideRoster = getById(dto.getRosterId());
        }

        if (Objects.isNull(guideRoster)) {
            throw new FebsException("人员信息错误！");
        }
        // 判断前提步骤信息
        EduSmartWelcomeGuideStep step = eduSmartWelcomeGuideStepService.getById(dto.getStepId());
        if (Objects.isNull(step)) {
            throw new FebsException("步骤信息错误！");
        }
        if (Objects.nonNull(step.getPremiseStepId())) {
            EduSmartWelcomeGuideStep premiseStep = eduSmartWelcomeGuideStepService
                    .premiseStep(step.getPremiseStepId(), new EduSmartWelcomeGuideStep());
            if (ObjectUtil.isNotNull(premiseStep)) {
                if (ObjectUtil.equals(GuideStepTypeEnum.EXAMINE_TYPE.getType(), premiseStep.getStepType()) || ObjectUtil
                        .equals(GuideStepTypeEnum.CLASS.getType(), premiseStep.getStepType()) ||
                        ObjectUtil.equals(GuideStepTypeEnum.DORM.getType(), premiseStep.getStepType())
                        || ObjectUtil.equals(GuideStepTypeEnum.MATCH_FACE.getType(), premiseStep.getStepType())) {
                    EduSmartWelcomeGuideRosterRelationStep premiseRelationStep = eduSmartWelcomeGuideRosterRelationStepService
                            .getOne(Wrappers.lambdaQuery(new EduSmartWelcomeGuideRosterRelationStep())
                                    .eq(EduSmartWelcomeGuideRosterRelationStep::getRosterId, dto.getRosterId())
                                    .eq(EduSmartWelcomeGuideRosterRelationStep::getStepId, premiseStep.getId())
                                    .eq(EduSmartWelcomeGuideRosterRelationStep::getStatus, AuditStatusEnum.PASS_STATUS.getStatus())
                            );
                    if (Objects.isNull(premiseRelationStep)) {
                        throw new FebsException(String.format("请审核通过【%s】后执行其它步骤！", premiseStep.getStepName()));
                    }
                }
            }
        }
        // 判断是否审核通过
        EduSmartWelcomeGuideRosterRelationStep relationStep = eduSmartWelcomeGuideRosterRelationStepService
                .getOne(Wrappers.lambdaQuery(new EduSmartWelcomeGuideRosterRelationStep())
                        .eq(EduSmartWelcomeGuideRosterRelationStep::getRosterId, dto.getRosterId())
                        .eq(EduSmartWelcomeGuideRosterRelationStep::getStepId, dto.getStepId())
                        .eq(EduSmartWelcomeGuideRosterRelationStep::getStatus, AuditStatusEnum.PASS_STATUS.getStatus()));
        if (Objects.nonNull(relationStep)) {
            throw new FebsException("该步骤已经审核通过！请勿重复操作");
        }
        // 保存审核信息
        EduSmartWelcomeGuideRosterRelationStep smartWelcomeGuideRosterRelationStep = eduSmartWelcomeGuideRosterRelationStepService
                .getOne(Wrappers.lambdaQuery(new EduSmartWelcomeGuideRosterRelationStep())
                        .eq(EduSmartWelcomeGuideRosterRelationStep::getGuideId, guideRoster.getGuideId())
                        .eq(EduSmartWelcomeGuideRosterRelationStep::getStepId, dto.getStepId())
                        .eq(EduSmartWelcomeGuideRosterRelationStep::getRelationId, dto.getRelationId()));

        if (ObjectUtil.isNull(smartWelcomeGuideRosterRelationStep)) {
            EduSmartWelcomeGuideRosterRelationStep saveInfo = new EduSmartWelcomeGuideRosterRelationStep();
            BeanUtils.copyProperties(dto, saveInfo);
            saveInfo.setDeptId(guideRoster.getDeptId());
            saveInfo.setGuideId(guideRoster.getGuideId());
            saveInfo.setRosterId(guideRoster.getId());
            saveInfo.setRelationId(dto.getRelationId());
            saveInfo.setOperateTime(LocalDateTime.now());
            saveInfo.setStatus(AuditStatusEnum.PASS_STATUS.getStatus());
            saveInfo.setCommentContent(dto.getCommentContent());
            eduSmartWelcomeGuideRosterRelationStepService.save(saveInfo);
        } else {
            eduSmartWelcomeGuideRosterRelationStepService
                    .update(Wrappers.lambdaUpdate(new EduSmartWelcomeGuideRosterRelationStep())
                            .eq(EduSmartWelcomeGuideRosterRelationStep::getId, smartWelcomeGuideRosterRelationStep.getId())
                            .set(EduSmartWelcomeGuideRosterRelationStep::getStatus, AuditStatusEnum.PASS_STATUS.getStatus())
                            .set(EduSmartWelcomeGuideRosterRelationStep::getCommentContent, dto.getCommentContent()));
        }

        //判断步骤类型分配班级和宿舍
        if (ObjectUtil.equals(GuideStepTypeEnum.CLASS.getType(), step.getStepType())) {
            eduSmartWelcomeGuideStepClassService.classBanding(guideRoster.getGuideId(), step.getId(), dto.getRosterId());
        }

        if (ObjectUtil.equals(GuideStepTypeEnum.DORM.getType(), step.getStepType())) {
            eduSmartWelcomeGuideStepDormService.dormBanding(guideRoster.getGuideId(), step.getId(), dto.getRosterId());
        }

        // 判断是否全部通过
        long passCount = eduSmartWelcomeGuideRosterRelationStepService
                .count(Wrappers.lambdaQuery(new EduSmartWelcomeGuideRosterRelationStep())
                        .eq(EduSmartWelcomeGuideRosterRelationStep::getRosterId, dto.getRosterId())
                        .eq(EduSmartWelcomeGuideRosterRelationStep::getStatus, AuditStatusEnum.PASS_STATUS.getStatus())
                );
        List<EduSmartWelcomeGuideStep> stepList = eduSmartWelcomeGuideStepService
                .list(Wrappers.lambdaQuery(new EduSmartWelcomeGuideStep())
                        .eq(EduSmartWelcomeGuideStep::getGuideId, guideRoster.getGuideId()));

        //需要审核的步骤
        List<EduSmartWelcomeGuideStep> needStepList = stepList.stream()
                .filter(s -> !s.getStepType().equals(GuideStepTypeEnum.NOTICE.getType())).collect(Collectors.toList());

        if (passCount == needStepList.size()) {
            EduSmartWelcomeGuideRoster saveRoster = new EduSmartWelcomeGuideRoster();
            saveRoster.setId(guideRoster.getId());
            saveRoster.setRegistrationStatus(RegistrationStatusEnum.REGISTRATION_SUCCESS.getStatus());
            updateById(saveRoster);

            //增加新生到学生库，以及分配宿舍
            //@Async注解是通过aop代理实现的，而我们调用自己类的异步方法时，绕过了aop代理从而导致其异步失效
            EduSmartWelcomeGuideRosterServiceImpl bean = applicationContext.getBean(EduSmartWelcomeGuideRosterServiceImpl.class);
            bean.addStudent(dto.getRosterId(), FebsUtil.getTopDeptId());
        }
    }

    @Async
    public void addStudent(Long rosterId, Long schoolId) {

        EduSmartWelcomeGuideRoster roster = (EduSmartWelcomeGuideRoster) redisService
                .hget(CachePrefixConstant.WELCOME_ROSTER, rosterId.toString());
        if (ObjectUtil.isNull(roster)) {
            roster = this.getById(rosterId);
        }
        EduSmartWelcomeGuideClassRecord classRecord = eduSmartWelcomeGuideClassRecordService
                .getOne(Wrappers.lambdaQuery(new EduSmartWelcomeGuideClassRecord())
                        .eq(EduSmartWelcomeGuideClassRecord::getRosterId, rosterId));

        EduSmartWelcomeGuideDormRecord dormRecord = eduSmartWelcomeGuideDormRecordService
                .getOne(Wrappers.lambdaQuery(new EduSmartWelcomeGuideDormRecord())
                        .eq(EduSmartWelcomeGuideDormRecord::getRosterId, rosterId));

        EduStudent student = new EduStudent();
        student.setStuName(roster.getFullName());
        student.setStuSex(roster.getGender().toString());
        student.setAvatar(roster.getAvatar());
        student.setIdNumber(roster.getIdNumber());
        if (ObjectUtil.isNotNull(classRecord)) {
            student.setSchoolId(classRecord.getSchoolId());
            student.setCampusId(classRecord.getCampusId());
            student.setSectionId(classRecord.getSectionId());
            student.setGradeId(classRecord.getGradeId());
            student.setClassId(classRecord.getClassId());
        } else {
            //查询校区
//            Dept dept = remoteDeptService.getSchoolByName(roster.getAdmittedDepartment()).getData();
            student.setSchoolId(schoolId);
//            student.setCampusId(dept.getDeptId());
        }

        if (ObjectUtil.isNotNull(dormRecord)) {
            student.setDormId(dormRecord.getDormId());
            student.setDormRoomId(dormRecord.getDormRoomId());
            student.setType(1);//住宿
        }

        EduParent parent = new EduParent();
        parent.setParentType("本人");
        parent.setMobile(roster.getMobile());
        student.setParents(Stream.of(parent).collect(Collectors.toList()));
        log.info("智慧迎新完成增加学生：【{}】", student);
        EduStudent eduStudent = remoteStudentService.saveStudent(student).getData();
        //保存宿舍
//        if (ObjectUtil.isNotNull(eduStudent)) {
//            eduStudent.setDormId(student.getDormId());
//            eduStudent.setDormRoomId(student.getDormRoomId());
//            remoteStudentService.saveStudentDorm(eduStudent);
//        }
    }


    @Override
    public void exportRosterInfoData(GuideRosterSelectPageDTO dto, String uuid) {
        String fileName = FileUtil.getLocalUploadAddress() + uuid + ".xls";
        File file = null;
        try {
            StopWatch stopWatch = new StopWatch();
            stopWatch.start();
            // 查询花名册信息
            if (ObjectUtil.isNotNull(dto.getPassStepId())) {
                // 查询出完成步骤的人员信息
                List<EduSmartWelcomeGuideRosterRelationStep> relationStepList = eduSmartWelcomeGuideRosterRelationStepService
                        .list(Wrappers.lambdaQuery(new EduSmartWelcomeGuideRosterRelationStep())
                                .eq(EduSmartWelcomeGuideRosterRelationStep::getGuideId, dto.getGuideId())
                                .eq(EduSmartWelcomeGuideRosterRelationStep::getStepId, dto.getPassStepId()));
                if (CollUtil.isNotEmpty(relationStepList)) {
                    dto.setPassRosterIdList(relationStepList.stream().map(EduSmartWelcomeGuideRosterRelationStep::getRosterId)
                            .collect(Collectors.toList()));
                }
            }
            List<GuideRosterSelectPageVO> list = baseMapper.listGuideRoster(dto);
            int listSize = list.size();
            // 导出的信息
            List<List<String>> exportDataList = new ArrayList<>();
            for (int i = 0; i < listSize; i++) {
                GuideRosterSelectPageVO vo = list.get(i);
                if (redisService.hasKey(CachePrefixConstant.GUIDE_ROSTER_STEP_DATA + vo.getRosterId())) {
                    String str = (String) redisService.get(CachePrefixConstant.GUIDE_ROSTER_STEP_DATA + vo.getRosterId());
                    List<String> strings = JSON.parseArray(str, String.class);
                    exportDataList.add(strings);
                    continue;
                }

                Boolean isCache = true;

                redisService.hset(CachePrefixConstant.GUIDE_ROSTER_DATA_DOWNLOAD, uuid, ExportRosterDataVO.builder()
                        .key(uuid)
                        .exportStatus(FileDealStatusEnum.DEALING.getStatus())
                        .totalNum(listSize)
                        .currentNum(i).build());
                // 查询绑定关系
                EduSmartWelcomeGuideRosterRelation relation = eduSmartWelcomeGuideRosterRelationService
                        .getOne(Wrappers.lambdaQuery(new EduSmartWelcomeGuideRosterRelation())
                                .eq(EduSmartWelcomeGuideRosterRelation::getRosterId, vo.getRosterId())
                        );
                // 封装每一行数据
                ArrayList<String> singleList = CollUtil.newArrayList(vo.getIdNumber(),
                        vo.getFullName(), vo.getAdmittedMajor(), vo.getGraduateSchool(), vo.getDormitory(), vo.getDormitoryRoom(),
                        vo.getCampusName(), vo.getSectionName(), vo.getClassName());
                // 处理步骤信息
                List<EduSmartWelcomeGuideStep> stepList = eduSmartWelcomeGuideStepService.
                        listStepInfo(Objects.nonNull(relation) ? relation.getId() : null, dto.getGuideId());
                if (CollUtil.isNotEmpty(stepList)) {
                    for (EduSmartWelcomeGuideStep step : stepList) {
                        try {
                            // 获取步骤类型
                            GuideStepTypeEnum stepTypeEnum = EnumUtils.valueOf(GuideStepTypeEnum.class, step.getStepType(),
                                    GuideStepTypeEnum.class.getMethod("getType"));
                            if (!Objects.requireNonNull(stepTypeEnum).isExamineFlag()) {
                                singleList.add("√");
                            } else {
                                singleList.add(step.getStatus() == 0 ? "√" : "--");
                                if (step.getStatus() != 0) {
                                    isCache = false;
                                }
                            }
                        } catch (Exception e) {
                            isCache = false;
                        }
                    }
                }
                // 添加excel数据
                if (isCache) {
                    redisService
                            .set(CachePrefixConstant.GUIDE_ROSTER_STEP_DATA + vo.getRosterId(),
                                    JSONObject.toJSON(singleList).toString());
                }
                exportDataList.add(singleList);
            }
            file = new File(fileName);
            // 导出数据
            EasyExcel.write(file)
                    .excelType(ExcelTypeEnum.XLS)
                    // 这里放入动态头
                    .head(getExportHead(dto.getGuideId())).sheet("花名册")
                    // 当然这里数据也可以用 List<List<String>> 去传入
                    .doWrite(exportDataList);
            // 上传文件到媒资
            String fileUrl = FileUtil.uploadFileToMediaServer(uploadUrl, file);
            redisService.hset(CachePrefixConstant.GUIDE_ROSTER_DATA_DOWNLOAD, uuid, ExportRosterDataVO.builder()
                    .key(uuid)
                    .filePath(fileUrl)
                    .exportStatus(FileDealStatusEnum.DEAL_SUCCESS.getStatus())
                    .totalNum(listSize == 0 ? 1 : listSize)
                    .currentNum(listSize == 0 ? 1 : listSize).build());
            stopWatch.stop();
            log.info("导出花名册信息总共耗时: {}", stopWatch.getTotalTimeSeconds() + "秒");
        } catch (Exception e) {
            log.error("导出花名册信息错误", e);
            redisService.hset(CachePrefixConstant.GUIDE_ROSTER_DATA_DOWNLOAD, uuid, ExportRosterDataVO.builder()
                    .key(uuid)
                    .exportStatus(FileDealStatusEnum.DEAL_FAIL.getStatus()).build());
        } finally {
            if (Objects.nonNull(file)) {
                cn.hutool.core.io.FileUtil.del(file);
            }
        }
    }

    /**
     * 生成花名册导出数据excel表头
     *
     * @param guideId 指南id
     * @return java.util.List<java.util.List < java.lang.String>>
     * @author ZYJ
     * @date 2023/8/26 14:20
     */
    private List<List<String>> getExportHead(Long guideId) {
        // 表头list的生成，实际的表头信息可以从数据库或者缓存等处动态读取
        List<List<String>> allColList = new ArrayList<>();
        // 身份证号表头
        allColList.add(CollUtil.newArrayList("身份证号"));
        // 姓名表头
        allColList.add(CollUtil.newArrayList("姓名"));
        // 录取专业表头
        allColList.add(CollUtil.newArrayList("录取专业"));
        // 毕业学校表头
        allColList.add(CollUtil.newArrayList("毕业学校"));
        allColList.add(CollUtil.newArrayList("分配宿舍楼"));
        allColList.add(CollUtil.newArrayList("分配宿舍号"));
        allColList.add(CollUtil.newArrayList("分配校区"));
        allColList.add(CollUtil.newArrayList("分配系部"));
        allColList.add(CollUtil.newArrayList("分配班级"));
        // 动态表头
        List<GuideStepColVO> colList = eduSmartWelcomeGuideStepService.listGuideRosterTableCol(guideId);
        colList.forEach(item -> allColList.add(CollUtil.newArrayList(item.getStepName())));
        return allColList;
    }

    @Override
    public void createRosterQrCode(Long rosterId, Long guideId) {
        EduSmartWelcomeGuideRoster guideRoster = getById(rosterId);
        if (Objects.isNull(guideRoster)) {
            throw new FebsException("花名册信息错误");
        }
        if (StrUtil.isNotBlank(guideRoster.getQrCodeUrl())) {
            throw new FebsException("该人员已经生成过二维码了！请勿重复操作");
        }
        File qrCodeFile = null;
        try {
            cn.hutool.json.JSONObject obj = JSONUtil.createObj()
                    .set("rosterId", guideRoster.getId())
                    .set("deptId", Objects.requireNonNull(FebsUtil.getCurrentUser()).getDeptId())
                    .set("guideId", guideId)
                    .set("fullName", guideRoster.getFullName())
                    .set("graduateSchool", guideRoster.getGraduateSchool())
                    .set("idNumber", guideRoster.getIdNumber())
                    .set("admittedMajor", guideRoster.getAdmittedMajor());
            // 生成文件名称
            String fileName = UUID.randomUUID().toString(true) + ".png";
            String filePath = FileUtil.getLocalUploadAddress() + fileName;
            QrCodeUtil.generateQrCodeImage(obj.toString(), 400, 400, filePath);
            // 上传文件到媒资
            qrCodeFile = new File(filePath);
            String qrCodeAddress = FileUtil.uploadFileToMediaServer(uploadUrl, qrCodeFile);
            baseMapper.updateById(
                    EduSmartWelcomeGuideRoster.builder()
                            .id(guideRoster.getId())
                            .qrCodeUrl(qrCodeAddress)
                            .build());
        } catch (Exception e) {
            log.error("生成二维码失败", e);
            throw new FebsException("生成二维码失败");
        } finally {
            if (Objects.nonNull(qrCodeFile)) {
                cn.hutool.core.io.FileUtil.del(qrCodeFile);
            }
        }
    }

    @Override
    public void exportRosterPic(Long guideId, String key) {
        exportGuidePicClient.exportLargeData(SelectGuidePicExportData.builder()
                .key(key)
                .guideId(guideId)
                .build()
        );
    }

    @Override
    public Object getExportRosterPicInfo(String key) {
        return exportGuidePicClient.selectExportInfo(key);
    }

    @Override
    public void downloadRosterPicChunk(DownloadFileChunk dto, HttpServletResponse response) {
        exportGuidePicClient.downLoadChunk(dto, response);
    }
}
