package com.jeequan.jeepay.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.utils.JeepayKit;
import com.jeequan.jeepay.db.entity.MemberAccountHistory;
import com.jeequan.jeepay.db.entity.MemberInfo;
import com.jeequan.jeepay.db.entity.MemberRechargeRecord;
import com.jeequan.jeepay.service.mapper.MemberAccountHistoryMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.Map;

/**
 * <p>
 * 会员账户流水表 服务实现类
 * </p>
 *
 * @author [mybatis plus generator]
 * @since 2023-04-12
 */
@Slf4j
@Service
public class MemberAccountHistoryService extends ServiceImpl<MemberAccountHistoryMapper, MemberAccountHistory> {

    @Autowired private MemberInfoService memberInfoService;
    @Autowired private MemberAccountHistoryMapper memberAccountHistoryMapper;

    /**
     * 会员充值，更新会员余额  &&  记录流水
     * */
    @Transactional(rollbackFor = Exception.class)
    public Long updateMbrAccount4RechagreRecord(MemberRechargeRecord rechargeRecord) {
        return updateMbrAccountAndInsertHistory(rechargeRecord.getMchNo(), null, null, rechargeRecord.getMbrId(), rechargeRecord.getEntryAmount(),
                MemberAccountHistory.BIZ_RECHARGE_PAY, rechargeRecord.getRechargeRecordId(), null).getAfterAmount();
    }

    /**
     * 更新会员余额  &&  记录流水
     * changeAmount 为<正>表示增加余额，为<负>表示减少余额
     * */
    @Transactional(rollbackFor = Exception.class)
    public MemberAccountHistory updateMbrAccountAndInsertHistory(String mchNo, String storeId, Long qrcId, String mbrId, Long changeAmount,
                                                                 Byte bizType, String rechargeRecordId, String remark) {
        if (changeAmount == 0) {
            log.info("会员：{}，无金额变动", mbrId);
            return null;
        }

        MemberInfo memberInfo = memberInfoService.selectOne(mchNo, mbrId);
        if (memberInfo == null) {
            throw new BizException("会员不存在");
        }
        if (changeAmount < 0 && memberInfo.getBalance() < Math.abs(changeAmount)) {
            log.warn("会员：{}，余额不足, 余额={}，变动金额={}", mbrId, memberInfo.getBalance(), changeAmount);
            throw new BizException("余额不足");
        }

        // 更新余额
        MemberInfo updateAccount = new MemberInfo();
        updateAccount.setMchNo(mchNo);
        updateAccount.setMbrId(mbrId);
        updateAccount.setBalance(changeAmount);

        MemberInfo dbAccount = updateBalanceAndSafeKey(updateAccount);

        // 记录流水
        MemberAccountHistory history = new MemberAccountHistory();
        history.setMbrId(mbrId);
        history.setMbrName(memberInfo.getMbrName());
        history.setMbrTel(memberInfo.getMbrTel());
        history.setMchNo(mchNo);
        history.setStoreId(storeId);
        history.setQrcId(qrcId);
        history.setBeforeAmount(dbAccount.getBalance() - changeAmount);
        history.setChangeAmount(changeAmount);
        history.setAfterAmount(dbAccount.getBalance());
        history.setBizType(bizType);
        history.setRelaBizOrderId(rechargeRecordId);
        history.setRemark(remark);

        boolean result = this.save(history);
        if (!result) {
            throw new BizException(ApiCodeEnum.SYS_OPERATION_FAIL_UPDATE);
        }

        return history;
    }

    /**
     * 更新会员余额
     * */
    @Transactional(rollbackFor = Exception.class)
    public MemberInfo updateBalanceAndSafeKey(MemberInfo updateAccount) {
        String mbrId = updateAccount.getMbrId();

        MemberInfo memberInfo = memberInfoService.getById(mbrId);
        if( !JeepayKit.genAccountSafeKey(mbrId, memberInfo.getBalance()).equals(memberInfo.getSafeKey())){
            log.warn("【会员账户安全锁】校验失败,mbrId={}", mbrId);
            //安全机制码校验失败，无法继续操作
            throw new BizException("账户安全验证失败，请联系系统管理员");
        }

        //判断是否更新成功
        if(baseMapper.updateBalanceByMbrId(updateAccount) <= 0){
            //更新失败，触发事物回滚机制
            throw new BizException("更新会员账户金额有误");
        }

        memberInfo = memberInfoService.selectOne(updateAccount.getMchNo(), mbrId);
        if(memberInfo.getBalance() < 0) {
            //数据有误，触发事物回滚机制
            throw new BizException("更新会员账户金额有误");
        }

        //更新safeKey
        baseMapper.updateSafeKey(memberInfo.getMbrId(), JeepayKit.MBR_ACCOUNT_SAFE_KEY);

        return memberInfo;
    }

    public Map count(LambdaQueryWrapper<MemberAccountHistory> wrapper) {
        return memberAccountHistoryMapper.count(wrapper);
    }


    /**
     * @author: xiaoyu
     * @date: 2023/4/18 10:20
     * @describe: 查询条件
     */
    public void selectParams(MemberAccountHistory accountHistory, LambdaQueryWrapper<MemberAccountHistory> wrapper) {
        // 商户号
        wrapper.eq(StringUtils.isNotEmpty(accountHistory.getMchNo()), MemberAccountHistory::getMchNo, accountHistory.getMchNo());
        // 手机号
        wrapper.like(StringUtils.isNotEmpty(accountHistory.getMbrTel()), MemberAccountHistory::getMbrTel, accountHistory.getMbrTel());
        // 记录ID
        wrapper.eq(accountHistory.getHid() != null, MemberAccountHistory::getHid, accountHistory.getHid());
        // 会员ID
        wrapper.eq(StringUtils.isNotEmpty(accountHistory.getMbrId()), MemberAccountHistory::getMbrId, accountHistory.getMbrId());
        // 会员名称快照
        wrapper.like(StringUtils.isNotEmpty(accountHistory.getMbrName()), MemberAccountHistory::getMbrName, accountHistory.getMbrName());
        // 业务类型
        wrapper.eq(accountHistory.getBizType() != null, MemberAccountHistory::getBizType, accountHistory.getBizType());
        // 关联订单号
        wrapper.eq(StringUtils.isNotEmpty(accountHistory.getRelaBizOrderId()), MemberAccountHistory::getRelaBizOrderId, accountHistory.getRelaBizOrderId());
        // 时间范围条件
        Date[] dateRange = accountHistory.buildQueryDateRange();
        if (dateRange[0] != null) {
            wrapper.ge(MemberAccountHistory::getCreatedAt, dateRange[0]);
        }
        if (dateRange[1] != null) {
            wrapper.le(MemberAccountHistory::getCreatedAt, dateRange[1]);
        }
    }

}
