package com.ruoyi.hezhi.service.impl;


import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.crypto.digest.MD5;
import com.alibaba.fastjson2.JSONObject;
import com.kuaidi100.sdk.contant.CompanyConstant;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ImgUpload;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.asPose.AsposeUtil;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.common.utils.kd100.Kd100Util;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.hezhi.domain.*;
import com.ruoyi.hezhi.domain.dto.ExamRegistrationDTO;
import com.ruoyi.hezhi.domain.dto.PostAddressDTO;
import com.ruoyi.hezhi.domain.vo.TbExamRegistrationCodeVo;
import com.ruoyi.hezhi.domain.vo.TbExamRegistrationVO;
import com.ruoyi.hezhi.domain.vo.TopicImportTemplateVO;
import com.ruoyi.hezhi.mapper.*;
import com.ruoyi.hezhi.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.repository.init.ResourceReader;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.validation.*;
import java.io.FileInputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 考试报名Service业务层处理
 *
 * @author ruoyi
 * @date 2024-11-05
 */
@Slf4j
@Service
@Validated
public class TbExamRegistrationServiceImpl implements ITbExamRegistrationService
{
    @Autowired
    private TbExamRegistrationMapper tbExamRegistrationMapper;
    @Autowired
    private ITbExamService examService;
    @Autowired
    private ITbExamFileService examFileService;
    @Autowired
    private ITbMemberOrderService memberOrderService;
    @Autowired
    private TbMemberScoreMapper tbMemberScoreMapper;
    @Autowired
    private TbConfigMapper tbConfigMapper;
    @Autowired
    private ITbPostAddressService tbPostAddressService;
    @Autowired
    private ITbExpressKdCodeService tbExpressKdCodeService;
    @Autowired
    private TbMemberMajorMapper tbMemberMajorMapper;
    @Autowired
    private TbExamMapper tbExamMapper;
    @Autowired
    private TbExamSimulateInfoMapper tbExamSimulateInfoMapper;
    @Autowired
    private Kd100Util kd100Util;
    @Resource
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;
    @Autowired
    private TbCourseMapper tbCourseMapper;;
    @Resource
    private TbRegionMapper tbRegionMapper;;
    @Autowired
    private TbExamCourseMapper tbExamCourseMapper;
    @Autowired
    private TbExamBatchMapper tbExamBatchMapper;
    @Autowired
    private TbMemberOrderMapper tbMemberOrderMapper;
    @Autowired
    private TbStudyCenterTeacherMapper tbStudyCenterTeacherMapper;

    @Resource
    private TbStudentMapper tbStudentMapper;
    @Resource
    private TbEvaluateAgencyMapper tbEvaluateAgencyMapper;
    @Resource
    private TbStudyCenterMapper tbStudyCenterMapper;

    @Autowired
    private RedisCache redisCache;

    /**
     * 查询考试报名
     *
     * @param examRegistrationId 考试报名主键
     * @return 考试报名
     */
    @Override
    public TbExamRegistration selectTbExamRegistrationByExamRegistrationId(Long examRegistrationId)
    {
        return tbExamRegistrationMapper.selectTbExamRegistrationByExamRegistrationId(examRegistrationId);
    }
    /**
     * 查询发货信息
     *
     * @param examRegistrationId 考试报名主键
     * @return 考试报名
     */
    @Override
    public TbExamRegistration selectTbExamRegistrationByExamRegistrationIdFahuo(Long examRegistrationId)
    {
        return tbExamRegistrationMapper.selectTbExamRegistrationByExamRegistrationIdFahuo(examRegistrationId);
    }

    /**
     * 查询考试报名列表
     *
     * @param tbExamRegistration 考试报名
     * @return 考试报名
     */
    @Override
    public List<TbExamRegistration> selectTbExamRegistrationList(TbExamRegistration tbExamRegistration)
    {
        return tbExamRegistrationMapper.selectTbExamRegistrationList(tbExamRegistration);
    }

    /**
     * 新增考试报名
     *
     * @param tbExamRegistration 考试报名
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertTbExamRegistration(TbExamRegistration tbExamRegistration)
    {
        tbExamRegistration.setCreateTime(DateUtils.getNowDate());
        tbExamRegistration.setPayType(0);
        tbExamRegistration.setIsPay(0);
        Long courseId = tbExamRegistration.getCourseId();
        if (courseId == null){
            throw new ServiceException("请选择课程");
        }
        // 根据课程ID 获取考试ID
        TbExamCourse tbExamCourse = tbExamCourseMapper.getExamIdByCourseId(tbExamRegistration.getCourseId());
        if (ObjectUtils.isEmpty(tbExamCourse)){
            throw new ServiceException("未查询到考试信息");
        }
        TbExam tbExam = examService.selectTbExamByExamId(tbExamCourse.getExamId());
        if (ObjectUtils.isEmpty(tbExam)) {
            throw new ServiceException("考试信息异常，请联系管理员！！！");
        }

        // 查询考试批次
        List<TbExamBatch> tbExamBatchList = tbExamBatchMapper.getEnableByExamId(tbExam.getExamId(), tbExam.getExamBatchEarly());
        if (tbExamBatchList.isEmpty()){
            throw new ServiceException("无可报名批次");
        }
        TbExamBatch tbExamBatch = tbExamBatchList.get(0);
        tbExamRegistration.setExamBatchIndex(tbExamBatch.getBatchIndex().intValue());
        tbExamRegistration.setRegistrationBatch(tbExamBatch.getExamBatch());
        //如果没有用户，创建
        Long userId = tbStudentMapper.selectTbStudentByPhone(tbExamRegistration.getContactInformation());
        if (ObjectUtils.isEmpty(userId)) {
            // 新增用户
            TbStudent insertStudent = new TbStudent();
            //报名信息直接赋值给用户
            insertStudent.setStudentName(tbExamRegistration.getName());//姓名
            insertStudent.setSex(tbExamRegistration.getSex());//性别
            insertStudent.setEducation(tbExamRegistration.getEducation());//学历
            insertStudent.setGraduationSchool(tbExamRegistration.getGraduationSchool());//毕业院校
            insertStudent.setBirthday(tbExamRegistration.getBirthday());//出生日期
            insertStudent.setPhone(tbExamRegistration.getContactInformation());//登录手机号
            insertStudent.setStudentNumber(IdUtils.fastSimpleUUID());
            insertStudent.setCreateTime(DateUtils.getNowDate());
            insertStudent.setExamineStatus(3);
            insertStudent.setFrozenStatus(0);
            insertStudent.setHeadPortrait("https://image.xnszz.com/IMG_1280_1280@FuvEKIdCm5NN36gZN9gJhk2Ei0-p.jpg");
            insertStudent.setNickName("学员_" + IdUtils.fastSimpleUUID().substring(1, 8));

            int row = tbStudentMapper.insertTbStudent(insertStudent);

            //如果成功再次根据手机号查询用户id
            if (row > 0){
                userId = tbStudentMapper.selectTbStudentByPhone(tbExamRegistration.getContactInformation());
            }else {
                // 新增用户失败，记录失败原因
                throw new ServiceException("新增用户失败");
            }
        }else {
            //如果有用户，则补充用户信息
            TbStudent tbStudent = tbStudentMapper.selectTbStudentByStudentId(userId);
            //姓名、性别、学历、毕业院校、出生日期
            if (StringUtils.isEmpty(tbStudent.getStudentName())){
                tbStudent.setStudentName(tbExamRegistration.getName());
            }
            if (tbStudent.getSex() == null|| tbStudent.getSex() == 2){
                tbStudent.setSex(tbExamRegistration.getSex());
            }
            if (StringUtils.isEmpty(tbStudent.getEducation())){
                tbStudent.setEducation(tbExamRegistration.getEducation());
            }
            if (StringUtils.isEmpty(tbStudent.getGraduationSchool())){
                tbStudent.setGraduationSchool(tbExamRegistration.getGraduationSchool());
            }
            if (StringUtils.isEmpty(tbStudent.getBirthday())){
                tbStudent.setBirthday(tbExamRegistration.getBirthday());
            }
            //更新个人资料
            tbStudentMapper.updateTbStudent(tbStudent);
        }
        if(ObjectUtils.isNotEmpty(userId)){
            tbExamRegistration.setMemberUserId(userId);
        }
        //校验当前数据是否在库中已存在
        TbExamRegistration tbExamRegistrations = tbExamRegistrationMapper.selectTbExamRegistrationByBatchIndex(tbExamRegistration);
        if(ObjectUtils.isNotEmpty(tbExamRegistrations)){
            // 数据已存在，记录失败原因
            throw new ServiceException("已报名");
        }
        int row = tbExamRegistrationMapper.insertTbExamRegistration(tbExamRegistration);
        if (row > 0){
            TbMemberMajor tbMemberMajor = tbMemberMajorMapper.selectTbMemberMajorByMemberAndMajorId(tbExamRegistration.getMemberUserId(), null, tbExamRegistration.getCourseId());
            if (tbMemberMajor != null) {
                tbMemberMajor.setUpdateTime(DateUtils.getNowDate());
                tbMemberMajorMapper.updateTbMemberMajor(tbMemberMajor);
            } else {
                TbMemberMajor memberMajor = new TbMemberMajor();
                memberMajor.setMemberUserId(tbExamRegistration.getMemberUserId());
                memberMajor.setResId(tbExamRegistration.getCourseId());
                memberMajor.setCreateTime(DateUtils.getNowDate());
                memberMajor.setType(1);
                tbMemberMajorMapper.insertTbMemberMajor(memberMajor);
            }

            //生成订单
            TbMemberOrder memberOrder = new TbMemberOrder();
            memberOrder.setOrderNo(IdUtil.getSnowflakeNextIdStr());
            memberOrder.setMemberUserId(tbExamRegistration.getMemberUserId());
            memberOrder.setDataId(tbExamRegistration.getExamRegistrationId());
            memberOrder.setPayPrice(tbExam.getPrice());
            memberOrder.setOrderPrice(tbExam.getPrice());
            memberOrder.setDeductionScore(new BigDecimal(0));
            memberOrder.setOrderType(2);
            memberOrder.setPayType(0);
            memberOrder.setPayStatus(0);
            memberOrder.setOrderName(tbExam.getName() + "考试报名费");
            memberOrder.setRemarks(tbExam.getName() + "考试报名费");
            memberOrderService.insertTbMemberOrder(memberOrder);

            //处理参与量
            threadPoolTaskExecutor.execute(() -> {
                TbCourse tbCourse = tbCourseMapper.selectTbCourseByCourseId(tbExamRegistration.getCourseId());
                if (StringUtils.isNotNull(tbCourse)){
                    tbCourse.setParticipateNum(tbCourse.getParticipateNum() + 1);
                    tbCourseMapper.updateTbCourse(tbCourse);
                }
            });
            //生成准考证号
            String examNumber =  getZkzh(tbExamRegistration);
            tbExamRegistration.setZkzh(examNumber);
            tbExamRegistrationMapper.updateTbExamRegistration(tbExamRegistration);
        }else{
            throw new ServiceException("新增失败");
        }
        return row;
    }

    /**
     * 修改考试报名
     *
     * @param tbExamRegistration 考试报名
     * @return 结果
     */
    @Override
    public int updateTbExamRegistration(TbExamRegistration tbExamRegistration)
    {
        tbExamRegistration.setUpdateTime(DateUtils.getNowDate());
        return tbExamRegistrationMapper.updateTbExamRegistration(tbExamRegistration);
    }

    /**
     * 批量删除考试报名
     *
     * @param examRegistrationIds 需要删除的考试报名主键
     * @return 结果
     */
    @Override
    public int deleteTbExamRegistrationByExamRegistrationIds(Long[] examRegistrationIds)
    {
        return tbExamRegistrationMapper.deleteTbExamRegistrationByExamRegistrationIds(examRegistrationIds);
    }

    /**
     * 删除考试报名信息
     *
     * @param examRegistrationId 考试报名主键
     * @return 结果
     */
    @Override
    public int deleteTbExamRegistrationByExamRegistrationId(Long examRegistrationId)
    {
        return tbExamRegistrationMapper.deleteTbExamRegistrationByExamRegistrationId(examRegistrationId);
    }

    /**
     * 证书发货
     * @param tbExamRegistration 参数
     * @return 结果
     */
    @Override
    public int certificateSend(TbExamRegistration tbExamRegistration){
        String sendManName = tbExamRegistration.getSendManName();
        String sendManMobile = tbExamRegistration.getSendManMobile();
        String sendManPrintAddr = tbExamRegistration.getSendManPrintAddr();

        TbExamRegistration examRegistration = tbExamRegistrationMapper.selectTbExamRegistrationByExamRegistrationId(tbExamRegistration.getExamRegistrationId());
        if (ObjectUtils.isEmpty(examRegistration)){
            throw new ServiceException("未查询到考试报名信息");
        }
        if (examRegistration.getCertificateStatus()!=1){
            throw new ServiceException("不是待发货状态，发货失败");
        }
        examRegistration.setCertificate(tbExamRegistration.getCertificate());
        examRegistration.setSendManName(sendManName);
        examRegistration.setSendManMobile(sendManMobile);
        examRegistration.setSendManPrintAddr(sendManPrintAddr);
        return tbExamRegistrationMapper.updateTbExamRegistration(examRegistration);
        // todo 后续需要对接快递，将以下代码取消注释，进行调试
//        try {
//            JSONObject sendResult = kd100Util.testBorderOfficial(
//                    CompanyConstant.EMS,
//                    sendManName,
//                    sendManMobile,
//                    sendManPrintAddr,
//                    tbExamRegistration.getName(),
//                    tbExamRegistration.getContactPhone(),
//                    tbExamRegistration.getProvinceName() + tbExamRegistration.getCityName() + tbExamRegistration.getAreaName() + tbExamRegistration.getAddress());
//
//            Boolean result = sendResult.getBoolean("result");
//
//            if (result){
//                JSONObject data = sendResult.getJSONObject("data");
//                String taskId = data.getString("taskId");
//                String orderId = data.getString("orderId");
//                String kuaidinum = data.getString("kuaidinum");
//                String pollToken = data.getString("pollToken");
//
//                tbExamRegistration.setShippingMark("ems");
//                tbExamRegistration.setShippingName("ems");
//                tbExamRegistration.setShippingCode(kuaidinum);
//                tbExamRegistration.setShippingTaskId(taskId);
//                tbExamRegistration.setShippingOrderId(orderId);
//                tbExamRegistration.setShippingPollToken(pollToken);
//                tbExamRegistration.setSendManName(sendManName);
//                tbExamRegistration.setSendManMobile(sendManMobile);
//                tbExamRegistration.setSendManPrintAddr(sendManPrintAddr);
//                tbExamRegistrationMapper.updateTbExamRegistration(examRegistration);
//
//                return 1;
//            }else {
//                String message = sendResult.getString("message");
//                throw new ServiceException(message);
//            }
//        } catch (Exception e) {
//            e.printStackTrace();
//            throw new ServiceException("发货提交异常");
//        }
    }

    /**
     * 考试报名
     *
     * @param examRegistrationDTO
     * @return ok
     */
    @Transactional
    @Override
    public AjaxResult examRegistration(ExamRegistrationDTO examRegistrationDTO) {
        Long courseId = examRegistrationDTO.getCourseId();
        if (courseId == null){
            throw new ServiceException("请选择课程");
        }
        // 根据课程ID 获取考试ID
        TbCourse course = tbCourseMapper.selectTbCourseByCourseId(examRegistrationDTO.getCourseId());
        if (ObjectUtils.isEmpty(course)){
            throw new ServiceException("未查询到课程信息");
        }

        TbExam tbExam = examService.selectTbExamByExamId(course.getExamId());
        if (ObjectUtils.isEmpty(tbExam)) {
            return AjaxResult.error("未查询到考试信息，请联系管理员！！！");
        }

        // 查询考试批次
        TbExamBatch tbExamBatch = tbExamBatchMapper.selectCurrentExamBatch(tbExam.getExamId());
        if (null == tbExamBatch){
            throw new ServiceException("无可报名批次");
        }

//        TbExamRegistration tbExamRegistration = tbExamRegistrationMapper.selectTbExamRegistrationByUserIdExamId(examRegistrationDTO.getMemberUserId(), tbExam.getExamId());
        TbExamRegistration registrationParam = new TbExamRegistration();
        registrationParam.setMemberUserId(examRegistrationDTO.getMemberUserId());
        registrationParam.setExamId(tbExam.getExamId());
        registrationParam.setExamBatchIndex(tbExamBatch.getBatchIndex().intValue());
        TbExamRegistration tbExamRegistration = tbExamRegistrationMapper.selectTbExamRegistrationByBatchIndex(registrationParam);
        if (ObjectUtils.isNotEmpty(tbExamRegistration)) {
            return AjaxResult.error("已报名，请勿重复提交");
        }else {
            TbExamRegistration registration = new TbExamRegistration();
            registration.setMemberUserId(examRegistrationDTO.getMemberUserId());
            registration.setExamId(tbExam.getExamId());
            registration.setExamBatchIndex(tbExamBatch.getBatchIndex().intValue());
            registration.setName(examRegistrationDTO.getName());
            registration.setSex(examRegistrationDTO.getSex());
            registration.setFormerName(examRegistrationDTO.getFormerName());
            registration.setNation(examRegistrationDTO.getNation());
            registration.setIdentityCard(examRegistrationDTO.getIdentityCard());
            registration.setBirthday(DateUtil.parse(examRegistrationDTO.getBirthday(), "yyyy-MM-dd").toString("yyyy-MM-dd"));
            registration.setSourceType(examRegistrationDTO.getSourceType());
            if (!CollectionUtils.isEmpty(examRegistrationDTO.getNativePlace())) {
                //获取区域信息
                registration.setNativePlace(String.join(",", examRegistrationDTO.getNativePlace()));
            }
            registration.setPoliticalStatus(examRegistrationDTO.getPoliticalStatus());
            registration.setEducation(examRegistrationDTO.getEducation());
            registration.setMajor(examRegistrationDTO.getMajor());
            registration.setGraduationSchool(examRegistrationDTO.getGraduationSchool());
            registration.setEntranceYear(examRegistrationDTO.getEntranceYear());
            registration.setContactInformation(examRegistrationDTO.getContactInformation());
            if (null != examRegistrationDTO.getProvinceId()) {
                registration.setProvinceId(examRegistrationDTO.getProvinceId());
                TbRegion region = tbRegionMapper.selectTbRegionById(registration.getProvinceId());
                registration.setProvinceName(null != region ? region.getName(): null);
            }
            if (null != examRegistrationDTO.getCityId()) {
                registration.setCityId(examRegistrationDTO.getCityId());
                TbRegion region = tbRegionMapper.selectTbRegionById(registration.getCityId());
                registration.setCityName(null != region ? region.getName(): null);
            }
            if (null != examRegistrationDTO.getAreaId()) {
                registration.setAreaId(examRegistrationDTO.getAreaId());
                TbRegion region = tbRegionMapper.selectTbRegionById(registration.getAreaId());
                registration.setAreaName(null != region ? region.getName(): null);
            }
            registration.setAddress(examRegistrationDTO.getAddress());
            registration.setZipCode(examRegistrationDTO.getZipCode());
            registration.setContactPhone(examRegistrationDTO.getContactPhone());
            registration.setEmail(examRegistrationDTO.getEmail());

            registration.setIdPhoto(examRegistrationDTO.getIdPhoto());
            registration.setIdentityCardBadge(examRegistrationDTO.getIdentityCardBadge());
            registration.setIdentityCardPortrait(examRegistrationDTO.getIdentityCardPortrait());
            registration.setGraduationCertificate(examRegistrationDTO.getGraduationCertificate());

            registration.setAgencyName(examRegistrationDTO.getAgencyName());
            registration.setCareerName(examRegistrationDTO.getCareerName());
            registration.setExamLevel(examRegistrationDTO.getExamLevel());
            registration.setRegistrationBatch(tbExamBatch.getExamBatch());
            registration.setStudyCenter(examRegistrationDTO.getStudyCenter());
            registration.setStudyCenterId(examRegistrationDTO.getStudyCenterId());
            registration.setAgencyCode(examRegistrationDTO.getAgencyCode());

            registration.setIsInspect(examRegistrationDTO.getIsInspect());
            registration.setSignPhoto(examRegistrationDTO.getSignPhoto());

            registration.setCreateTime(DateUtils.getNowDate());
            registration.setExamineStatus(0);

            registration.setIsPay(0);
            registration.setPayType(0);
            registration.setPayPrice(tbExam.getPrice());

            registration.setAgencyId(examRegistrationDTO.getAgencyId());
            registration.setCourseId(examRegistrationDTO.getCourseId());

            tbExamRegistrationMapper.insertTbExamRegistration(registration);

            TbMemberOrder memberOrder = new TbMemberOrder();
            memberOrder.setOrderNo(IdUtil.getSnowflakeNextIdStr());
            memberOrder.setMemberUserId(examRegistrationDTO.getMemberUserId());
            memberOrder.setDataId(registration.getExamRegistrationId());
            memberOrder.setPayPrice(tbExam.getPrice());
            memberOrder.setOrderPrice(tbExam.getPrice());
            memberOrder.setDeductionScore(new BigDecimal(0));
            memberOrder.setOrderType(2);
            memberOrder.setPayType(0);
            memberOrder.setPayStatus(0);
            memberOrder.setOrderName(tbExam.getName() + "考试报名费");
            memberOrder.setRemarks(tbExam.getName() + "考试报名费");
            memberOrderService.insertTbMemberOrder(memberOrder);

            TbMemberMajor tbMemberMajor = tbMemberMajorMapper.selectTbMemberMajorByMemberAndMajorId(examRegistrationDTO.getMemberUserId(), null, examRegistrationDTO.getCourseId());
            if (tbMemberMajor != null) {
                tbMemberMajor.setUpdateTime(DateUtils.getNowDate());
                tbMemberMajorMapper.updateTbMemberMajor(tbMemberMajor);
            } else {
                TbMemberMajor memberMajor = new TbMemberMajor();
                memberMajor.setMemberUserId(examRegistrationDTO.getMemberUserId());
                memberMajor.setResId(examRegistrationDTO.getCourseId());
                memberMajor.setCreateTime(DateUtils.getNowDate());
                memberMajor.setType(1);
                tbMemberMajorMapper.insertTbMemberMajor(memberMajor);
            }

            //处理参与量
            threadPoolTaskExecutor.execute(() -> {
                TbCourse tbCourse = tbCourseMapper.selectTbCourseByCourseId(courseId);
                if (StringUtils.isNotNull(tbCourse)){
                    tbCourse.setParticipateNum(tbCourse.getParticipateNum() + 1);
                    tbCourseMapper.updateTbCourse(tbCourse);
                }
            });
            return AjaxResult.success();
        }
    }

    /**
     * 查询用户考试报名
     *
     * @param memberUserId 用户ID
     * @param examId 考试ID
     * @return 考试报名
     */
    @Override
    public TbExamRegistration selectTbExamRegistrationByUserIdExamId(Long memberUserId, Long examId) {
        return tbExamRegistrationMapper.selectTbExamRegistrationByUserIdExamId(memberUserId, examId);
    }

    /**
     * 我的考试列表
     *
     * @param params 参数
     * @return 结果
     */
    @Override
    public List<Map<String, Object>> getMemberExamList(Map<String, Object> params) {
        return tbExamRegistrationMapper.getMemberExamList(params);
    }

    /**
     * 我的考试详情
     *
     * @param params 参数
     * @return 结果
     */
    @Override
    public Map<String, Object> getMemberExamInfo(Map<String, Object> params) {
        Map<String, Object> memberExamInfo = tbExamRegistrationMapper.getMemberExamInfo(params);
        if (memberExamInfo != null) {
            HashMap<String, Object> map = new HashMap<>();
            map.put("memberUserId", memberExamInfo.get("memberUserId").toString());
            map.put("examId", memberExamInfo.get("examId").toString());
            memberExamInfo.put("subjectFormalPhotographList", examFileService.getSubjectFormalPhotographList(map));
        }
        return memberExamInfo;
    }

    /**
     * 查询考试报名详情
     *
     * @param params 参数
     * @return 结果
     */
    @Override
    public Map<String, Object> getExamRegistrationInfo(Map<String, Object> params) {
        Map<String, Object> examRegistrationInfo = tbExamRegistrationMapper.getExamRegistrationInfo(params);
        if (ObjectUtils.isNotEmpty(examRegistrationInfo)) {
            Map<String, Object> memberScore = tbMemberScoreMapper.getMemberScore(params);

            // 可用积分
            BigDecimal canScore = new BigDecimal(memberScore.get("canScore").toString()).setScale(2, RoundingMode.HALF_UP);
            // 考试报名金额
            BigDecimal examPrice = new BigDecimal(examRegistrationInfo.get("examPrice").toString()).setScale(2, RoundingMode.HALF_UP);
            TbConfig aboutIntegral = tbConfigMapper.selectTbConfigByIdentifying("aboutIntegral");
            // 一积分抵扣X元
            BigDecimal deductionProportion = aboutIntegral.getConfigDecimal2();
            // 积分抵扣百分比
            String rateString = aboutIntegral.getConfigString2();
            //默认积分抵扣比例为1
            BigDecimal rate = new BigDecimal(1);
            if (StringUtils.isNotEmpty(rateString)) {
                try {
                    rate = new BigDecimal(rateString);
                    // 检查 rate 是否在有效范围内，例如 0 到 1 之间
                    if (rate.compareTo(BigDecimal.ZERO) < 0 || rate.compareTo(BigDecimal.ONE) > 0) {
                        // 如果不在有效范围内，设置为默认值
                        rate = new BigDecimal(1);
                        System.err.println("Rate out of range: " + rateString); // 记录错误信息
                    }
                } catch (NumberFormatException e) {
                    // 捕获无效数字格式，记录日志、返回默认值
                    rate = new BigDecimal(1); // 或者可以设置其他默认值，具体根据业务需求
                    System.err.println("Invalid rate format: " + rateString); // 记录错误信息
                }
            }

            // 计算最大抵扣金额：examPrice * rate
            BigDecimal maxDiscountAmount = examPrice.multiply(rate).setScale(2, RoundingMode.HALF_UP);
            // 最大抵扣积分
            BigDecimal maxDiscountScore = maxDiscountAmount.divide(deductionProportion, 2, RoundingMode.HALF_UP);;
            // 抵扣积分
            BigDecimal deductionScore = new BigDecimal(memberScore.get("canScore").toString()).setScale(2, RoundingMode.HALF_UP);
            // 实付
            BigDecimal payment = new BigDecimal(examRegistrationInfo.get("examPrice").toString()).setScale(2, RoundingMode.HALF_UP);


            // 抵扣金额 = 可用积分 * 一积分抵扣X元
            BigDecimal discountPrice = canScore.multiply(deductionProportion).setScale(2, RoundingMode.HALF_UP);


            // 如果计算出来的抵扣金额大于最大抵扣金额，则限制为最大抵扣金额
            if (discountPrice.compareTo(maxDiscountAmount) > 0) {
                discountPrice = maxDiscountAmount;
                // 根据最大抵扣金额重新计算抵扣的积分数
                deductionScore = discountPrice.divide(deductionProportion, 2, RoundingMode.HALF_UP);
            }

            //如果抵扣金额大于考试价格，则考试价格为0
            if(discountPrice.compareTo(examPrice) >= 0) {
                discountPrice = examPrice;
                deductionScore = examPrice.divide(deductionProportion);
                payment = new BigDecimal(0);
            }

            //如果考试价格大于抵扣价格，则考试价格减去抵扣价格
            if(examPrice.compareTo(discountPrice) > 0) {
                payment = payment.subtract(discountPrice);
            }


            // 可用积分
            examRegistrationInfo.put("canScore", canScore);
            // 优惠金额（元）
            examRegistrationInfo.put("discountPrice", discountPrice);
            // 抵扣积分
            examRegistrationInfo.put("deductionScore", deductionScore);
            // 实付
            examRegistrationInfo.put("payment", payment);
            //最多可抵扣金额
            examRegistrationInfo.put("maxDiscountAmount", maxDiscountAmount);
            //最多可抵扣积分
            examRegistrationInfo.put("maxDiscountScore", maxDiscountScore);

            TbMemberOrder memberOrder = new TbMemberOrder();
            memberOrder.setOrderNo(MapUtils.getString(examRegistrationInfo, "orderNo"));
            memberOrder.setPayPrice(payment);
            memberOrder.setDiscountPrice(discountPrice);
            memberOrder.setDeductionScore(deductionScore);
            memberOrder.setUpdateTime(DateUtils.getNowDate());
            memberOrderService.updateTbMemberOrderByOrderNo(memberOrder);
        }
        return examRegistrationInfo;
    }


    /**
     * 学习计划-我的课件列表
     *
     * @param params 参数
     * @return 结果
     */
    @Override
    public List<Map<String, Object>> getMemberCoursewareList(Map<String, Object> params) {
        return tbExamRegistrationMapper.getMemberCoursewareList(params);
    }

    /**
     * 我的报名表、准考证、证书
     *
     * @param params 参数
     * @return 结果
     */
    @Override
    public Map<String, Object> getMemberCertificateMore(Map<String, Object> params) {
        return tbExamRegistrationMapper.getMemberCertificateMore(params);
    }

    // /**
    //  * 查看快递信息
    //  *
    //  * @param params 参数
    //  * @return 结果
    //  */
    // @Override
    // public Map<String, Object> getExpressInfo(Map<String, Object> params) {
    //     Map<String, Object> certificateMore = tbExamRegistrationMapper.getMemberCertificateMore(params);
    //     if (certificateMore != null) {
    //         String shippingLogo = "";
    //         List<Map<String,Object>> expressList = new ArrayList<>();
    //         int certificateStatus = Integer.parseInt(certificateMore.get("certificateStatus").toString());
    //         if (certificateStatus == 2) {
    //             // 已发货
    //
    //             // 查询快递
    //             TbExpressKdCode expressKdCode = tbExpressKdCodeService.selectTbExpressKdCodeByCode(certificateMore.get("shippingMark").toString());
    //             shippingLogo = expressKdCode.getLogo();
    //
    //             String shippingMark = certificateMore.get("shippingMark").toString();
    //             String shippingCode = certificateMore.get("shippingCode").toString();
    //             expressList = tbExpressKdCodeService.checkExpressInfoMessage(shippingMark, shippingCode);
    //         }
    //
    //         certificateMore.put("shippingLogo", shippingLogo);
    //         certificateMore.put("expressList", expressList);
    //
    //     }
    //
    //     return certificateMore;
    // }

    /**
     * 填写证书收货信息
     *
     * @param postAddressDTO
     * @return ok
     */
    @Transactional
    @Override
    public AjaxResult submitCertificateGoodsInfo(PostAddressDTO postAddressDTO) {
        TbExamRegistration examRegistration = tbExamRegistrationMapper.selectTbExamRegistrationByExamRegistrationId(postAddressDTO.getExamRegistrationId());
        if (examRegistration == null) {
            return AjaxResult.error("报名信息有误");
        }
        TbPostAddress postAddress = tbPostAddressService.selectTbPostAddressByMemberUserIdDataId(postAddressDTO.getMemberUserId(), postAddressDTO.getExamRegistrationId(), 1);
        if (postAddress != null) {
            return AjaxResult.error("您已填写，请勿重复提交");
        }
        //传id了就跳过，没传id传名字了才查
        if (ObjectUtils.isEmpty(postAddressDTO.getProvinceId())&&StringUtils.isNotBlank(postAddressDTO.getProvinceName())){
            Long provinceId = tbRegionMapper.selectIdByName1(postAddressDTO.getProvinceName());
            if (provinceId==null){
                return AjaxResult.error("无法找到省名称");
            }else {
                postAddressDTO.setProvinceId(provinceId);
            }
        }
        if (ObjectUtils.isEmpty(postAddressDTO.getCityId())&&StringUtils.isNotBlank(postAddressDTO.getCityName())){
            Long cityId = tbRegionMapper.selectIdByName2(postAddressDTO.getCityName());
            if (cityId==null){
                return AjaxResult.error("无法找到市名称");
            }else {
                postAddressDTO.setCityId(cityId);
            }
        }
        if (ObjectUtils.isEmpty(postAddressDTO.getAreaId())&&StringUtils.isNotBlank(postAddressDTO.getAreaName())){
            Long areaId = tbRegionMapper.selectIdByName3(postAddressDTO.getAreaName(),postAddressDTO.getCityId());
            if (areaId==null){
                return AjaxResult.error("无法找到区名称");
            }else {
                postAddressDTO.setAreaId(areaId);
            }
        }
        TbPostAddress address = new TbPostAddress();
        address.setMemberUserId(postAddressDTO.getMemberUserId());
        address.setName(postAddressDTO.getName());
        address.setPhone(postAddressDTO.getPhone());
        address.setProvinceId(postAddressDTO.getProvinceId());
        address.setCityId(postAddressDTO.getCityId());
        address.setAreaId(postAddressDTO.getAreaId());
        address.setProvinceName(postAddressDTO.getProvinceName());
        address.setCityName(postAddressDTO.getCityName());
        address.setAreaName(postAddressDTO.getAreaName());
        address.setAddress(postAddressDTO.getAddress());
        address.setDataId(postAddressDTO.getExamRegistrationId());
        address.setType(1);
        tbPostAddressService.insertTbPostAddress(address);

        examRegistration.setWriteAt(DateUtils.getTime());
        examRegistration.setCertificateStatus(1);
        tbExamRegistrationMapper.updateTbExamRegistration(examRegistration);

        return AjaxResult.success();
    }

    /**
     * 报名考试即将开始弹窗列表
     *
     * @param params 参数
     * @return 结果
     */
    @Override
    public Map<String, Object> getStartNowPopupList(Map<String, Object> params) {
        return tbExamRegistrationMapper.getStartNowPopupList(params);
    }

    /**
     * 获取考试报名表
     * @param type 1-准考证，4-证书，10-报名表，11-成绩单
     * @param memberUserId 用户ID
     * @param examRegistrationId 考试报名ID
     * @return 结果
     */
    @Override
    public JSONObject getReportFormView(Long type, Long memberUserId, Long examRegistrationId){
        TbExamRegistration tbExamRegistration = tbExamRegistrationMapper.getByExamRegistrationId(memberUserId, examRegistrationId);
        if (ObjectUtils.isEmpty(tbExamRegistration)){
            throw new ServiceException("未查询到考试报名信息");
        }

        String fileUrl = "";
        if (1 == type){// 准考证
            fileUrl = this.downloadAdmissionTicket(tbExamRegistration);
        }
        if (4 == type){// 证书
            fileUrl = tbExamRegistration.getCertificate();
        }
        if (10 == type){// 报名表
            fileUrl = this.downloadReportForm(tbExamRegistration);
        }
        if (11 == type){// 成绩单
            try {
                fileUrl = this.downloadTranscript(tbExamRegistration);
            } catch (Exception e) {
                e.printStackTrace();
                throw new ServiceException("成绩单下载失败");
            }
        }

        JSONObject result = new JSONObject();
        result.put("fileUrl", fileUrl);
        return result;
    }




    /**
     * 渲染成绩单
     * @param tbExamRegistration 参数
     * @return 结果
     */
    public String downloadTranscript(TbExamRegistration tbExamRegistration){
        TbExamSimulateInfo tbExamSimulateInfo = tbExamSimulateInfoMapper.getByMemberUserId(tbExamRegistration.getMemberUserId(), tbExamRegistration.getExamId());
        if (ObjectUtils.isEmpty(tbExamRegistration)){
            throw new ServiceException("未查询到成绩单信息，请先完成考试");
        }

        Map<String, String> paramMap = new HashMap<>();
        if (StringUtils.isNotBlank(tbExamRegistration.getName())){
            paramMap.put("$姓名$", tbExamRegistration.getName());
        }else {
            paramMap.put("$姓名$", "*");
        }
        if (StringUtils.isNotBlank(tbExamRegistration.getAgencyName())){
            paramMap.put("$主考机构$", tbExamRegistration.getAgencyName());
        }else {
            paramMap.put("$主考机构$", "*");
        }
        if (StringUtils.isNotBlank(tbExamRegistration.getMajor())){
            paramMap.put("$专业$", tbExamRegistration.getMajor());
        }else {
            paramMap.put("$专业$", "*");
        }
        if (StringUtils.isNotBlank(tbExamRegistration.getExamLevel())){
            paramMap.put("$等级$", tbExamRegistration.getExamLevel());
        }else {
            paramMap.put("$等级$", "*");
        }
        if (null != tbExamSimulateInfo.getCompleteScore()){
            paramMap.put("$分数$", tbExamSimulateInfo.getCompleteScore().toString());
        }else {
            paramMap.put("$分数$", "*");
        }
        if (null != tbExamSimulateInfo.getPassStatus()){
            paramMap.put("$合格$", tbExamSimulateInfo.getPassStatus() == 1 ? "'合格'" : "不合格");
        }else {
            paramMap.put("$合格$", "*");
        }
        if (StringUtils.isNotBlank(tbExamRegistration.getRegistrationBatch())){
            paramMap.put("$批次$", tbExamRegistration.getRegistrationBatch());
        }else {
            paramMap.put("$批次$", "*");
        }
        String completeTime = tbExamSimulateInfo.getCompleteTime();
        if (StringUtils.isNotBlank(completeTime)){
            String[] completeTimeSplit = completeTime.split(" ");
            String[] dateSplit = completeTimeSplit[0].split("-");
            paramMap.put("$考试年$", dateSplit[0]);
            paramMap.put("$考试月$", dateSplit[1]);
            paramMap.put("$考试日$", dateSplit[2]);
        }else {
            paramMap.put("$考试年$", "*");
            paramMap.put("$考试月$", "*");
            paramMap.put("$考试日$", "*");
        }

        Date nowDate = DateUtils.getNowDate();
        paramMap.put("$年$", DateUtils.parseDateToStr("yyyy", nowDate));
        paramMap.put("$月$", DateUtils.parseDateToStr("MM", nowDate));
        paramMap.put("$日$", DateUtils.parseDateToStr("dd", nowDate));
        String transcriptCode = IdUtil.getSnowflakeNextIdStr();
        paramMap.put("$成绩单编号$", transcriptCode);

        tbExamSimulateInfo.setTranscriptCode(transcriptCode);
        tbExamSimulateInfoMapper.updateTbExamSimulateInfo(tbExamSimulateInfo);


        String fileName = tbExamRegistration.getName()+"_成绩单_"+ MD5.create().digestHex(tbExamRegistration.getMemberUserId()+"_"+tbExamRegistration.getExamRegistrationId()) +".pdf";
        String saveUrl = AsposeUtil.SAVE_PATH+fileName;
        try {
            AsposeUtil.replace4Doc(
                    ResourceReader.class.getClassLoader().getResourceAsStream(AsposeUtil.TRANSCRIPT_PATH),
                    saveUrl,
                    paramMap,
                    "0",
                    false);
        }catch (Exception e){
            throw new ServiceException("文件解析异常");
        }
        String fileUrl = "";
        try {
            FileInputStream fileInputStream = new FileInputStream(saveUrl);
            fileUrl = new ImgUpload().uploadStream(fileInputStream, fileName);
        } catch (IOException e) {
            throw new ServiceException("文件保存异常");
        }

        return fileUrl;
    }

    /**
     * 渲染准考证
     * @param tbExamRegistration 参数
     * @return 结果
     */
    public String downloadAdmissionTicket(TbExamRegistration tbExamRegistration){
        TbExam tbExam = tbExamMapper.selectTbExamByExamId(tbExamRegistration.getExamId());
        if (ObjectUtils.isEmpty(tbExam)){
            throw new ServiceException("未查询到考试信息");
        }
        TbExamBatch byExamIdBatchIndex = tbExamBatchMapper.getByExamIdBatchIndex(tbExam.getExamId(), tbExamRegistration.getExamBatchIndex());
        //TbMemberOrder tbMemberOrder = tbMemberOrderMapper.selectOrderByDataId(tbExamRegistration.getExamRegistrationId());

        String examStartTime = DateUtil.format(byExamIdBatchIndex.getExamStartTime(), "yyyy-MM-dd HH:mm:ss");
        String examEndTime =  DateUtil.format(byExamIdBatchIndex.getExamEndTime(), "yyyy-MM-dd HH:mm:ss");

        Map<String, String> paramMap = new HashMap<>();
        if (StringUtils.isNotBlank(tbExamRegistration.getName())){
            paramMap.put("$姓名$", tbExamRegistration.getName());
        }else {
            paramMap.put("$姓名$", "*");
        }
        paramMap.put("$性别$", tbExamRegistration.getSex() == null ? "*" : tbExamRegistration.getSex() == 0 ? "男" : tbExamRegistration.getSex() == 1 ? "女" : "未知");
        if (StringUtils.isNotBlank(tbExamRegistration.getZkzh())){
            paramMap.put("$准考证号$", tbExamRegistration.getZkzh());
        }else {
            paramMap.put("$准考证号$", "*");
        }
        if (StringUtils.isNotBlank(tbExamRegistration.getIdentityCard())){
            paramMap.put("$居民身份证$", tbExamRegistration.getIdentityCard());
        }else {
            paramMap.put("$居民身份证$", "*");
        }
        if (StringUtils.isNotBlank(tbExamRegistration.getAgencyName())){
            paramMap.put("$评价机构$", tbExamRegistration.getAgencyName());
        }else {
            paramMap.put("$评价机构$", "*");
        }
        if (StringUtils.isNotBlank(tbExamRegistration.getCareerName())){
            paramMap.put("$职业名称$", tbExamRegistration.getCareerName());
        }else {
            paramMap.put("$职业名称$", "*");
        }
        if (StringUtils.isNotBlank(tbExamRegistration.getMajor())){
            paramMap.put("$工种名称$", tbExamRegistration.getMajor());
        }else {
            paramMap.put("$工种名称$", "*");
        }
        if (StringUtils.isNotBlank(tbExam.getName())){
            paramMap.put("$考试科目$", tbExam.getName());
        }else {
            paramMap.put("$考试科目$", "*");
        }
        if (StringUtils.isNotBlank(tbExamRegistration.getExamLevel())){
            paramMap.put("$报考等级$", tbExamRegistration.getExamLevel());
        }else {
            paramMap.put("$报考等级$", "*");
        }
        if (StringUtils.isNotBlank(tbExamRegistration.getEducation())){
            paramMap.put("$文化程度$", tbExamRegistration.getEducation());
        }else {
            paramMap.put("$文化程度$", "*");
        }
        if (StringUtils.isNotBlank(tbExamRegistration.getIdPhoto())){
            paramMap.put("$蓝底证件照$", "$pic:513:231:"+tbExamRegistration.getIdPhoto());
        }else {
            paramMap.put("$蓝底证件照$", "*");
        }
        if (StringUtils.isNotBlank(tbExamRegistration.getRegistrationBatch())){
            paramMap.put("$批次$", tbExamRegistration.getRegistrationBatch());
        }else {
            paramMap.put("$批次$", "*");
        }
        if (StringUtils.isNotBlank(examStartTime) ){
            paramMap.put("$理论考试开始时间$", examStartTime);
        }else {
            paramMap.put("$理论考试开始时间$", "*");
        }
        if ( StringUtils.isNotBlank(examEndTime)){
            paramMap.put("$理论考试结束时间$", examEndTime);
        }else {
            paramMap.put("$理论考试结束时间$", "*");
        }

        String fileName = tbExamRegistration.getName()+"_学信准考证_"+ MD5.create().digestHex(tbExamRegistration.getMemberUserId()+"_"+tbExamRegistration.getExamRegistrationId()) +".pdf";
        String saveUrl = AsposeUtil.SAVE_PATH+fileName;
        try {
            AsposeUtil.replace4Doc(
                    ResourceReader.class.getClassLoader().getResourceAsStream(AsposeUtil.ADMISSION_TICKET_PATH),
                    saveUrl,
                    paramMap,
                    "0",
                    false);
        }catch (Exception e){
            throw new ServiceException("文件解析异常");
        }
        String fileUrl = "";
        try {
            FileInputStream fileInputStream = new FileInputStream(saveUrl);
            fileUrl = new ImgUpload().uploadStream(fileInputStream, fileName);
        } catch (IOException e) {
            throw new ServiceException("文件保存异常");
        }

        return fileUrl;
    }

    /**
     * 渲染报名表
     * @param tbExamRegistration 参数
     * @return 结果
     */
    public String downloadReportForm(TbExamRegistration tbExamRegistration){

        StringBuilder studyCenterTeacherName = new StringBuilder();
        Long studyCenterId = tbExamRegistration.getStudyCenterId();
        if (null != studyCenterId){
            List<TbStudyCenterTeacher> studyCenterTeacherList = tbStudyCenterTeacherMapper.getByStudyCenterId(studyCenterId);
            if (!studyCenterTeacherList.isEmpty()){
                if (studyCenterTeacherList.size() > 3){
                    studyCenterTeacherList.subList(0, 3).forEach(item ->{
                        String teacherPhone = item.getTeacherPhone();
                        String teacherName = item.getTeacherName();
                        if (StringUtils.isNotBlank(teacherName) && StringUtils.isNotBlank(teacherPhone)){

                        }
                        String str = teacherName+" "+teacherPhone+"  ";
                        studyCenterTeacherName.append(str);
                    });
                }
            }
        }
        if (ObjectUtils.isEmpty(tbExamRegistration)){
            throw new ServiceException("未查询到考试报名信息");
        }

        Map<String, String> paramMap = new HashMap<>();
        if (StringUtils.isNotBlank(tbExamRegistration.getName())){
            paramMap.put("$姓名$", tbExamRegistration.getName());
        }else {
            paramMap.put("$姓名$", "*");
        }
        paramMap.put("$性别$", tbExamRegistration.getSex() == null ? "*" : tbExamRegistration.getSex() == 0 ? "未知" : tbExamRegistration.getSex() == 1 ? "男" : "女");
        if (StringUtils.isNotBlank(tbExamRegistration.getFormerName())){
            paramMap.put("$曾用名$", tbExamRegistration.getFormerName());
        }else {
            paramMap.put("$曾用名$", "*");
        }
        if (StringUtils.isNotBlank(tbExamRegistration.getNation())){
            paramMap.put("$民族$", tbExamRegistration.getNation());
        }else {
            paramMap.put("$民族$", "*");
        }
        if (StringUtils.isNotBlank(tbExamRegistration.getIdentityCard())){
            paramMap.put("$身份证号$", tbExamRegistration.getIdentityCard());
        }else {
            paramMap.put("$身份证号$", "*");
        }
        String birthYear= "";
        String birthMonth= "";
        String birthDay= "";
        String birthday = tbExamRegistration.getBirthday();
        if (StringUtils.isNotBlank(birthday)){
            String[] split = birthday.split("-");
            birthYear = split[0];
            birthMonth = split[1];
            birthDay = split[2];
        }
        if (StringUtils.isNotBlank(birthYear)){
            paramMap.put("$出生年$", birthYear);
        }else {
            paramMap.put("$出生年$", "*");
        }
        if (StringUtils.isNotBlank(birthMonth)){
            paramMap.put("$出生月$", birthMonth);
        }else {
            paramMap.put("$出生月$", "*");
        }
        if (StringUtils.isNotBlank(birthDay)){
            paramMap.put("$出生日$", birthDay);
        }else {
            paramMap.put("$出生日$", "*");
        }
        if (StringUtils.isNotBlank(tbExamRegistration.getSourceType())){
            paramMap.put("$生源类型$", tbExamRegistration.getSourceType());
        }else {
            paramMap.put("$生源类型$", "*");
        }
        if (StringUtils.isNotBlank(tbExamRegistration.getNativePlace())){
            paramMap.put("$籍贯$", tbExamRegistration.getNativePlace());
        }else {
            paramMap.put("$籍贯$", "*");
        }
        if (StringUtils.isNotBlank(tbExamRegistration.getPoliticalStatus())){
            paramMap.put("$政治面貌$", tbExamRegistration.getPoliticalStatus());
        }else {
            paramMap.put("$政治面貌$", "*");
        }
        if (StringUtils.isNotBlank(tbExamRegistration.getIdPhoto())){
            paramMap.put("$蓝底证件照$", "$pic:413:531:"+tbExamRegistration.getIdPhoto());
        }else {
            paramMap.put("$蓝底证件照$", "*");
        }
        if (StringUtils.isNotBlank(tbExamRegistration.getSignPhoto())){
            paramMap.put("$签名$", "$pic:113:52:"+tbExamRegistration.getSignPhoto());
        }else {
            paramMap.put("$签名$", "*");
        }
        if (StringUtils.isNotBlank(tbExamRegistration.getEducation())){
            paramMap.put("$学历$", tbExamRegistration.getEducation());
        }else {
            paramMap.put("$学历$", "*");
        }
        if (StringUtils.isNotBlank(tbExamRegistration.getMajor())){
            paramMap.put("$专业$", tbExamRegistration.getMajor());
        }else {
            paramMap.put("$专业$", "*");
        }
        if (StringUtils.isNotBlank(tbExamRegistration.getGraduationSchool())){
            paramMap.put("$所在学校$", tbExamRegistration.getGraduationSchool());
        }else {
            paramMap.put("$所在学校$", "*");
        }
        if (StringUtils.isNotBlank(tbExamRegistration.getEntranceYear())){
            paramMap.put("$入学年份$", tbExamRegistration.getEntranceYear());
        }else {
            paramMap.put("$入学年份$", "*");
        }
        if (StringUtils.isNotBlank(tbExamRegistration.getContactInformation())){
            paramMap.put("$联系方式$", tbExamRegistration.getContactInformation());
        }else {
            paramMap.put("$联系方式$", "*");
        }
        if (StringUtils.isNotBlank(tbExamRegistration.getAddress())){
            paramMap.put("$通信地址$", tbExamRegistration.getAddress());
        }else {
            paramMap.put("$通信地址$", "*");
        }
        if (StringUtils.isNotBlank(tbExamRegistration.getZipCode())){
            paramMap.put("$邮编$", tbExamRegistration.getZipCode());
        }else {
            paramMap.put("$邮编$", "*");
        }
        if (StringUtils.isNotBlank(tbExamRegistration.getContactPhone())){
            paramMap.put("$联系电话$", tbExamRegistration.getContactPhone());
        }else {
            paramMap.put("$联系电话$", "*");
        }
        if(StringUtils.isNotBlank(tbExamRegistration.getEmail())){
            paramMap.put("$电子邮箱$", tbExamRegistration.getEmail());
        }else {
            paramMap.put("$电子邮箱$", "*");
        }
        if(StringUtils.isNotBlank(tbExamRegistration.getAgencyName())){
            paramMap.put("$机构名称$", tbExamRegistration.getAgencyName());
        }else {
            paramMap.put("$机构名称$", "*");
        }
        if(StringUtils.isNotBlank(tbExamRegistration.getCareerName())){
            paramMap.put("$职业名称$", tbExamRegistration.getCareerName());
        }else {
            paramMap.put("$职业名称$", "*");
        }
        if(StringUtils.isNotBlank(tbExamRegistration.getRegistrationBatch())){
            paramMap.put("$报名批次$", tbExamRegistration.getRegistrationBatch());
        }else {
            paramMap.put("$报名批次$", "*");
        }
        if(StringUtils.isNotBlank(tbExamRegistration.getStudyCenter())){
            paramMap.put("$学习中心$", tbExamRegistration.getStudyCenter());
        }else {
            paramMap.put("$学习中心$", "*");
        }
        if(StringUtils.isNotBlank(tbExamRegistration.getAgencyCode())){
            paramMap.put("$机构代码$", tbExamRegistration.getAgencyCode());
        }else {
            paramMap.put("$机构代码$", "*");
        }

        Date createTime = tbExamRegistration.getCreateTime();
        if (null != createTime){
            paramMap.put("$年$", DateUtils.parseDateToStr("yyyy", createTime));
            paramMap.put("$月$", DateUtils.parseDateToStr("MM", createTime));
            paramMap.put("$日$", DateUtils.parseDateToStr("dd", createTime));
        }else {
            paramMap.put("$年$", "*");
            paramMap.put("$月$", "*");
            paramMap.put("$日$", "*");
        }
        if (StringUtils.isNotBlank(studyCenterTeacherName)){
            paramMap.put("$教师$", studyCenterTeacherName.toString());
        }else {
            paramMap.put("$教师$", "*");
        }
        if (StringUtils.isNotBlank(tbExamRegistration.getIdentityCardPortrait())){
            paramMap.put("$身份证正面$", "$pic:583.2:365.4:"+tbExamRegistration.getIdentityCardPortrait());
        }else {
            paramMap.put("$身份证正面$", "*");
        }
        if (StringUtils.isNotBlank(tbExamRegistration.getIdentityCardBadge())){
            paramMap.put("$身份证反面$", "$pic:583.2:365.4:"+tbExamRegistration.getIdentityCardBadge());
        }else {
            paramMap.put("$身份证反面$", "*");
        }

        String fileName = tbExamRegistration.getName()+"_报名表_"+ MD5.create().digestHex(tbExamRegistration.getMemberUserId()+"_"+tbExamRegistration.getExamRegistrationId())+ System.currentTimeMillis() +".pdf";
        String saveUrl = AsposeUtil.SAVE_PATH+fileName;
        try {
            AsposeUtil.replace4Doc(
                    ResourceReader.class.getClassLoader().getResourceAsStream(AsposeUtil.REPORT_FORM_PATH),
                    saveUrl,
                    paramMap,
                    "0",
                    false);
        }catch (Exception e){
            throw new ServiceException("文件解析异常");
        }
        String fileUrl = "";
        try {
            FileInputStream fileInputStream = new FileInputStream(saveUrl);
            fileUrl = new ImgUpload().uploadStream(fileInputStream, fileName);
        } catch (IOException e) {
            throw new ServiceException("文件保存异常");
        }

        return fileUrl;
    }

    /**
     * 导入考试报名
     * @param list 文件
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String importData(@Valid List<TbExamRegistrationVO> list) throws Exception {
        if (ObjectUtils.isEmpty(list)){
            throw new ServiceException("导入信息不能为空");
        }
        //导入数据不为空校验表中是否有重复数据(进行去重)
         List<TbExamRegistrationVO> collect = list.stream().distinct().collect(Collectors.toList());
        // 使用 Map 存储手机号和失败原因
        Map<String, String> erreList = new HashMap<>();
        int successRow = 0;
        for (TbExamRegistrationVO item : collect) {
            //首先校验数据
            String birthday = item.getBirthday();
            String normalized = birthday.replace("/", "-");
            String formatted = null;
            LocalDate date;
            try {
                // 先用宽松格式解析（允许不补0）
                date = LocalDate.parse(normalized, DateTimeFormatter.ofPattern("yyyy-M-d"));

                // 再用严格格式格式化（自动补0）
                formatted = date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            } catch (Exception e1) {
                try {
                    // 尝试解析 Java Date.toString() 格式
                    SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy", Locale.ENGLISH);
                    Date parsedDate = sdf.parse(normalized);
                    SimpleDateFormat targetFormat = new SimpleDateFormat("yyyy-MM-dd");
                    formatted = targetFormat.format(parsedDate);
                } catch (Exception e2) {
                    erreList.put(item.getContactInformation(), "生日格式有误，应为：1999-09-09 或 Fri Jul 07 00:00:00 CST 2000");
                    continue;
                }
            }
            item.setBirthday(formatted); // 回写为标准格式
            //校验手机号必须11位纯数字
            if(item.getContactInformation().length() != 11||!item.getContactInformation().matches("^[0-9]*$")){
                erreList.put(item.getContactInformation(), "手机号格式有误，应为11位纯数字");
                continue;
            }
            //校验身份证号必须18位
            if(item.getIdentityCard().length() != 18){
                erreList.put(item.getContactInformation(), "身份证号格式有误，应为18位");
            }
            TbExamRegistration tbExamRegistration = new TbExamRegistration();
            BeanUtils.copyProperties(item, tbExamRegistration);
            //毕业证书有最多三张图，需要合并url
            List<String> images = new ArrayList<>();
            if (StringUtils.isNotBlank(item.getGraduationCertificate())) {
                images.add(item.getGraduationCertificate());
            }
            if (StringUtils.isNotBlank(item.getGraduationCertificate2())) {
                images.add(item.getGraduationCertificate2());
            }
            if (StringUtils.isNotBlank(item.getGraduationCertificate3())) {
                images.add(item.getGraduationCertificate3());
            }
            tbExamRegistration.setGraduationCertificate(String.join(",", images));

            //省市区的id根据名称查出来
            if (StringUtils.isNotBlank(item.getProvinceName())) {
                Long provinceCode = tbRegionMapper.selectIdByName1(item.getProvinceName());
                if (provinceCode == null) {
                    erreList.put(item.getContactInformation(), "省名称有误");
                    continue;
                } else {
                    tbExamRegistration.setProvinceId(provinceCode);
                }
                if (StringUtils.isNotBlank(item.getCityName())) {
                    Long cityCode = tbRegionMapper.selectIdByName2(item.getCityName());
                    if (cityCode == null) {
                        erreList.put(item.getContactInformation(), "市名称有误");
                        continue;
                    } else {
                        tbExamRegistration.setCityId(cityCode);
                    }
                    if (StringUtils.isNotBlank(item.getAreaName())) {
                        Long areaCode = tbRegionMapper.selectIdByName3(item.getAreaName(),cityCode);
                        if (areaCode == null) {
                            erreList.put(item.getContactInformation(), "区名称有误");
                            continue;
                        } else {
                            tbExamRegistration.setAreaId(areaCode);
                        }
                    }else {
                        erreList.put(item.getContactInformation(), "区名称未填");
                        continue;
                    }
                }else{
                    erreList.put(item.getContactInformation(), "市名称未填");
                    continue;
                }
            }else{
                erreList.put(item.getContactInformation(), "省名称未填");
                continue;
            }

            tbExamRegistration.setCreateTime(DateUtils.getNowDate());
            tbExamRegistration.setIsPay(0);
            tbExamRegistration.setPayType(0);
            TbExamBatch byexamBatch = tbExamBatchMapper.getByexamBatch(item.getRegistrationBatch());
            if (ObjectUtils.isNotEmpty(byexamBatch)) {
                tbExamRegistration.setExamId(byexamBatch.getExamId());//考试ID
                tbExamRegistration.setRegistrationBatch(byexamBatch.getExamBatch());//考试批次
                tbExamRegistration.setExamBatchIndex(byexamBatch.getBatchIndex().intValue());//考试批次index
//                tbExamRegistration.setAgencyId(byexamBatch.getEvaluateAencyId());
                tbExamRegistration.setExamBatchIndex(Integer.valueOf(byexamBatch.getBatchIndex().toString()));//批次index
            }else {
                // 查询不到批次时，记录失败原因
                erreList.put(item.getContactInformation(), "未找到对应考试批次");
                continue;
            }
            TbCourse tbCourse1 = tbCourseMapper.selectTbCourseByName(tbExamRegistration.getCareerName());
            if (tbCourse1 == null){
                erreList.put(item.getContactInformation(), "未找到该职业名称");
                continue;
            }
            TbExam tbExam = examService.selectTbExamByExamId(byexamBatch.getExamId());
            if (ObjectUtils.isEmpty(tbExam)) {
                erreList.put(item.getContactInformation(), "考试信息异常");
                continue;
            }
            tbExamRegistration.setCourseId(tbCourse1.getCourseId());

            TbEvaluateAgency tbEvaluateAgency = tbEvaluateAgencyMapper.selectTbEvaluateAgencyByName(tbExamRegistration.getAgencyName());
            if (tbEvaluateAgency == null){
                erreList.put(item.getContactInformation(), "未找到该机构名称");
                continue;
            }
            tbExamRegistration.setAgencyId(tbEvaluateAgency.getEvaluateAgencyId());
            tbExamRegistration.setAgencyCode(tbEvaluateAgency.getEvaluateAgencyCode());
            TbStudyCenter tbStudyCenter = tbStudyCenterMapper.selectTbStudyCenterByStudyCenterName(tbExamRegistration.getStudyCenter());
            if (ObjectUtils.isEmpty(tbStudyCenter)){
                erreList.put(item.getContactInformation(), "未找到该学习中心名称");
                continue;
            }
            tbExamRegistration.setStudyCenterId(tbStudyCenter.getStudyCenterId());
            //如果没有用户，创建
            Long userId = tbStudentMapper.selectTbStudentByPhone(item.getContactInformation());
            if (ObjectUtils.isEmpty(userId)) {
                // 新增用户
                TbStudent insertStudent = new TbStudent();
                //报名信息直接赋值给用户
                insertStudent.setStudentName(item.getName());//姓名
                insertStudent.setSex(item.getSex());//性别
                insertStudent.setEducation(item.getEducation());//学历
                insertStudent.setGraduationSchool(item.getGraduationSchool());//毕业院校
                insertStudent.setBirthday(item.getBirthday());//出生日期
                insertStudent.setPhone(item.getContactInformation());
                insertStudent.setStudentNumber(IdUtils.fastSimpleUUID());
                insertStudent.setCreateTime(DateUtils.getNowDate());
                insertStudent.setExamineStatus(3);
                insertStudent.setFrozenStatus(0);
                insertStudent.setHeadPortrait("https://image.xnszz.com/IMG_1280_1280@FuvEKIdCm5NN36gZN9gJhk2Ei0-p.jpg");
                insertStudent.setNickName("学员_" + IdUtils.fastSimpleUUID().substring(1, 8));

                int row = tbStudentMapper.insertTbStudent(insertStudent);

                //如果成功再次根据手机号查询用户id
                if (row > 0){
                    userId = tbStudentMapper.selectTbStudentByPhone(item.getContactInformation());
                }else {
                    // 新增用户失败，记录失败原因
                    erreList.put(item.getContactInformation(), "新增用户失败");
                    continue;
                }
            }else {
                //如果有用户，则补充用户信息
                TbStudent tbStudent = tbStudentMapper.selectTbStudentByStudentId(userId);
                //姓名、性别、学历、毕业院校、出生日期
                if (StringUtils.isEmpty(tbStudent.getStudentName())){
                    tbStudent.setStudentName(item.getName());
                }
                if (tbStudent.getSex() == null|| tbStudent.getSex() == 2){
                    tbStudent.setSex(item.getSex());
                }
                if (StringUtils.isEmpty(tbStudent.getEducation())){
                    tbStudent.setEducation(item.getEducation());
                }
                if (StringUtils.isEmpty(tbStudent.getGraduationSchool())){
                    tbStudent.setGraduationSchool(item.getGraduationSchool());
                }
                if (StringUtils.isEmpty(tbStudent.getBirthday())){
                    tbStudent.setBirthday(item.getBirthday());
                }
                //更新个人资料
                tbStudentMapper.updateTbStudent(tbStudent);
            }
            if(ObjectUtils.isNotEmpty(userId)){
                tbExamRegistration.setMemberUserId(userId);
            }

            //校验当前数据是否在库中已存在
            TbExamRegistration tbExamRegistrations = tbExamRegistrationMapper.selectTbExamRegistrationByBatchIndex(tbExamRegistration);
            if(ObjectUtils.isNotEmpty(tbExamRegistrations)){//根据批次batchIndex和MemberUserId和考试Id查出数据，同批次不能重复报名
                // 数据已存在，记录失败原因
                erreList.put(item.getContactInformation(), "已报名");
                continue;
            }
            int row = tbExamRegistrationMapper.insertTbExamRegistration(tbExamRegistration);
            if (row > 0){
                TbMemberMajor tbMemberMajor = tbMemberMajorMapper.selectTbMemberMajorByMemberAndMajorId(tbExamRegistration.getMemberUserId(), null, tbExamRegistration.getCourseId());
                if (tbMemberMajor != null) {
                    tbMemberMajor.setUpdateTime(DateUtils.getNowDate());
                    tbMemberMajorMapper.updateTbMemberMajor(tbMemberMajor);
                } else {
                    TbMemberMajor memberMajor = new TbMemberMajor();
                    memberMajor.setMemberUserId(tbExamRegistration.getMemberUserId());
                    memberMajor.setResId(tbExamRegistration.getCourseId());
                    memberMajor.setCreateTime(DateUtils.getNowDate());
                    memberMajor.setType(1);
                    tbMemberMajorMapper.insertTbMemberMajor(memberMajor);
                }
                //生成订单
                TbMemberOrder memberOrder = new TbMemberOrder();
                memberOrder.setOrderNo(IdUtil.getSnowflakeNextIdStr());
                memberOrder.setMemberUserId(tbExamRegistration.getMemberUserId());
                memberOrder.setDataId(tbExamRegistration.getExamRegistrationId());
                memberOrder.setPayPrice(tbExam.getPrice());
                memberOrder.setOrderPrice(tbExam.getPrice());
                memberOrder.setDeductionScore(new BigDecimal(0));
                memberOrder.setOrderType(2);
                memberOrder.setPayType(0);
                memberOrder.setPayStatus(0);
                memberOrder.setOrderName(tbExam.getName() + "考试报名费");
                memberOrder.setRemarks(tbExam.getName() + "考试报名费");
                memberOrderService.insertTbMemberOrder(memberOrder);
                //处理参与量
                threadPoolTaskExecutor.execute(() -> {
                    TbCourse tbCourse = tbCourseMapper.selectTbCourseByCourseId(tbExamRegistration.getCourseId());
                    if (StringUtils.isNotNull(tbCourse)){
                        tbCourse.setParticipateNum(tbCourse.getParticipateNum() + 1);
                        tbCourseMapper.updateTbCourse(tbCourse);
                    }
                });
                //生成准考证号
                String examNumber =  getZkzh(tbExamRegistration);
                tbExamRegistration.setZkzh(examNumber);
                tbExamRegistrationMapper.updateTbExamRegistration(tbExamRegistration);
                successRow++;
            }else{
                erreList.put(item.getContactInformation(), "新增失败");
            }

        }
        if (successRow>0) {
            String baseMessage = "导入成功" + successRow + "条数据, 失败" + erreList.size() + "条数据";
            if (!erreList.isEmpty()) {
                List<String> failedInfoStrings = new ArrayList<>();
                for (Map.Entry<String, String> entry : erreList.entrySet()) {
                    failedInfoStrings.add("联系方式："+entry.getKey() + "（原因：" + entry.getValue() + "）<br>");
                }
                baseMessage += ", 失败信息：<br>" + String.join(" ", failedInfoStrings);
            }
            return baseMessage;
        } else {
            String message = "无数据导入, 失败" + erreList.size() + "条数据";
            if (!erreList.isEmpty()) {
                List<String> failedInfoStrings = new ArrayList<>();
                for (Map.Entry<String, String> entry : erreList.entrySet()) {
                    failedInfoStrings.add("联系方式："+entry.getKey() + "（原因：" + entry.getValue() + "）<br>");
                }
                message += ", 失败信息：<br>" + String.join(" ", failedInfoStrings);
            }
            return message;
        }


    }

    @Override
    public AjaxResult havaOrderToPay(Long memberUserId) {
        boolean exists = tbMemberOrderMapper.existsUnpaidExamOrder(memberUserId);
        return exists ? AjaxResult.success("您有新的考试报名信息还没有支付") : AjaxResult.success("");
    }

    /*
    * 生成准考证号
    * */
    public String getZkzh(TbExamRegistration tbExamRegistration){
        //生成准考证号
        String redisKey = "zkzh:" + tbExamRegistration.getCourseId()+tbExamRegistration.getStudyCenterId()+tbExamRegistration.getAgencyCode();
        int number = 1;
        if (redisCache.hasKey(redisKey)) {
            //查出缓存中的数据
            Integer cachedData = redisCache.getCacheObject(redisKey);
            if (cachedData!=null) {
                number = cachedData;
                if (number > 999999) {//大于了重置，否则就生成准考证号并加1存储
                    number = 1;
                }
            }
        }
        redisCache.setCacheObject(redisKey, number+1);
        // 给number前面补0，使其总长度为6位
        String formattedNumber = String.format("%06d", number);
        return tbExamRegistration.getRegistrationBatch()+tbExamRegistration.getStudyCenterId()+tbExamRegistration.getAgencyCode()+formattedNumber;
    }

}
