package com.ruoyi.voluntary.service.impl;

import java.util.*;
import java.util.stream.Collectors;

import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.enums.RoleType;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.voluntary.domain.*;
import com.ruoyi.voluntary.mapper.BusiClassesMapper;
import com.ruoyi.voluntary.service.ISysLocationsService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.compress.utils.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.enums.BoolValues;
import com.ruoyi.common.enums.CardStatus;
import com.ruoyi.common.enums.CardType;
import com.ruoyi.common.exception.base.BaseException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.NumberUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.mapper.SysUserMapper;
import com.ruoyi.voluntary.mapper.BusiAgentsMapper;
import com.ruoyi.voluntary.mapper.BusiCardsMapper;
import com.ruoyi.voluntary.service.IBusiCardsOpenDetailService;
import com.ruoyi.voluntary.service.IBusiCardsOpenService;
import com.ruoyi.voluntary.service.IBusiCardsService;

/**
 * vip卡Service业务层处理
 *
 * @author voluntary
 * @date 2022-11-20
 */
@Service
public class BusiCardsServiceImpl implements IBusiCardsService {
    protected static final Logger log = LoggerFactory.getLogger(BusiCardsServiceImpl.class);

    @Autowired
    private BusiCardsMapper busiCardsMapper;
    @Autowired
    private ISysUserService userService;

    @Autowired
    private BusiClassesMapper busiClassesMapper;
    @Autowired
    private BusiAgentsMapper busiAgentsMapper;

    @Autowired
    private IBusiCardsOpenService cardsOpenService;

    @Autowired
    private IBusiCardsOpenDetailService cardsOpenDetailService;

    @Autowired
    private SysUserMapper userMapper;

    @Autowired
    private ISysLocationsService sysLocationsService;

    /**
     * 查询vip卡
     *
     * @param cardId vip卡主键
     * @return vip卡
     */
    @Override
    public BusiCards selectBusiCardsByCardId(Long cardId) {
        return busiCardsMapper.selectBusiCardsByCardId(cardId);
    }

    /**
     * 查询vip卡列表
     *
     * @param busiCards vip卡
     * @return vip卡
     */
    @Override
    public List<BusiCards> selectBusiCardsList(BusiCards busiCards) {
        return busiCardsMapper.selectBusiCardsList(busiCards);
    }

    @Override
    public BusiCards selectBusiCardsByCardNo(String cardNo) {
        return busiCardsMapper.selectBusiCardsByCardNo(cardNo);
    }

    @Override
    public BusiCards selectOneECard() {
        return busiCardsMapper.selectOneECard();
    }

    @Override
    public List<BusiCards> selectBusiCardsByCardNos(List<String> cardNos) {
        return busiCardsMapper.selectBusiCardsByCardNos(cardNos);
    }

    /**
     * 新增vip卡
     *
     * @param busiCards vip卡
     * @return 结果
     */
    @Override
    public int insertBusiCards(BusiCards busiCards) {
        busiCards.setCreateTime(DateUtils.getNowDate());
        return busiCardsMapper.insertBusiCards(busiCards);
    }

    /**
     * 修改vip卡
     *
     * @param busiCards vip卡
     * @return 结果
     */
    @Override
    @Transactional
    public int updateBusiCards(BusiCards busiCards) {
        SysUser user = userMapper.selectUserByCardId(busiCards.getCardId());
        busiCards.setNickName(busiCards.getName());
        if (null != user && null != busiCards.getMobile()) {
            // 校验手机号是否唯一
            SysUser checkUser = new SysUser(user.getUserId(), busiCards.getMobile());
            if (StringUtils.isNotEmpty(busiCards.getMobile()) && UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(checkUser))) {
                throw new BaseException("手机号码[" + busiCards.getMobile() + "]已存在");
            }
        }
        if (null != busiCards.getEndYear()) {
            busiCards.setYear(busiCards.getEndYear() - 3);
        }
        Long gradeId = null;
        if (null != busiCards.getClassId()) {
            BusiClasses classes = busiClassesMapper.selectBusiClassesByClassId(busiCards.getClassId());
            if (null != classes) {
                gradeId = classes.getGradeId();
                busiCards.setGradeId(classes.getGradeId());
            }
        }
        busiCards.setUpdateTime(DateUtils.getNowDate());
        int res = busiCardsMapper.updateBusiCards(busiCards);
        SysUser updateUser = null;
        if (null != user && StringUtils.isNotBlank(busiCards.getPassword())) {
            // 修改密码
            updateUser = new SysUser();
            updateUser.setUserId(user.getUserId());
            String pwd = StringUtils.trimToEmpty(busiCards.getPassword());
            updateUser.setPassword(SecurityUtils.encryptPassword(pwd));
            updateUser.setPassword2(pwd);
            updateUser.setUpdateBy(SecurityUtils.getLoginUser().getUsername());
            userMapper.updateUser(updateUser);
        } else if (null != user && null != user.getUserId()) {
            updateUser = new SysUser();
            updateUser.setUserId(user.getUserId());
            updateUser.setNickName(busiCards.getName());
            updateUser.setPhonenumber(busiCards.getMobile());
            updateUser.setGroupId(busiCards.getGroupId());
            updateUser.setScore(busiCards.getScore());

            updateUser.setSchoolId(busiCards.getSchoolId());
            updateUser.setGradeId(gradeId);
            updateUser.setClassId(busiCards.getClassId());

            updateUser.setYear(busiCards.getYear());

            updateUser.setUpdateBy(SecurityUtils.getLoginUser().getUsername());
        }
        if (null != updateUser) {
            userMapper.updateUser(updateUser);
        }
        return res;
    }

    /**
     * 批量删除vip卡
     *
     * @param cardIds 需要删除的vip卡主键
     * @return 结果
     */
    @Override
    public int deleteBusiCardsByCardIds(Long[] cardIds) {
        return busiCardsMapper.deleteBusiCardsByCardIds(cardIds);
    }

    /**
     * 删除vip卡信息
     *
     * @param cardId vip卡主键
     * @return 结果
     */
    @Override
    public int deleteBusiCardsByCardId(Long cardId) {
        return busiCardsMapper.deleteBusiCardsByCardId(cardId);
    }

    @Override
    @Transactional(rollbackFor = {Exception.class, BaseException.class})
    public List<BusiCards> createCard(BusiCards busiCards) {
        try {
            // 类型
            int cardsType = busiCards.getType();
            // 卡数
            int cardNum = busiCards.getCardNum();
            if (0 >= cardNum || 10000 < cardNum) {
                throw new BaseException("卡数量在1到10000之间");
            }

            // 获取卡前缀最大数量
            int max = busiCardsMapper.getMaxCardNo(cardsType);
            int len = Constants.FRONT_CARD_LENGTH;
            if (CardType.isTestCard(cardsType)) {
                len = Constants.FRONT_TEST_CARD_LENGTH;
                max = max == 0 ? 800001 : max + 1;
            } else if (CardType.isECard(cardsType)) {
                // 电子卡8位，0开头
                max = max == 0 ? 00000001 : max + 1;
            } else if (CardType.isVipCard(cardsType)) {
                // VIP卡8位，1开头
                max = max == 0 ? Integer.parseInt(CardType.vipCard.getValue()+"0000001") : max + 1;
            } else if (CardType.isExperienceCard(cardsType)) {
                // 体验卡8位，9开头
                max = max == 0 ? 90000001 : max + 1;
            }

            List<BusiCards> cards = new ArrayList<>();
            Date now = new Date();
            for (int list = cardNum - 1; list >= 0; list--) {
                String cardNo = StringUtils.leftPad(String.valueOf(max), len, '0');

                // 密码使用8位数字
                String password = NumberUtils.getRandom(Constants.FRONT_CARD_PASSWORD_LENGTH);
                BusiCards bc = new BusiCards();
                bc.setCardNo(cardNo);
                bc.setPassword(password);
                bc.setType(cardsType);
                bc.setStatus(CardStatus.undistributed.getValue());
                bc.setIsPay(BoolValues.no.getValue());
                bc.setIsRefund(BoolValues.no.getValue());
                bc.setIsSettlement(BoolValues.no.getValue());
                bc.setIsUsed(BoolValues.no.getValue());
                bc.setCreateTime(now);
                bc.setUpdateTime(now);
                cards.add(bc);
                max++;
            }

            int flag = busiCardsMapper.insertBatchCardList(cards);
            if (flag != cards.size()) {
                throw new BaseException("添加失败");
            }
            return cards;
        } catch (BaseException be) {
            throw be;
        } catch (Exception e) {
            e.printStackTrace();
            throw new BaseException("添加异常");
        }

    }

    /**
     * 批量更新卡状态 定时任务更新为过期卡
     *
     * @param status
     */
    @Override
    @Transactional
    public int updateBusiCardsBatch(Integer status) {
        /**
         * 0未分配，1已分配，2已激活，9已过期 对于激活卡及缴费卡如果outTime小于当前时间就设置为过期卡
         */
        if (null == status) {
            status = CardStatus.expired.getValue();
        }
        BusiCards query = new BusiCards();
        query.setEndOutTime(DateUtils.getDate());
        // 查询过期卡（status：0未分配，1已分配，2已激活，9已过期，10已关卡）
        List<BusiCards> busiCardsList = busiCardsMapper.selectBusiOutTimeCardsList(query);
        //已关闭卡
        busiCardsList.addAll(busiCardsMapper.selectBusiCardsClosed());
        if (CollectionUtils.isEmpty(busiCardsList)) {
            return 0;
        }
        for (BusiCards ll : busiCardsList) {
            ll.setStatus(status);
        }
        log.error("定时任务批量，更新（2激活卡）的状态为（9过期卡）：{}",
            JSONObject.toJSONString(busiCardsList.stream().map(BusiCards::getCardNo).collect(Collectors.toList())));
        int count = 0;
        if (busiCardsList.size() <= 500) {
            // 更新卡状态
            busiCardsMapper.updateBusiCardsBatch(busiCardsList);
            count += busiCardsList.size();
        } else {
            // 每500张更新一次
            List<BusiCards> cardsList = new ArrayList<>();
            for (BusiCards busiCards : busiCardsList) {
                cardsList.add(busiCards);
                if (cardsList.size() >= 500) {
                    // 更新卡状态
                    busiCardsMapper.updateBusiCardsBatch(cardsList);
                    count += cardsList.size();
                    cardsList.clear();
                }
            }

            if (cardsList.size() > 0) {
                // 更新卡状态
                busiCardsMapper.updateBusiCardsBatch(cardsList);
                count += cardsList.size();
                cardsList.clear();
            }
        }

        //更新用户角色为普通用户
        Long[] roleIds = new Long[]{RoleType.frontCommon.getValue()};
        List<String> cardNos = busiCardsList.stream().map(BusiCards::getCardNo).collect(Collectors.toList());
        Map<Long,Long[]> userMap = new HashMap<>();
        List<SysUser> sysUsersList = userService.selectBatchUserByUserName(cardNos);
        sysUsersList.stream().forEach(user -> {
            user.setIsBind(BoolValues.no.getValue());
            user.setCurrentRoleId(RoleType.frontCommon.getValue());
            userMap.put(user.getUserId(),roleIds);
        });
        //更新isBind
        userService.batchUpdateUser(sysUsersList);
        //更新用户角色
        userService.updateUserRoleBatch(userMap);

        return count;

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String distributionCard(BusiCards reqCard) {
        try {
            // 校验卡学年
            if (null != reqCard.getYear()) {
                int validYear = DateUtils.getCurrentYear() - 5;
                if (reqCard.getYear() < validYear) {
                    throw new BaseException("学年不能小于" + validYear);
                }
            }
            // 获取分配卡数量
            if (null == reqCard.getType()) {
                throw new BaseException("卡类型参数不能为空");
            }

            if (StringUtils.isBlank(reqCard.getStartCard())) {
                throw new BaseException("起始账号不存在");
            }
            if (StringUtils.isBlank(reqCard.getEndCard())) {
                throw new BaseException("截止账号不存在");
            }
            if (reqCard.getEndCard().length() != reqCard.getStartCard().length()) {
                throw new BaseException("开始截至卡号长度不一致");
            }

            if (!CardType.isMatchCardNo2Type(reqCard.getStartCard(), reqCard.getType())
                || !CardType.isMatchCardNo2Type(reqCard.getEndCard(), reqCard.getType())) {
                // throw new BaseException("卡号与类型不匹配");
            }

            int len = (int)(Long.valueOf(reqCard.getEndCard()) - Long.valueOf(reqCard.getStartCard()));
            if (len < 0) {
                throw new BaseException("起始卡号不能大于截止卡号");
            }

            // 存在相等的情况， 所以需要加一
            len++;

            // status <=1
            List<BusiCards> cards =
                busiCardsMapper.getIdsByCardAndRole(reqCard.getStartCard(), reqCard.getEndCard(), 1, reqCard.getAgainDistributionCard());

            if (CollectionUtils.isNotEmpty(cards)) {
                Date now = new Date();
                // 获取代理商信息
                BusiAgents busiAgent = busiAgentsMapper.selectBusiAgentsByAgentId(reqCard.getAgentId());
                if (null == busiAgent) {
                    // throw new BaseException("代理商不存在");
                }
                List<BusiCards> busiCardsList = Lists.newArrayList();
                List<String> cardNoList = new ArrayList<>();
                List<String> alreadyCardNoList = new ArrayList<>();
                BusiCardsOpen cardsOpen = new BusiCardsOpen();
                cardsOpen.setCardType(reqCard.getType());
                cardsOpen.setStartNo(reqCard.getStartCard());
                cardsOpen.setEndNo(reqCard.getEndCard());
                cardsOpen.setSender(String.valueOf(reqCard.getAgentId()));
                Integer againDistributionCard = null == reqCard.getAgainDistributionCard() ? 0 : reqCard.getAgainDistributionCard();
                cardsOpen.setIsReopen(againDistributionCard);
                cardsOpen.setCreateTime(new Date());
                cardsOpen.setSchoolId(reqCard.getDistributeSchoolId());
                cardsOpen.setYear(String.valueOf(reqCard.getYear()));
                cardsOpenService.insertBusiCardsOpen(cardsOpen);
                Long cardOpenId = cardsOpen.getId();

                List<BusiCardsOpenDetail> busiCardsOpenDetailList = Lists.newArrayList();
                for (BusiCards updateCard : cards) {
                    // 20210924：莫-徐确认，对于已注册的卡不能重新分配
                    // 0未分配，1已分配，2已激活，9失效卡
                    if (null != updateCard.getStatus() && updateCard.getStatus() >= CardStatus.actived.getValue()) {
                        alreadyCardNoList.add(updateCard.getCardNo());
                        continue;
                    }
                    if (BoolValues.isFalse(againDistributionCard)) {
                        if (CardStatus.isDistributed(updateCard.getStatus())) {
                            alreadyCardNoList.add(updateCard.getCardNo());
                            continue;
                        }
                    }
                    updateCard.setOpenId(cardOpenId);
                    updateCard.setDistributeTime(now);
                    updateCard.setStatus(CardStatus.distributed.getValue());
                    updateCard.setUpdateTime(now);
                    updateCard.setYear(reqCard.getYear());
                    updateCard.setAgentId(busiAgent.getAgentId());
                    // 卡分配学校，用于结算
                    if (null != reqCard.getDistributeProvinceId() && reqCard.getDistributeProvinceId() > 0) {
                        updateCard.setDistributeLocation(sysLocationsService.getNameByLocationId(reqCard.getDistributeProvinceId().longValue()));
                    } else {
                        updateCard.setDistributeLocation("");
                    }
                    updateCard.setDistributeSchoolId(reqCard.getDistributeSchoolId());
                    if (StringUtils.isNotBlank(updateCard.getDistributeLocation())) {
                        updateCard.setDistributeType(null != reqCard.getDistributeSchoolId() && reqCard.getDistributeSchoolId() > 0 ? 2 : 1);
                    } else {
                        updateCard.setDistributeType(0);
                    }
                    if (StringUtils.isNotBlank(reqCard.getDistributeExamType())) {
                        updateCard.setDistributeExamType(reqCard.getDistributeExamType());
                        updateCard.setDistributeType(3);
                    }
                    cardNoList.add(updateCard.getCardNo());
                    busiCardsList.add(updateCard);
                    // 卡分配详情
                    BusiCardsOpenDetail busiCardsOpenDetail = new BusiCardsOpenDetail();
                    busiCardsOpenDetail.setCardNo(updateCard.getCardNo());
                    busiCardsOpenDetail.setOpenId(cardOpenId);
                    busiCardsOpenDetail.setCreateTime(now);
                    busiCardsOpenDetailList.add(busiCardsOpenDetail);

                    if (busiCardsList.size() == 500) {
                        // 更新卡状态
                        busiCardsMapper.updateBusiCardsBatch(busiCardsList);
                        busiCardsList.clear();
                    }
                    if (busiCardsOpenDetailList.size() == 500) {
                        // 分配详情
                        cardsOpenDetailService.insertBatch(busiCardsOpenDetailList);
                        busiCardsOpenDetailList.clear();
                    }
                }
                if (busiCardsList.size() > 0) {
                    // 更新卡状态
                    busiCardsMapper.updateBusiCardsBatch(busiCardsList);
                    busiCardsList.clear();
                }
                if (busiCardsOpenDetailList.size() > 0) {
                    // 分配详情
                    cardsOpenDetailService.insertBatch(busiCardsOpenDetailList);
                    busiCardsOpenDetailList.clear();
                }
                if (CollectionUtils.isNotEmpty(cardNoList)) {
                    return "分配卡：" + StringUtils.join(cardNoList, ",");
                    // +"\n"+"已分配卡："+
                    // StringUtils.join(alreadyCardNoList, ",");
                }
            }

            throw new BaseException("卡号已全部分配");
        } catch (BaseException be) {
            throw be;
        } catch (Exception e) {
            e.printStackTrace();
            throw new BaseException("分配异常");
        }
    }

    @Override
    public Integer batch(JSONObject data) {
        String cmd = data.getString("command");
        List<Long> cardIds = data.getJSONArray("cardIds").toJavaList(Long.class);
        BusiCards update = new BusiCards().setCardIds(cardIds);
        switch (cmd.toLowerCase()) {
            case "pay":// 缴费
                // update.setIsRefund(Integer.valueOf(0));//
                update.setIsPay(Integer.valueOf(1));// 是否付费
                update.setPayStatus(Integer.valueOf(1));// 缴费状态
                update.setPayTime(new Date());// 缴费时间
                // update.setStatus(CardStatus.actived.getValue());// 已激活
                // 体验卡、测试卡、电子卡不能操作缴费
                update.getParams().put("custWhere", " and type not in (0,8,9) ");
                break;
            case "close":// 关卡
                update.setStatus(CardStatus.closed.getValue());// 已关卡
                update.setCloseTime(new Date());// 关卡时间
                // 卡关闭前，保存状态A，
                update.getParams().put("custSet", " tmp_status = status ");
                // 已缴费不能关卡，已关卡的也不能再次操作关卡
                update.getParams().put("custWhere", " and pay_status <> 1 and status <> " + CardStatus.closed.getValue());
                break;
            case "reopen":// 重开
                // update.setStatus(CardStatus.actived.getValue());// 已激活
                update.setDistributeTime(new Date());// 开卡时间
                // 关卡(已关卡)重开后，恢复成原有状态A
                update.getParams().put("custSet", " status = tmp_status ");
                // 已关卡,才可以重开
                update.getParams().put("custWhere", " and status = " + CardStatus.closed.getValue());
                break;
            case "delay":// 续期
                Integer days = data.getInteger("days");
                update.setDays(days);// 在过期日期上增加续期天数
//                update.setOutDate(DateUtils.addDays(new Date(), days - 1));// 到期时间，此处时间错误，应该是以当前时间与过期时间中大的时间为基准朝后面增加
                update.setStatus(CardStatus.actived.getValue());// 已激活
                int count = busiCardsMapper.batchUpdate(update);
                //续期后，更新用户isBind=1,用户角色为前端VIP RoleType.frontVip=4
                userService.selectBatchUserByCardId(cardIds).forEach(user -> {
                    if(BoolValues.isTrue(user.getIsBind())||RoleType.isFrontVip( user.getCurrentRoleId())){
                        //已经绑定或为前端VIP的不需要重新更新
                        return;
                    }
                    user.setIsBind(BoolValues.yes.getValue());
                    user.setCurrentRoleId(RoleType.frontVip.getValue());
                    Long[] roleIds = new Long[]{RoleType.frontVip.getValue()};
                    user.setRoleIds(roleIds);
                    userService.updateUser(user);
                });

                return count;
            case "refund":// 退费
                update.setIsRefund(Integer.valueOf(1));//
                update.setPayStatus(Integer.valueOf(2));// 缴费状态
                update.setRefundTime(new Date());
                // update.setStatus(CardStatus.distributed.getValue());// 已分配
                update.getParams().put("custWhere", " and pay_status = 1 ");
                break;
            default:
                return Integer.valueOf(0);
        }
        return busiCardsMapper.batchUpdate(update);
    }

    @Override
    @SuppressWarnings("rawtypes")
    public List<Map> staticByAgent(BusiCards card) {
        return busiCardsMapper.staticByAgent(card);
    }

    @Override
    public List<BusiCards> selectBusiCardsClosed() {
        return busiCardsMapper.selectBusiCardsClosed();
    }

}
