package com.ym.mec.biz.service.impl;

import com.ym.mec.auth.api.client.SysUserFeignService;
import com.ym.mec.auth.api.entity.SysUser;
import com.ym.mec.biz.dal.dao.*;
import com.ym.mec.biz.dal.entity.*;
import com.ym.mec.biz.dal.enums.*;
import com.ym.mec.biz.dal.page.SporadicChargeInfoQueryInfo;
import com.ym.mec.biz.service.*;
import com.ym.mec.common.dal.BaseDAO;
import com.ym.mec.common.exception.BizException;
import com.ym.mec.common.page.PageInfo;
import com.ym.mec.common.service.impl.BaseServiceImpl;
import com.ym.mec.thirdparty.message.MessageSenderPluginContext;
import com.ym.mec.util.collection.MapUtil;
import org.apache.commons.lang3.StringUtils;
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.Propagation;
import org.springframework.transaction.annotation.Transactional;

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

@Service
public class SporadicChargeInfoImpl extends BaseServiceImpl<Integer, SporadicChargeInfo> implements SporadicChargeInfoService {

    @Autowired
    private SporadicChargeInfoDao sporadicChargeInfoDao;
    @Autowired
    private StudentPaymentOrderDao studentPaymentOrderDao;
    @Autowired
    private SysUserFeignService sysUserFeignService;
    @Autowired
    private SysMessageService sysMessageService;
    @Autowired
    private OrganizationDao organizationDao;
    @Autowired
    private TeacherDao teacherDao;
    @Autowired
    private MusicGroupDao musicGroupDao;
    @Autowired
    private SysUserCashAccountService sysUserCashAccountService;
    @Autowired
    private SysUserCashAccountDetailService sysUserCashAccountDetailService;
    @Autowired
    private DegreeRegistrationService degreeRegistrationService;
    @Autowired
    private ContractService contractService;
    @Autowired
    private LuckDrawCountService luckDrawCountService;

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Override
    public BaseDAO<Integer, SporadicChargeInfo> getDAO() {
        return sporadicChargeInfoDao;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Boolean renewForCallback(StudentPaymentOrder studentPaymentOrder) throws Exception {
        int updateCount = studentPaymentOrderDao.update(studentPaymentOrder);
        if (updateCount <= 0) {
            throw new BizException("订单更新失败");
        }
        Integer userId = studentPaymentOrder.getUserId();
        SysUser sysUser = sysUserFeignService.queryUserById(userId);
        SporadicChargeInfo info = sporadicChargeInfoDao.get(Integer.parseInt(studentPaymentOrder.getMusicGroupId()));

        Map<Integer, String> map = new HashMap<>();
        map.put(userId, sysUser.getPhone());
        Map<Integer, String> yimei = new HashMap<>();
        map.put(userId, userId.toString());
        if (studentPaymentOrder.getStatus() == DealStatusEnum.SUCCESS) {
            try {
                contractService.transferProduceContract(userId, null);
            } catch (Exception e) {
                logger.error("产品协议生成失败", e);
            }

            //福袋活动，增加课程余额
            if (info.getChargeType().getCode() == 6 || info.getChargeType().getCode() == 12) {
                if (info.getMaxAmount() != null) {
                    List<SporadicChargeInfo> activeInfos = sporadicChargeInfoDao.getOrganActiveInfo(info.getOrganId(), 12);
                    for (SporadicChargeInfo activeInfo : activeInfos) {
                        activeInfo.setPaidAmount(activeInfo.getPaidAmount().add(studentPaymentOrder.getActualAmount()));
                        activeInfo.setUpdateTime(new Date());
                        int update = sporadicChargeInfoDao.update(activeInfo);
                        if (update <= 0) {
                            throw new BizException("已收金额更新失败，请重试");
                        }
                    }
                }
                //第二单起每买一单增加一次抽奖机会
                int times = studentPaymentOrderDao.getUserOrderNumByType(userId, OrderTypeEnum.DOUBLE_ELEVEN2020);
                int num = studentPaymentOrder.getClassGroupId() == null ? 1 : studentPaymentOrder.getClassGroupId();
                if (times <= 1) {
                    num--;
                }
                if (num > 0) {
                    if (!luckDrawCountService.updateTimes(userId.longValue(), num)) {
                        throw new BizException("给用户增加抽奖次数失败");
                    }
                }
                boolean appendCourseBalance = sysUserCashAccountService.appendCourseBalance(userId, studentPaymentOrder.getActualAmount(), PlatformCashAccountDetailTypeEnum.SPORADIC, "双11活动");
                if (!appendCourseBalance) {
                    throw new BizException("增加用户课程余额失败");
                }
            } else if (info.getChargeType().getCode() == 9 || info.getChargeType().getCode() == 13) { //零星收费账户充值,网基课活动
                sysUserCashAccountService.updateBalance(userId, studentPaymentOrder.getActualAmount(), PlatformCashAccountDetailTypeEnum.RECHARGE, "零星收费"+info.getChargeType().getMsg(), studentPaymentOrder.getTransNo());
            } else if (info.getOrganId().equals(42) && info.getChargeType().equals(SporadicChargeTypeEnum.LEVEL)) {
                degreeRegistrationService.updateStatus(studentPaymentOrder);
                return true;
            } else {
                //插入交易明细
                BigDecimal amount = studentPaymentOrder.getActualAmount();
                Date nowDate = new Date();
                SysUserCashAccount cashAccount = sysUserCashAccountService.get(userId);
                //充值
                SysUserCashAccountDetail rechargeDetail = new SysUserCashAccountDetail();
                rechargeDetail.setAmount(amount);
                rechargeDetail.setBalance(cashAccount.getBalance().add(amount));
                rechargeDetail.setComment("缴费前充值");
                rechargeDetail.setCreateTime(nowDate);
                rechargeDetail.setStatus(DealStatusEnum.SUCCESS);
                rechargeDetail.setTransNo(studentPaymentOrder.getTransNo());
                rechargeDetail.setType(PlatformCashAccountDetailTypeEnum.RECHARGE);
                rechargeDetail.setUpdateTime(nowDate);
                rechargeDetail.setUserId(userId);
                rechargeDetail.setChannel(studentPaymentOrder.getPaymentChannel());
                rechargeDetail.setComAmount(studentPaymentOrder.getComAmount());
                rechargeDetail.setPerAmount(studentPaymentOrder.getPerAmount());
                sysUserCashAccountDetailService.insert(rechargeDetail);

                //缴费
                SysUserCashAccountDetail paymentDetail = new SysUserCashAccountDetail();
                paymentDetail.setAmount(amount.negate());
                paymentDetail.setBalance(cashAccount.getBalance());
                paymentDetail.setComment(info.getTitle());
                paymentDetail.setCreateTime(nowDate);
                paymentDetail.setStatus(DealStatusEnum.SUCCESS);
                paymentDetail.setTransNo(studentPaymentOrder.getTransNo());
                paymentDetail.setType(PlatformCashAccountDetailTypeEnum.PAY_FEE);
                paymentDetail.setUpdateTime(nowDate);
                paymentDetail.setUserId(userId);
                rechargeDetail.setChannel(studentPaymentOrder.getPaymentChannel());
                if (studentPaymentOrder.getComAmount() != null) {
                    rechargeDetail.setComAmount(studentPaymentOrder.getComAmount().negate());
                    rechargeDetail.setPerAmount(studentPaymentOrder.getPerAmount().negate());
                }

                sysUserCashAccountDetailService.insert(paymentDetail);
            }

            sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG, MessageTypeEnum.SMS_SPORADIC_PAYMENT_SUCCESS, map, null, 0, "1", "STUDENT",
                    studentPaymentOrder.getActualAmount(), info.getTitle());
            sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.AWSMS, MessageTypeEnum.SMS_SPORADIC_PAYMENT_SUCCESS, yimei, null, 0, "1", "",
                    studentPaymentOrder.getActualAmount(), info.getTitle());
            return true;
        }
        if (studentPaymentOrder.getStatus() == DealStatusEnum.CLOSE || studentPaymentOrder.getStatus() == DealStatusEnum.FAILED) {
            if (info.getOrganId().equals(42) && info.getChargeType().equals(SporadicChargeTypeEnum.LEVEL)) {
                degreeRegistrationService.updateStatus(studentPaymentOrder);
                return true;
            }

            if (studentPaymentOrder.getBalancePaymentAmount() != null && studentPaymentOrder.getBalancePaymentAmount().compareTo(BigDecimal.ZERO) > 0) {
                sysUserCashAccountService.updateBalance(studentPaymentOrder.getUserId(), studentPaymentOrder.getBalancePaymentAmount(), PlatformCashAccountDetailTypeEnum.REFUNDS, info.getTitle() + "支付失败");
            }

            sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG, MessageTypeEnum.SMS_SPORADIC_PAYMENT_FAILED, map, null, 0, "", "STUDENT",
                    studentPaymentOrder.getActualAmount(), info.getTitle());
            sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.AWSMS, MessageTypeEnum.SMS_SPORADIC_PAYMENT_FAILED, yimei, null, 0, "", "",
                    studentPaymentOrder.getActualAmount(), info.getTitle());
            return false;
        }
        return false;
    }

    @Override
    public PageInfo<SporadicChargeInfo> queryDetailPage(SporadicChargeInfoQueryInfo queryInfo) {
        PageInfo<SporadicChargeInfo> pageInfo = queryPage(queryInfo);
        List<SporadicChargeInfo> rows = pageInfo.getRows();
        if (rows != null && rows.size() > 0) {
            if (queryInfo.getIsExport() && rows.size() > 50000) {
                throw new BizException("数据集太大，不能导出.最大数据集不能超过50000");
            }
            Set<Integer> organIds = rows.stream().map(e -> e.getOrganId()).collect(Collectors.toSet());
            List<Integer> userIds = rows.stream().map(e -> e.getUserId()).collect(Collectors.toList());
            if (userIds == null) {
                userIds = new ArrayList<>();
            }
            Set<Integer> operatorIds = rows.stream().map(e -> e.getOperatorId()).collect(Collectors.toSet());
            Map<Integer, String> organNames = MapUtil.convertMybatisMap(organizationDao.findOrganNameMapList(organIds));
            Map<Integer, String> operatorNames = MapUtil.convertMybatisMap(teacherDao.queryNameByIds(StringUtils.join(operatorIds, ",")));
            Map<Integer, String> userNames = MapUtil.convertMybatisMap(teacherDao.queryUsernameByIds(userIds));
            rows.forEach(e -> {
                e.setOrganName(organNames.get(e.getOrganId()));
                if (e.getUserId() != null) {
                    e.setUserName(userNames.get(e.getUserId()));
                }
                e.setOperatorName(operatorNames.get(e.getOperatorId()));
            });
        }
        return pageInfo;
    }

    @Override
    public SporadicChargeInfo getDetail(Integer id) {
        SporadicChargeInfo sporadicChargeInfo = sporadicChargeInfoDao.get(id);
        if (sporadicChargeInfo.getUserId() != null) {
            SysUser sysUser = sysUserFeignService.queryUserById(sporadicChargeInfo.getUserId());
            sporadicChargeInfo.setUserName(sysUser.getUsername());
        }
        return sporadicChargeInfo;
    }

    @Override
    public SporadicChargeInfo findByOrganIdAndType(Integer organId, Integer type) {
        return sporadicChargeInfoDao.findByOrganIdAndType(organId, type);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateOpenFlag(Integer sporadicId, Integer openFlag) {
        SporadicChargeInfo sporadicChargeInfo = sporadicChargeInfoDao.get(sporadicId);
        sporadicChargeInfo.setOpenFlag(openFlag);
        sporadicChargeInfo.setUpdateTime(new Date());
        sporadicChargeInfoDao.update(sporadicChargeInfo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void del(Integer id) {
        Integer count = studentPaymentOrderDao.countSporadicOrder(id);
        if (count == null || count == 0) {
            sporadicChargeInfoDao.delete(id);
        } else {
            throw new BizException("当前缴费项目存在收费记录，请走关闭流程");
        }
    }

    @Override
    public SporadicChargeInfo findDetail(Integer id, Integer userId) {
        if (userId == null) {
            SysUser sysUser = sysUserFeignService.queryUserInfo();
            if (sysUser == null || sysUser.getId() == null) {
                throw new BizException("用户不存在");
            }
            userId = sysUser.getId();
        }
        SporadicChargeInfo chargeInfo = sporadicChargeInfoDao.get(id);
        MusicGroup musicGroup = musicGroupDao.get(chargeInfo.getMusicGroupId());
        if (musicGroup != null) {
            chargeInfo.setMusicGroupName(musicGroup.getName());
        }
        if (chargeInfo != null) {
            SysUserCashAccount locked = sysUserCashAccountService.getLocked(userId);
            chargeInfo.setBalance(locked.getBalance());
        } else {
            throw new BizException("信息不存在");
        }
        return chargeInfo;
    }

    @Override
    public List<SporadicChargeInfo> getOrganActiveInfo(Integer organId, Integer type) {
        return sporadicChargeInfoDao.getOrganActiveInfo(organId, type);
    }
}
