package com.yonge.cooleshow.biz.dal.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yonge.cooleshow.auth.api.client.SysUserFeignService;
import com.yonge.cooleshow.biz.dal.dao.StudentDao;
import com.yonge.cooleshow.biz.dal.dto.search.StudentSearch;
import com.yonge.cooleshow.biz.dal.entity.*;
import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
import com.yonge.cooleshow.biz.dal.enums.MessageTypeEnum;
import com.yonge.cooleshow.biz.dal.enums.SourceTypeEnum;
import com.yonge.cooleshow.biz.dal.mapper.TenantActivationCodeMapper;
import com.yonge.cooleshow.biz.dal.mapper.TenantAlbumPurchaseMapper;
import com.yonge.cooleshow.biz.dal.mapper.UserTenantAlbumRecordMapper;
import com.yonge.cooleshow.biz.dal.service.*;
import com.yonge.cooleshow.biz.dal.vo.StudentVo;
import com.yonge.cooleshow.biz.dal.vo.UserOrderDetailVo;
import com.yonge.cooleshow.biz.dal.wrapper.TenantActivationCodeWrapper;
import com.yonge.cooleshow.biz.dal.wrapper.TenantAlbumWrapper;
import com.yonge.cooleshow.common.entity.HttpResponseResult;
import com.yonge.cooleshow.common.enums.EActivationCode;
import com.yonge.toolset.base.exception.BizException;
import com.yonge.toolset.mybatis.support.PageUtil;
import com.yonge.toolset.thirdparty.message.MessageSenderPluginContext;
import com.yonge.toolset.utils.easyexcel.ExcelDataReaderProperty;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.function.Function;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 机构激活码
 * 2023-07-21 17:32:49
 */
@Slf4j
@Service
public class TenantActivationCodeServiceImpl extends ServiceImpl<TenantActivationCodeMapper, TenantActivationCode> implements TenantActivationCodeService {

    @Autowired
    private StudentDao studentDao;

    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private TenantAlbumPurchaseMapper tenantAlbumPurchaseMapper;

    @Autowired
    private UserTenantAlbumRecordMapper userTenantAlbumRecordMapper;

    @Autowired
    private TenantInfoService tenantInfoService;

    @Autowired
    private SysMessageService sysMessageService;

    @Autowired
    private TenantGroupAlbumService tenantGroupAlbumService;


    private static final String PHONE_REG = "^1\\d{10}$";

    /**
     * 查询详情
     *
     * @param id 详情ID
     * @return TenantActivationCode
     */
    @Override
    public TenantActivationCode detail(Long id) {

        return baseMapper.selectById(id);
    }

    /**
     * 分页查询
     *
     * @param page  IPage<TenantActivationCode>
     * @param query TenantActivationCodeWrapper.TenantActivationCodeQuery
     * @return IPage<TenantActivationCode>
     */
    @Override
    public IPage<TenantActivationCodeWrapper.TenantActivationCode> selectPage(IPage<TenantActivationCodeWrapper.TenantActivationCode> page,
                                                                              TenantActivationCodeWrapper.TenantActivationCodeQuery query) {

        return page.setRecords(baseMapper.selectPage(page, query));
    }

    /**
     * 添加
     *
     * @param tenantActivationCode TenantActivationCodeWrapper.TenantActivationCode
     * @return Boolean
     */
    @Override
    public Boolean add(TenantActivationCodeWrapper.TenantActivationCode tenantActivationCode) {

        return this.save(JSON.parseObject(tenantActivationCode.jsonString(), TenantActivationCode.class));
    }

    /**
     * 更新
     *
     * @param tenantActivationCode TenantActivationCodeWrapper.TenantActivationCode
     * @return Boolean
     */
    @Override
    public Boolean update(TenantActivationCodeWrapper.TenantActivationCode tenantActivationCode) {

        return this.updateById(JSON.parseObject(tenantActivationCode.jsonString(), TenantActivationCode.class));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void sendActivationCode(Long tenantId, Long tenantAlbumPurchaseId, List<String> activationCodeList,
                                   List<Long> studentIdList) {
        QueryWrapper<TenantActivationCode> queryWrapper = new QueryWrapper<>();
        if (CollectionUtils.isEmpty(activationCodeList)) {
            // 入参为空走批量发放方式
            queryWrapper.lambda().eq(TenantActivationCode::getTenantId, tenantId)
                    .eq(TenantActivationCode::getTenantAlbumPurchaseId, tenantAlbumPurchaseId)
                    .eq(TenantActivationCode::getSendStatus, EActivationCode.WAIT)
                    .eq(TenantActivationCode::getActivationStatus, false);
        } else {
            queryWrapper.lambda().eq(TenantActivationCode::getTenantId, tenantId)
                    .eq(TenantActivationCode::getTenantAlbumPurchaseId, tenantAlbumPurchaseId)
                    .in(TenantActivationCode::getActivationCode, activationCodeList)
                    .eq(TenantActivationCode::getSendStatus, EActivationCode.WAIT)
                    .eq(TenantActivationCode::getActivationStatus, false);
        }

        List<TenantActivationCode> tenantActivationCodes = baseMapper.selectList(queryWrapper);
        if (tenantActivationCodes.isEmpty()) {
            throw new BizException("无可发放的激活码");
        }

        QueryWrapper<Student> studentQueryWrapper = new QueryWrapper<>();
        studentQueryWrapper.lambda().eq(Student::getTenantId, tenantId)
                .in(Student::getUserId, studentIdList);
        List<Student> students = studentDao.selectList(studentQueryWrapper);
        if (tenantActivationCodes.size() < students.size()) {
            throw new BizException("学生的数量不能大于可用的激活码数量");
        }

        List<Long> studentIds = students.stream().map(Student::getUserId).collect(Collectors.toList());
        Map<Long, String> idPhoneMap = sysUserService.getDao().selectBatchIds(studentIds).stream()
                .collect(Collectors.toMap(SysUser::getId, SysUser::getPhone));

        for (int i = 0; i < studentIds.size(); i++) {
            Long studentId = studentIds.get(i);
            boolean update = this.lambdaUpdate()
                    .set(TenantActivationCode::getSendStatus, EActivationCode.SEND.getCode())
                    .set(TenantActivationCode::getActivationPhone, idPhoneMap.get(studentId))
                    .set(TenantActivationCode::getSendTime, new Date())
                    .eq(TenantActivationCode::getActivationStatus, false)
                    .eq(TenantActivationCode::getId, tenantActivationCodes.get(i).getId())
                    .update();
            if (!update) {
                throw new BizException("激活码已被激活:" + tenantActivationCodes.get(i).getActivationCode());
            }
        }
        if (idPhoneMap.size() >0) {
            idPhoneMap.forEach(this::sendActivationCodeMessage);
        }
    }

    private void sendActivationCodeMessage(Long userId,String phone) {

        Map<Long, String> receivers = new HashMap<>(1);
        receivers.put(userId, phone);
        try {
            sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG, MessageTypeEnum.TENANT_SEND_CODE,
                    receivers, null, 0, null, ClientEnum.TENANT_STUDENT.getCode());
        } catch (Exception e) {
            log.error("机构发放激活码推送异常", e);
        }
    }

    @Override
    public void sendCancelActivationCodeMessage(Map<Long, String> receivers, String tenantName) {
        try {
            sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG, MessageTypeEnum.TENANT_CODE_SENDCANCEL,
                    receivers, null, 0, null, ClientEnum.TENANT_STUDENT.getCode(),tenantName);
        } catch (Exception e) {
            log.error("机构发放激活码推送异常", e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void active(String activationCode, Long studentId) {
        Student student = studentDao.selectById(studentId);
        if (student == null) {
            throw new BizException("学生不存在");
        }
        TenantActivationCode code = this.lambdaQuery().eq(TenantActivationCode::getActivationCode, activationCode).last("limit 1").one();
        if (code == null) {
            throw new BizException("激活码不存在");
        }
        if (Boolean.TRUE.equals(code.getActivationStatus())) {
            throw new BizException("激活码已经被使用");
        }

        // 判断激活码是否已经发送给学生
        SysUser sysUser = sysUserService.getDao().selectById(studentId);
        if (!sysUser.getPhone().equals(code.getActivationPhone())) { // 发给自己不校验，可以直接用，未发放需要校验
            if (EActivationCode.SEND.equals(code.getSendStatus())) { //已经发送给别人
                throw new BizException("激活码不可用");
            }
            // 未发放，线下抄送
            // 校验小组专辑的小组和机构是否和学生一致，并且小组专辑是启用状态
            Long tenantAlbumId = code.getTenantAlbumId();
            List<Long> tenantGroupIds = tenantGroupAlbumService.lambdaQuery()
                    .eq(TenantGroupAlbum::getTenantAlbumId, tenantAlbumId)
                    .eq(TenantGroupAlbum::getStatus, true)
                    .eq(TenantGroupAlbum::getDelFlag, false)
                    .list().stream().map(TenantGroupAlbum::getTenantGroupId).distinct().collect(Collectors.toList());
            if (!tenantGroupIds.contains(student.getTenantGroupId())) {
                throw new BizException("激活码不可用");
            }
        }



        // 通过状态和ID同时判断更新是否存在竞争
        boolean update = this.lambdaUpdate()
                .set(TenantActivationCode::getActivationStatus, true)
                .set(TenantActivationCode::getActivationUserId, student.getUserId())
                .set(TenantActivationCode::getActivationTime, new Date())
                .set(TenantActivationCode::getActivationPhone, sysUser.getPhone())
                .set(TenantActivationCode::getSendStatus, EActivationCode.SEND)
                .eq(TenantActivationCode::getId, code.getId())
                .eq(TenantActivationCode::getActivationStatus, false)
                .update();
        if (!update) {
            throw new BizException("激活码已经被使用");
        }
        Long tenantAlbumPurchaseId = code.getTenantAlbumPurchaseId();
        TenantAlbumPurchase purchase = tenantAlbumPurchaseMapper.selectById(tenantAlbumPurchaseId);

        addUserTenantAlbumRecord(student.getUserId(), purchase, null);

        Long tenantId = Optional.ofNullable(student.getTenantId()).orElse(-1L);
        // 更新购买记录中激活码使用统计数量值
        Integer activeCodeNumber = this.lambdaQuery()
                .eq(TenantActivationCode::getTenantId, tenantId)
                .eq(TenantActivationCode::getTenantAlbumPurchaseId, code.getTenantAlbumPurchaseId())
                .eq(TenantActivationCode::getActivationStatus, true).count();

        TenantAlbumPurchase albumPurchase = tenantAlbumPurchaseMapper.selectById(code.getTenantAlbumPurchaseId());
        albumPurchase.setActiveQuantity(activeCodeNumber);
        if (activeCodeNumber.equals(albumPurchase.getPurchaseQuantity())) {
            albumPurchase.setActiveStatus("ALL");
        } else {
            albumPurchase.setActiveStatus("PART");
        }
        tenantAlbumPurchaseMapper.updateById(albumPurchase);
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public void activeById(String id, Long userId) {
        Student student = studentDao.selectById(userId);
        if (student == null) {
            throw new BizException("学生不存在");
        }
        TenantActivationCode code = baseMapper.selectById(id);
        if(code == null) {
            throw new BizException("激活码不存在");
        }
        SysUser sysUser = sysUserService.getDao().selectById(student.getUserId());
        if(!sysUser.getPhone().equals(code.getActivationPhone())) {
            // 该激活码未指定为当前学生使用
            throw new BizException("激活码不存在");
        }
        if (Boolean.TRUE.equals(code.getActivationStatus())) {
            throw new BizException("激活码已经被使用");
        }

        // 通过状态和ID同时判断更新是否存在竞争
        boolean update = this.lambdaUpdate()
                .set(TenantActivationCode::getActivationStatus, true)
                .set(TenantActivationCode::getActivationUserId, student.getUserId())
                .set(TenantActivationCode::getActivationTime, new Date())
                .set(TenantActivationCode::getActivationPhone, sysUser.getPhone())
                .eq(TenantActivationCode::getId, code.getId())
                .eq(TenantActivationCode::getActivationStatus, false)
                .update();
        if (!update) {
            throw new BizException("激活码已经被使用");
        }
        Long tenantAlbumPurchaseId = code.getTenantAlbumPurchaseId();
        TenantAlbumPurchase purchase = tenantAlbumPurchaseMapper.selectById(tenantAlbumPurchaseId);

        addUserTenantAlbumRecord(student.getUserId(), purchase, null);

        // 更新购买记录中激活码使用统计数量值
        Integer activeCodeNumber = this.lambdaQuery()
                .eq(TenantActivationCode::getTenantId, code.getTenantId())
                .eq(TenantActivationCode::getTenantAlbumPurchaseId, code.getTenantAlbumPurchaseId())
                .eq(TenantActivationCode::getActivationStatus, true).count();

        TenantAlbumPurchase tenantAlbumPurchase = new TenantAlbumPurchase();
        tenantAlbumPurchase.setId(code.getTenantAlbumPurchaseId());
        tenantAlbumPurchase.setActiveQuantity(activeCodeNumber);

        if (activeCodeNumber.equals(tenantAlbumPurchase.getPurchaseQuantity())) {
            tenantAlbumPurchase.setActiveStatus("ALL");
        } else {
            tenantAlbumPurchase.setActiveStatus("PART");
        }
        tenantAlbumPurchaseMapper.updateById(tenantAlbumPurchase);

    }

    @Override
    public void resend(String code, Long userId, Long tenantId, Long tenantAlbumPurchaseId) {
        // 查询激活码信息
        TenantActivationCode one = this.lambdaQuery()
                .eq(TenantActivationCode::getActivationCode, code)
                .eq(TenantActivationCode::getTenantId, tenantId)
                .eq(TenantActivationCode::getTenantAlbumPurchaseId, tenantAlbumPurchaseId)
                .eq(TenantActivationCode::getSendStatus, EActivationCode.SEND)
                .last("limit 1")
                .one();
        if(one == null) {
            throw new BizException("当前激活码不可以重发");
        }
        if (Boolean.TRUE.equals(one.getActivationStatus())) {
            throw new BizException("激活码已经被使用");
        }

        SysUser sysUser = sysUserService.getDao().selectById(userId);
        if (sysUser == null) {
            throw new BizException("用户不存在");
        }
        one.setActivationPhone(sysUser.getPhone());
        this.updateById(one);
        TenantInfo tenantInfo = tenantInfoService.getById(tenantId);
        Map<Long, String> receivers = new HashMap<>(1);
        receivers.put(userId, sysUser.getPhone());
        this.sendCancelActivationCodeMessage(receivers,tenantInfo.getName());
        this.sendActivationCodeMessage(userId,sysUser.getPhone());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void sendCancel(TenantInfo tenantInfo, TenantActivationCode activationCode) {
        boolean update = this.lambdaUpdate()
                .set(TenantActivationCode::getSendStatus, EActivationCode.WAIT)
                .set(TenantActivationCode::getActivationPhone, "")
                .set(TenantActivationCode::getSendTime, null)
                .eq(TenantActivationCode::getId, activationCode.getId())
                .eq(TenantActivationCode::getActivationStatus, false)
                .eq(TenantActivationCode::getSendStatus, EActivationCode.SEND)
                .update();
        if (!update) {
            TenantActivationCode code = this.getById(activationCode.getId());
            if (EActivationCode.WAIT.equals(code.getSendStatus())) {
                throw new BizException(5101, "激活码已撤回");
            }
            if (Boolean.TRUE.equals(code.getActivationStatus())) {
                throw new BizException(5102, "激活码已经激活");
            }
        }
        com.yonge.cooleshow.auth.api.entity.SysUser sysUser = sysUserService.findUserByPhone(activationCode.getActivationPhone());
        if (sysUser != null) {
            Map<Long, String> receivers = new HashMap<>(1);
            receivers.put(sysUser.getId(), activationCode.getActivationPhone());
            this.sendCancelActivationCodeMessage(receivers,tenantInfo.getName());
        }
    }
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void batchSendCancel(TenantInfo tenantInfo, String ids) {
        List<Long> idList = Arrays.stream(ids.split(",")).map(Long::valueOf).distinct().collect(Collectors.toList());
        Collection<TenantActivationCode> tenantActivationCodes = this.listByIds(idList);
        for (TenantActivationCode tenantActivationCode : tenantActivationCodes) {
            if (Boolean.TRUE.equals(tenantActivationCode.getActivationStatus())) {
                throw new BizException(5102, "激活码已经激活");
            }
        }
        tenantActivationCodes.removeIf(next -> Boolean.TRUE.equals(next.getActivationStatus()));
        if (tenantActivationCodes.isEmpty()) {
            throw new BizException("无可撤回的激活码");
        }

        for (TenantActivationCode code : tenantActivationCodes) {
            this.sendCancel(tenantInfo, code);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void batchResend(TenantInfo tenantInfo, Long tenantAlbumPurchaseId, List<String> activationCodeList,
                            List<Long> studentIdList) {

        if (CollectionUtils.isEmpty(studentIdList)) {
            throw new BizException("学生列表不能为空");
        }

        QueryWrapper<TenantActivationCode> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(TenantActivationCode::getTenantId, tenantInfo.getId())
                .eq(TenantActivationCode::getTenantAlbumPurchaseId, tenantAlbumPurchaseId)
                .eq(TenantActivationCode::getActivationStatus, false)
                .in(CollectionUtils.isNotEmpty(activationCodeList), TenantActivationCode::getActivationCode,
                        activationCodeList);
        List<TenantActivationCode> activationCodes = this.list(queryWrapper);
        if (activationCodes.isEmpty()) {
            throw new BizException("无可重发的激活码");
        }
        if (activationCodes.size() < studentIdList.size()) {
            throw new BizException("可发激活码的数量小于学生的数量");
        }

        List<SysUser> sysUsers = sysUserService.getDao().selectBatchIds(studentIdList);
        Map<Long, String> mapPhoneById = sysUsers.stream().collect(Collectors.toMap(SysUser::getId, SysUser::getPhone));

        List<TenantActivationCode> updates = new ArrayList<>();
        for (int i = 0; i < studentIdList.size(); i++) {
            TenantActivationCode tenantActivationCode = activationCodes.get(i);
            tenantActivationCode.setSendStatus(EActivationCode.SEND);
            tenantActivationCode.setSendTime(new Date());
            tenantActivationCode.setActivationPhone(mapPhoneById.getOrDefault(studentIdList.get(i), ""));
            updates.add(tenantActivationCode);
        }
        this.updateBatchById(updates);
    }


    /**
     * 添加用户机构专辑激活记录
     *
     * @param studentId         学生ID
     * @param userOrderDetailVo 订单详情
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addUserTenantAlbumRecord(Long studentId, UserOrderDetailVo userOrderDetailVo) {
        addUserTenantAlbumRecord(studentId, null, userOrderDetailVo);

    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public HttpResponseResult<Object> importActiveCode(List<ExcelDataReaderProperty<TenantActivationCodeWrapper.ImportTemplate>> dataList,
                                                           Long tenantId, Long userId, Long tenantAlbumPurchaseId) {
        if (dataList.isEmpty()) {
            return HttpResponseResult.failed(500, null, "未解析到数据");
        }
        dataList.sort(Comparator.comparingInt(ExcelDataReaderProperty::getRowIndex));

        List<TenantActivationCodeWrapper.ImportTemplate> importTemplates = dataList.stream().map(ExcelDataReaderProperty::getClazz).collect(Collectors.toList());
        List<String> codeList = importTemplates.stream().map(TenantActivationCodeWrapper.ImportTemplate::getCode).
                filter(StringUtils::isNotEmpty).collect(Collectors.toList());
        if (codeList.isEmpty()) {
            return HttpResponseResult.failed(500, null, "未指定激活码");
        }

        List<String> phoneList = importTemplates.stream().map(TenantActivationCodeWrapper.ImportTemplate::getPhone)
                        .filter(StringUtils::isNotEmpty).collect(Collectors.toList());
        if (phoneList.isEmpty()) {
            return HttpResponseResult.failed(500, null, "未指定手机号");
        }

        List<TenantActivationCode> activationCodes = this.lambdaQuery()
                .eq(TenantActivationCode::getTenantId, tenantId)
                .eq(TenantActivationCode::getTenantAlbumPurchaseId, tenantAlbumPurchaseId)
                .in(TenantActivationCode::getActivationCode, codeList).list();
        Map<String, TenantActivationCode> mapByCode = activationCodes.stream().collect(Collectors.toMap(TenantActivationCode::getActivationCode, Function.identity()));


        TenantAlbumPurchase purchase = tenantAlbumPurchaseMapper.selectById(tenantAlbumPurchaseId);
        List<Long> tenantGroupIds = tenantGroupAlbumService.lambdaQuery()
                .eq(TenantGroupAlbum::getTenantAlbumId, purchase.getTenantAlbumId())
                .eq(TenantGroupAlbum::getStatus, true)
                .eq(TenantGroupAlbum::getDelFlag, false)
                .list().stream().map(TenantGroupAlbum::getTenantGroupId).distinct().collect(Collectors.toList());

        StudentSearch studentSearch = new StudentSearch();
        studentSearch.setRows(9999);
        studentSearch.setPage(1);
        studentSearch.setPhoneList(phoneList);
        List<StudentVo> studentVos = studentDao.selectPage(PageUtil.getPage(studentSearch), studentSearch);
        Map<String, StudentVo> mapStudentByPhone = studentVos.stream().collect(Collectors.toMap(StudentVo::getPhone, Function.identity()));

//        Map<Integer,List<String>> errMsgMap = new LinkedHashMap<>();
        Map<String, Integer> codeRowMap = new HashMap<>();


        String phone_err = "手机号错误或已注册成为其他机构";
        List<Integer> phone_err_lines = new ArrayList<>();
        String code_send = "激活码已被发放";
        List<Integer> code_send_lines = new ArrayList<>();
        String code_not_exist = "激活码不存在";
        List<Integer> code_not_exist_lines = new ArrayList<>();
        String code_repeat = "激活码重复";
        Map<String,List<Integer>> code_repeat_lines = new LinkedHashMap<>();

        int rowIndex = 1;
        // 校验数据格式是否错误 第二行开始取数据
        for (TenantActivationCodeWrapper.ImportTemplate template : importTemplates) {
            rowIndex++;

            String acCode = template.getCode();
            if (StringUtils.isEmpty(acCode)) {
                continue;
            }
            int msgRowNo = rowIndex;
//            List<String> errList = errMsgMap.getOrDefault(msgRowNo, new ArrayList<>());
            String code = template.getCode();
            if (codeRowMap.containsKey(code)) {
                List<Integer> lines = code_repeat_lines.getOrDefault(code, new ArrayList<>());
                Integer repeatLine = codeRowMap.get(code);
                if (!lines.contains(repeatLine)) {
                    lines.add(repeatLine);
                }
                lines.add(msgRowNo);
                code_repeat_lines.put(code, lines);
            } else {
                codeRowMap.put(acCode, msgRowNo);
            }

            if (!mapByCode.containsKey(code)) {
                code_not_exist_lines.add(msgRowNo);
            } else {
                TenantActivationCode tenantActivationCode = mapByCode.get(code);
                if (tenantActivationCode.getActivationStatus() || EActivationCode.SEND.equals(tenantActivationCode.getSendStatus())) {
                    code_send_lines.add(msgRowNo);
                }
            }
            String phone = template.getPhone();
            if (StringUtils.isNotEmpty(phone)) {
                if (!Pattern.matches(PHONE_REG, phone.trim()) ||
                        (mapStudentByPhone.containsKey(phone) && ((!mapStudentByPhone.get(phone).getTenantId().equals(tenantId)) ||
                                !tenantGroupIds.contains(mapStudentByPhone.get(phone).getTenantGroupId())))) {
                    phone_err_lines.add(msgRowNo);
                }
            }

//            errMsgMap.put(msgRowNo, errList);
        }


        int totalErrSize = phone_err_lines.size() + code_send_lines.size() + code_not_exist_lines.size() + code_repeat_lines.values().size();
        if (totalErrSize > 0) {
            StringBuilder errMsg = new StringBuilder("");
            errMsg.append("导入失败，共").append(totalErrSize).append("条错误信息~");
            List<String> errData = new ArrayList<>();
            if (!phone_err_lines.isEmpty()) {
                StringBuilder err = new StringBuilder("");
                String errLines = phone_err_lines.stream().map(String::valueOf).collect(Collectors.joining("、"));
                err.append("第").append(errLines).append("行错误，").append(phone_err);
                errData.add(err.toString());
            }

            if (!code_send_lines.isEmpty()) {
                StringBuilder err = new StringBuilder("");
                String errLines = code_send_lines.stream().map(String::valueOf).collect(Collectors.joining("、"));
                err.append("第").append(errLines).append("行错误，").append(code_send);
                errData.add(err.toString());
            }

            if (!code_not_exist_lines.isEmpty()) {
                StringBuilder err = new StringBuilder("");
                String errLines = code_not_exist_lines.stream().map(String::valueOf).collect(Collectors.joining("、"));
                err.append("第").append(errLines).append("行错误，").append(code_not_exist);
                errData.add(err.toString());
            }

            if (!code_repeat_lines.isEmpty()) {
                StringBuilder err = new StringBuilder("");
                List<String> lineErr = new ArrayList<>();
                for (List<Integer> value : code_repeat_lines.values()) {
                    String errLines = value.stream().map(String::valueOf).collect(Collectors.joining("、"));
                    lineErr.add("第" + errLines + "行");
                }
                err.append(String.join(",", lineErr)).append("错误，").append(code_repeat);
                errData.add(err.toString());
            }
            return HttpResponseResult.failed(500, errData,errMsg.toString());
        }


//        List<String> errMsg = errMsgMap.values().stream().flatMap(Collection::stream).collect(Collectors.toList());
//        if (!errMsg.isEmpty()) {
//            String errLines = errMsgMap.entrySet().stream().filter(next -> CollectionUtils.isNotEmpty(next.getValue()))
//                    .map(next -> String.valueOf(next.getKey())).collect(Collectors.joining("、"));
//            errMsg.add(0, "第" + errLines + "行存在错误");
//            throw new BizException(String.join(",", errMsg));
//        }
        List<TenantActivationCode> tenantActivationCodes = importTemplates.stream()
                .filter(next -> StringUtils.isNotEmpty(next.getCode()) && StringUtils.isNotBlank(next.getPhone()))
                .map(next -> {
                    TenantActivationCode record = mapByCode.get(next.getCode());
                    TenantActivationCode tenantActivationCode = new TenantActivationCode();
                    tenantActivationCode.setId(record.getId());
                    tenantActivationCode.setActivationPhone(next.getPhone());
                    tenantActivationCode.setSendStatus(EActivationCode.SEND);
                    return tenantActivationCode;
                }).collect(Collectors.toList());
        if (tenantActivationCodes.isEmpty()) {
            return HttpResponseResult.failed(500, null, "没有合法的导入数据");
        }
        this.updateBatchById(tenantActivationCodes, 50);
        return HttpResponseResult.succeed();
    }

    private void addUserTenantAlbumRecord(Long studentId, TenantAlbumPurchase purchase,
                                          UserOrderDetailVo userOrderDetailVo) {


        UserTenantAlbumRecord userTenantAlbumRecord = new UserTenantAlbumRecord();
        if (userOrderDetailVo != null) {

            TenantAlbumWrapper.TenantAlbumContent tenantAlbumContent = JSON
                    .parseObject(userOrderDetailVo.getBizContent(), TenantAlbumWrapper.TenantAlbumContent.class);

            userTenantAlbumRecord.setTenantId(tenantAlbumContent.getTenantId());
            userTenantAlbumRecord.setUserId(studentId);
            userTenantAlbumRecord.setTenantAlbumId(tenantAlbumContent.getTenantAlbumId());
            userTenantAlbumRecord.setOrderNo(userOrderDetailVo.getOrderNo());
            userTenantAlbumRecord.setSourceType(SourceTypeEnum.ORDER);
            userTenantAlbumRecord.setClientType(ClientEnum.STUDENT);
            userTenantAlbumRecord.setSubOrderNo(userOrderDetailVo.getSubOrderNo());
            userTenantAlbumRecord.setCreateBy(studentId);
            userTenantAlbumRecord.setTimes(tenantAlbumContent.getBuyCycle());
            userTenantAlbumRecord.setType(tenantAlbumContent.getPurchaseType());
        } else if (purchase != null) {

            userTenantAlbumRecord.setTenantId(purchase.getTenantId());
            userTenantAlbumRecord.setUserId(studentId);
            userTenantAlbumRecord.setTenantAlbumId(purchase.getTenantAlbumId());
            userTenantAlbumRecord.setOrderNo(purchase.getId().toString());
            userTenantAlbumRecord.setSourceType(SourceTypeEnum.TENANT);
            userTenantAlbumRecord.setClientType(ClientEnum.STUDENT);
            userTenantAlbumRecord.setSubOrderNo(purchase.getId().toString());
            userTenantAlbumRecord.setCreateBy(studentId);
            userTenantAlbumRecord.setTimes(purchase.getPurchaseCycle());
            userTenantAlbumRecord.setType(purchase.getPurchaseType());
        }

        List<UserTenantAlbumRecord> userTenantAlbumRecords = userTenantAlbumRecordMapper
                .selectList(Wrappers.<UserTenantAlbumRecord>lambdaQuery()
                        .eq(UserTenantAlbumRecord::getTenantId, userTenantAlbumRecord.getTenantId())
                        .eq(UserTenantAlbumRecord::getUserId, studentId)
                        .eq(UserTenantAlbumRecord::getTenantAlbumId, userTenantAlbumRecord.getTenantAlbumId())
                        .eq(UserTenantAlbumRecord::getClientType, ClientEnum.STUDENT)
                        .orderByDesc(UserTenantAlbumRecord::getEndTime));

        userTenantAlbumRecord.setUserId(studentId);
        userTenantAlbumRecord.setCreateBy(studentId);


//        userTenantAlbumRecord.setType("MONTH");

        Calendar instance = Calendar.getInstance();
        if (userTenantAlbumRecords.isEmpty()) {
            instance.setTime(DateTime.now().withHourOfDay(0).withMinuteOfHour(0).withSecondOfMinute(0).toDate());
        } else {
            // 如果最后一次的时间的小于当前时间，则以当前时间为会员的开始时间
            // 如果最后一次的时间的大于当前时间，则以最后一次的结束时间为记录的开始时间，相当会员续期
            UserTenantAlbumRecord lastRecord = userTenantAlbumRecords.get(0);
            Date lastEndTime = lastRecord.getEndTime();
            if (lastEndTime.before(new Date())) {
                instance.setTime(DateTime.now().withHourOfDay(0).withMinuteOfHour(0).withSecondOfMinute(0).toDate());
            } else {
                instance.setTime(lastEndTime);
            }
        }
        userTenantAlbumRecord.setStartTime(instance.getTime());
        //DAY 日 MONTH 月 QUARTERLY 季度 YEAR_HALF 半年 YEAR 年
        switch (userTenantAlbumRecord.getType()) {
            case "DAY":
                instance.add(Calendar.DAY_OF_MONTH, userTenantAlbumRecord.getTimes());
                break;
            case "MONTH":
                instance.add(Calendar.MONTH, userTenantAlbumRecord.getTimes());
                break;
            case "QUARTERLY":
                instance.add(Calendar.MONTH, userTenantAlbumRecord.getTimes() * 3);
                break;
            case "YEAR_HALF":
                instance.add(Calendar.MONTH, userTenantAlbumRecord.getTimes() * 6);
                break;
            case "YEAR":
                instance.add(Calendar.MONTH, userTenantAlbumRecord.getTimes() * 12);
                break;
            default:
                instance.add(Calendar.MONTH, userTenantAlbumRecord.getTimes());
                break;
        }

        instance.set(Calendar.HOUR_OF_DAY, 23);
        instance.set(Calendar.MINUTE, 59);
        instance.set(Calendar.SECOND, 59);
        instance.set(Calendar.MILLISECOND, 0);
        userTenantAlbumRecord.setEndTime(instance.getTime());
        userTenantAlbumRecordMapper.insert(userTenantAlbumRecord);
    }
}