package com.willalp.integral.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.willalp.common.core.domain.ReturnEntity;
import com.willalp.common.core.domain.entity.SysDictData;
import com.willalp.common.core.domain.entity.SysUser;
import com.willalp.common.enums.RechargeEnum;
import com.willalp.common.enums.RechargeTypeEnum;
import com.willalp.common.enums.ReturnEnum;
import com.willalp.common.exception.base.BaseException;
import com.willalp.common.utils.DateUtils;
import com.willalp.common.utils.ObjectToTypes;
import com.willalp.common.utils.SecurityUtils;
import com.willalp.common.utils.StringUtils;
import com.willalp.files.domain.HsOrgPersonnelFiles;
import com.willalp.files.mapper.HsOrgPersonnelFilesMapper;
import com.willalp.integral.domain.Integral;
import com.willalp.integral.domain.excelVo.IntegralVo;
import com.willalp.integral.domain.excelVo.IntegralVo2;
import com.willalp.integral.mapper.IntegralMapper;
import com.willalp.integral.request.IntegralGroupQuery;
import com.willalp.integral.service.IIntegralService;
import com.willalp.system.domain.SysCardInfo;
import com.willalp.system.domain.SysUserOrganization;
import com.willalp.system.mapper.SysCardInfoMapper;
import com.willalp.system.mapper.SysUserMapper;
import com.willalp.system.mapper.SysUserOrganizationMapper;
import com.willalp.system.service.ISysDictTypeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 积分管理Service业务层处理
 *
 * @author willalp
 * @date 2021-12-02
 */
@Service
public class IntegralServiceImpl extends ServiceImpl<IntegralMapper, Integral> implements IIntegralService {
    @Autowired
    private IntegralMapper integralMapper;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private SysCardInfoMapper sysCardInfoMapper;

    @Autowired
    private SysUserOrganizationMapper sysUserOrganizationMapper;

    @Resource
    private HsOrgPersonnelFilesMapper opFilesMapper;


    /**
     * 查询积分管理列表
     *
     * @param integral 积分管理
     * @return 积分管理
     */
    @Override
    public List<Integral> selectIntegralList(Integral integral) {
        return integralMapper.selectIntegralList(integral);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int saveInfo(Integral integral) {
        List<SysUserOrganization> list = sysUserOrganizationMapper.queryOrganizationByLoginName(SecurityUtils.getUsername());
        if (!list.isEmpty()) {
            list = list.stream().filter(e -> e.getIsDefault() != null && e.getIsDefault() == 1).collect(Collectors.toList());
            if (!list.isEmpty()) {
                integral.setOrganizationCode(list.get(0).getOrganizationCode());
            }
        }
        SysCardInfo cardInfo = new SysCardInfo();
        cardInfo.setUserId(integral.getLoginName());
        List<SysCardInfo> cardInfoList = sysCardInfoMapper.selectSysCardInfoList(cardInfo);
        if (!cardInfoList.isEmpty()) {
            integral.setCardNumber(cardInfoList.get(0).getCardCode());
            integral.setCardName(cardInfoList.get(0).getCardUsername());
        }

        while (true) {
            String idStr = IdWorker.getIdStr();
            Integral byId = integralMapper.selectById(idStr);
            if (null == byId) {
                integral.setId(idStr);
                break;
            }
        }
        integral.setIsDelete(0);
        integral.setRechargeTime(DateUtils.getNowDate());
        integral.setRechargeId(SecurityUtils.getLoginUser().getUserId());
        //账户
        SysUserOrganization organization = new SysUserOrganization();
        organization.setLoginName(integral.getLoginName());
        organization.setOrganizationCode(integral.getOrganizationCode());
        List<SysUserOrganization> organs = sysUserOrganizationMapper.selectSysUserOrganizationList(organization);
        if (organs.size() > 0) {
            organization = organs.get(0);
        } else {
            throw new BaseException("当前用户不存在机构权限");
        }
        //账户增加余额
        if (integral.getMoneyType() == Integer.valueOf(RechargeEnum.ORGANRECHARGE.getValue())
                || integral.getMoneyType() == Integer.valueOf(RechargeEnum.PERSONRECHARGE.getValue())) {
            organization.setIntegral(organization.getIntegral().add(integral.getRechargeIntegral()));
        } else if (integral.getMoneyType() == Integer.valueOf(RechargeEnum.KEEPRECHARGE.getValue())) {//记账
            organization.setQuota(organization.getQuota().add(integral.getRechargeIntegral()));
        } else if (integral.getMoneyType() == Integer.valueOf(RechargeEnum.DEPOSITRECHARGE.getValue())) {//押金
            organization.setDeposit(organization.getDeposit().add(integral.getRechargeIntegral()));
        } else if (integral.getMoneyType() == Integer.valueOf(ReturnEnum.RETURN.getValue())) {//余额退还
            if (organization.getIntegral().compareTo(integral.getRechargeIntegral()) < 0) {
                throw new BaseException("余额不足");
            }
            organization.setIntegral(organization.getIntegral().subtract(integral.getRechargeIntegral()));
            integral.setRechargeIntegral(integral.getRechargeIntegral().negate());
        } else if (integral.getMoneyType() == Integer.valueOf(ReturnEnum.KEEPRETURN.getValue())) {//记账额度退还
            if (organization.getQuota().compareTo(integral.getRechargeIntegral()) < 0) {
                throw new BaseException("记账额度不足");
            }
            organization.setQuota(organization.getQuota().subtract(integral.getRechargeIntegral()));
            integral.setRechargeIntegral(integral.getRechargeIntegral().negate());
        } else if (integral.getMoneyType() == Integer.valueOf(ReturnEnum.DEPOSITRETURN.getValue())) {//押金
            if (organization.getDeposit().compareTo(integral.getRechargeIntegral()) < 0) {
                throw new BaseException("押金不足");
            }
            organization.setDeposit(organization.getDeposit().subtract(integral.getRechargeIntegral()));
            integral.setRechargeIntegral(integral.getRechargeIntegral().negate());
        } else if (integral.getMoneyType() == Integer.valueOf(ReturnEnum.RETURN.getValue())) {//因错退还

        }
        sysUserOrganizationMapper.updateById(organization);
        return integralMapper.insert(integral);
    }

    @Override
    public void returnPoints(List<IntegralGroupQuery> list) {
        List<String> depositList = list.stream().filter(e -> e.getMoneyType() == 1).map(o -> o.getLoginName()).collect(Collectors.toList());
        List<String> balanceList = list.stream().filter(e -> e.getMoneyType() == 2).map(o -> o.getLoginName()).collect(Collectors.toList());
        IntegralGroupQuery integralGroupQuery = new IntegralGroupQuery();
        List<Integral> returnList = new ArrayList<>();
        if (!depositList.isEmpty()) {
            integralGroupQuery.setLoginNameList(depositList);
            integralGroupQuery.setMoneyType(1);
            returnList.addAll(integralMapper.queryIntegralSum(integralGroupQuery));
        }
        if (!balanceList.isEmpty()) {
            integralGroupQuery.setLoginNameList(balanceList);
            integralGroupQuery.setMoneyType(2);
            returnList.addAll(integralMapper.queryIntegralSum(integralGroupQuery));
        }

        returnList.forEach(item -> {
            if (item.getMoneyType() != 1) {
                SysUserOrganization organization = new SysUserOrganization();
                organization.setLoginName(item.getLoginName());
                organization.setOrganizationCode(item.getOrganizationCode());
                List<SysUserOrganization> organs = sysUserOrganizationMapper.selectSysUserOrganizationList(organization);
                if (CollectionUtil.isNotEmpty(organs)) {
                    organization = organs.get(0);
                    if (organization.getIntegral().compareTo(item.getRechargeIntegral()) >= 0) {
                        organization.setIntegral(organization.getIntegral().subtract(item.getRechargeIntegral()));
                        sysUserOrganizationMapper.updateById(organization);
                    } else {
                        throw new BaseException(item.getNickName() + "积分余额不足,不能作废");
                    }
                } else {
                    throw new BaseException(item.getNickName() + "存在用户信息");
                }
            }
            while (true) {
                String idStr = IdWorker.getIdStr();
                Integral byId = integralMapper.selectById(idStr);
                if (null == byId) {
                    item.setId(idStr);
                    break;
                }
            }
            if (item.getMoneyType() != null && item.getMoneyType() != 1) {
                item.setMoneyType(RechargeTypeEnum.returnPoints.getCode());
            }
            item.setRechargeIntegral(item.getRechargeIntegral().multiply(new BigDecimal(-1)));
            item.setIsDelete(0);
            item.setRechargeTime(DateUtils.getNowDate());
            item.setRechargeId(SecurityUtils.getLoginUser().getUserId());
        });
        integralMapper.saveBatchIntegral(returnList);
    }

    @Override
    public String importData(List<Integral> list) {
        int successNum = 0;
        int failureNum = 0;
        StringBuilder failureMsg = new StringBuilder();
        for (Integral integral : list) {
            try {
                SysUser user = sysUserMapper.checkPhoneUnique(integral.getPhonenumber());
                if (user == null) {
                    failureNum++;
                    failureMsg.append(integral.getPhonenumber() + "不存在用户信息");
                    continue;
                }
                integral.setNickName(user.getNickName());
                integral.setLoginName(user.getUserName());
                integral.setMoneyType(RechargeTypeEnum.deposit.getCode());
                int count = saveInfo(integral);
                if (count > 0) {
                    successNum++;
                }
            } catch (Exception e) {
                failureNum++;
                log.error(e.getMessage(), e);
                failureMsg.append(e.getMessage());
            }
        }
        ReturnEntity<String> res = new ReturnEntity<>();
        if (failureNum > 0) {
            res.setReturnMessage("pns.integral.errorCode1", new String[]{
                    ObjectToTypes.parseString(failureNum), failureMsg.toString()
            });
        } else {
            res.setReturnMessage("pns.integral.successCode1", new String[]{
                    ObjectToTypes.parseString(successNum)
            });
        }
        return res.getMessage();
    }

    @Override
    public List<IntegralVo2> queryIntegralSum(IntegralGroupQuery integralGroupQuery) {
        return integralMapper.userBalances(integralGroupQuery);
    }

    @Override
    public List<Map<String, Object>> getIntegralReportList(Map<String, Object> req) {
        return integralMapper.getIntegralReportList(req);
    }

    @Resource
    private ISysDictTypeService dictTypeService;

    @Override
    public List<IntegralVo> rechargeTemplate() {
        List<HsOrgPersonnelFiles> hsOrgPersonnelFiles = opFilesMapper.templateHsOrgPersonnelFilesList();
        List<SysDictData> userTypes = dictTypeService.selectDictDataByType("user_type");
        List<IntegralVo> list = new ArrayList<>();
        if (0 != hsOrgPersonnelFiles.size()) {
            hsOrgPersonnelFiles.forEach(item -> {
                IntegralVo integral = new IntegralVo();
                integral.setNickName(item.getUserName());
                if (StringUtils.isNotBlank(item.getUserType())) {
                    SysDictData sysDictData = userTypes.get(Integer.parseInt(item.getUserType()) - 1);
                    if (sysDictData != null) {
                        integral.setUserType(sysDictData.getDictLabel());
                    } else {
                        integral.setUserType("未设置");
                    }
                }
                integral.setPhonenumber(item.getPhone());
                list.add(integral);
            });
        }
        return list;
    }
}
