package com.liquidnet.service.platform.service.impl.adam;

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.liquidnet.common.cache.redis.util.RedisUtil;
import com.liquidnet.service.adam.constant.AdamRedisConst;
import com.liquidnet.service.adam.dto.vo.AdamMemberOrderVo;
import com.liquidnet.service.adam.dto.vo.AdamUserMemberVo;
import com.liquidnet.service.adam.entity.AdamMemberOrder;
import com.liquidnet.service.adam.entity.AdamMemberRefund;
import com.liquidnet.service.adam.entity.AdamUserMember;
import com.liquidnet.service.adam.mapper.AdamMemberOrderMapper;
import com.liquidnet.service.adam.mapper.AdamMemberRefundMapper;
import com.liquidnet.service.adam.mapper.AdamUserMemberMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.stream.IntStream;

@Slf4j
@Service
public class PlatformMemberRefundService extends ServiceImpl<AdamMemberRefundMapper, AdamMemberRefund> {
    @Autowired
    private AdamMemberOrderMapper adamMemberOrderMapper;
    @Autowired
    private AdamUserMemberMapper adamUserMemberMapper;

    @Autowired
    private RedisUtil redisUtil;

    public boolean refundProcessing(HttpServletRequest request) {
        String refundNo = request.getParameter("orderRefundCode");
        String refundAt = request.getParameter("refundAt");
        String payNo = request.getParameter("refundCode");
        String refundError = request.getParameter("refundError");
        String refundAmt = request.getParameter("refundPrice");
        int status = Integer.parseInt(request.getParameter("status"));

        AdamMemberRefund memberRefund = this.getOne(Wrappers.lambdaQuery(AdamMemberRefund.class)
                .eq(AdamMemberRefund::getRefundNo, refundNo));

        if (null == memberRefund) {
            log.warn("会员退款回调处理失败:订单不存在[payNo:{},refundNo:{}]", payNo, refundNo);
            return false;
        }
        if (memberRefund.getRefundState() != 9) {
            log.warn("会员退款回调处理失败:订单已处理[payNo:{},refundNo:{}]", payNo, refundNo);
            return true;
        }

        LocalDateTime now = LocalDateTime.now();

        LambdaUpdateWrapper<AdamMemberRefund> memberRefundLambdaUpdateWrapper = Wrappers.lambdaUpdate(AdamMemberRefund.class)
                .eq(AdamMemberRefund::getRefundNo, refundNo);
        memberRefundLambdaUpdateWrapper.set(AdamMemberRefund::getRefundAt, refundAt);
        memberRefundLambdaUpdateWrapper.set(AdamMemberRefund::getRefundReason, refundError);
        memberRefundLambdaUpdateWrapper.set(AdamMemberRefund::getUpdatedAt, now);

        switch (status) {
            case 0:// 失败
                memberRefundLambdaUpdateWrapper.set(AdamMemberRefund::getRefundState, 3);
                return this.update(memberRefundLambdaUpdateWrapper);
            case 1:// 成功
                memberRefundLambdaUpdateWrapper.set(AdamMemberRefund::getRefundState, 1);
                if (this.update(memberRefundLambdaUpdateWrapper)) {

                    this.refundSuccProcessing(memberRefund.getOrderNo(), now);

                    return true;
                } else {
                    return false;
                }
            default:
                log.warn("会员退款回调处理失败:未知的状态[orderNo:{},refundNo:{},status:{}]", memberRefund.getOrderNo(), refundNo, status);
                return false;
        }
    }

    /* -------------------------------------------------------------------------- */

    private void refundSuccProcessing(String orderNo, LocalDateTime now) {
        AdamMemberOrder memberOrder = adamMemberOrderMapper.selectOne(Wrappers.lambdaUpdate(AdamMemberOrder.class).eq(AdamMemberOrder::getOrderNo, orderNo));
        LocalDateTime newExpiryAt = null;

        {// 同步用户端信息
            String moKey = AdamRedisConst.INFO_MEMBER_ORDER + memberOrder.getUid();
            ArrayList<AdamMemberOrderVo> vos = (ArrayList<AdamMemberOrderVo>) redisUtil.get(moKey);
            int idx = IntStream.range(0, vos.size()).filter(i -> vos.get(i).getOrderNo().equals(memberOrder.getOrderNo())).findFirst().orElse(-1);
            AdamMemberOrderVo vo = vos.get(idx);
            vo.setState(5);
            vo.setUpdatedAt(now);
            vos.set(idx, vo);
            boolean syncVo = redisUtil.set(moKey, vos);
            log.info("###会员退款回调处理成功:更新REDIS会员订单信息{}[orderNo:{},uid:{}]", syncVo ? "成功" : "失败", orderNo, memberOrder.getUid());

            String umKey = AdamRedisConst.INFO_USER_MEMBER.concat(memberOrder.getUid());
            AdamUserMemberVo userMemberVo = (AdamUserMemberVo) redisUtil.get(umKey);

            if (userMemberVo.getState() == 1) {// 非拉黑用户，则更新到期时间为减去订单标记的会员有效期的日期
                newExpiryAt = userMemberVo.getExpiryAt().minusDays(memberOrder.getDays());

                LocalDate nowDate = now.toLocalDate();
                LocalDate newExpiryDate = newExpiryAt.toLocalDate();
                if (newExpiryDate.isEqual(nowDate)) {// 新的过期时间如果和当前时间为同一天，则重置到期时间为当天00:00:00
                    newExpiryAt = now.withHour(0).withMinute(0).withSecond(0);
                }

                userMemberVo.setExpiryAt(newExpiryAt);
                userMemberVo.setUpdatedAt(now);

                syncVo = redisUtil.set(umKey, userMemberVo);
                log.info("###会员退款回调处理成功:更新REDIS会员信息{}[orderNo:{},uid:{}]", syncVo ? "成功" : "失败", orderNo, memberOrder.getUid());

                AdamUserMember updateInfoUserMember = new AdamUserMember();
                updateInfoUserMember.setExpiryAt(newExpiryAt);
                updateInfoUserMember.setUpdatedAt(now);
                updateInfoUserMember.setComment("R");
                int updateRst = adamUserMemberMapper.update(updateInfoUserMember, Wrappers.lambdaUpdate(AdamUserMember.class).eq(AdamUserMember::getUid, memberOrder.getUid()));
                log.info("###会员退款回调处理成功:更新DB会员信息{}[orderNo:{},uid:{}]", updateRst <= 0 ? "失败" : "成功", orderNo, memberOrder.getUid());
            }
        }

        AdamMemberOrder updateInfoMemberOrder = new AdamMemberOrder();
        updateInfoMemberOrder.setMid(memberOrder.getMid());
        updateInfoMemberOrder.setState(5);
        updateInfoMemberOrder.setUpdatedAt(now);
        int updateRst = adamMemberOrderMapper.updateById(updateInfoMemberOrder);
        log.info("###会员退款回调处理成功:更新DB订单信息{}[orderNo:{}]", updateRst <= 0 ? "失败" : "成功", orderNo);
    }
}
