package com.liquidnet.client.admin.zhengzai.adam.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
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.fasterxml.jackson.databind.JsonNode;
import com.liquidnet.client.admin.common.core.domain.AjaxResult;
import com.liquidnet.client.admin.common.utils.ShiroUtils;
import com.liquidnet.client.admin.zhengzai.adam.service.IAdamMemberOrderAdminService;
import com.liquidnet.common.cache.redis.util.RedisDataSourceUtil;
import com.liquidnet.commons.lang.util.*;
import com.liquidnet.service.adam.constant.AdamRedisConst;
import com.liquidnet.service.adam.dto.MemberOrderDto;
import com.liquidnet.service.adam.dto.admin.AdamMemberOrderRefundParam;
import com.liquidnet.service.adam.dto.admin.MemberOrderListReq;
import com.liquidnet.service.adam.dto.vo.AdamMemberOrderExtVo;
import com.liquidnet.service.adam.dto.vo.AdamMemberOrderVo;
import com.liquidnet.service.adam.dto.vo.AdamUserInfoVo;
import com.liquidnet.service.adam.dto.vo.AdamUserMemberVo;
import com.liquidnet.service.adam.dto.vo.admin.AdamMemberPriorityCouponAdminVo;
import com.liquidnet.service.adam.dto.vo.admin.MemberOrderDetailAdminVo;
import com.liquidnet.service.adam.entity.*;
import com.liquidnet.service.adam.mapper.*;
import com.liquidnet.service.candy.dto.admin.CandyPriorityCouponUsageDto;
import com.liquidnet.service.candy.mapper.CandyUserCouponMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.LinkedMultiValueMap;

import java.beans.IntrospectionException;
import java.lang.reflect.InvocationTargetException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.IntStream;

/**
 * @author AnJiabin <anjiabin@zhengzai.tv>
 * @version V1.0
 * @Description: TODO
 * @class: AdamMemberOrderAdminServiceImpl
 * @Package com.liquidnet.client.admin.zhengzai.adam.service.impl
 * @Copyright: LightNet @ Copyright (c) 2021
 * @date 2021/6/6 16:25
 */
@Slf4j
@Service
public class AdamMemberOrderAdminServiceImpl extends ServiceImpl<AdamMemberOrderMapper, AdamMemberOrder> implements IAdamMemberOrderAdminService {
    @Autowired
    private AdamMemberOrderMapper adamMemberOrderMapper;
    @Autowired
    private AdamUserMemberMapper adamUserMemberMapper;
    @Autowired
    private AdamUserInfoMapper adamUserInfoMapper;
    @Autowired
    private AdamUserMapper adamUserMapper;
    @Autowired
    private AdamMemberOrderExtMapper adamMemberOrderExtMapper;
    @Autowired
    private AdamMemberRefundMapper adamMemberRefundMapper;
    @Autowired
    private CandyUserCouponMapper candyUserCouponMapper;

    @Autowired
    private RedisDataSourceUtil redisDataSourceUtil;

    @Value("${liquidnet.service.dragon.urls.refundApply}")
    private String applyUrl;
    @Value("${liquidnet.service.platform.urls.memberRefundNotify}")
    private String notifyUrl;

    @Override
    public List<MemberOrderDto> getMemberOrderList(MemberOrderListReq memberOrderListReq) {
        Map<String, Object> reqParamMap = new HashMap<>();
        try {
            reqParamMap = BeanUtil.convertBeanToMap(memberOrderListReq,false);
        } catch (IntrospectionException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        List<MemberOrderDto> list = adamMemberOrderMapper.getMemberOrderList(reqParamMap);
        return list;
    }

    @Override
    public MemberOrderDetailAdminVo getMemberOrderDetail(String orderNo) {
        MemberOrderDetailAdminVo detailAdminVo = new MemberOrderDetailAdminVo();
        AdamMemberOrderVo adamMemberOrderVo = new AdamMemberOrderVo();
        AdamUser adamUser = new AdamUser();
        AdamUserInfoVo adamUserInfoVo = new AdamUserInfoVo();
        AdamUserMemberVo adamUserMemberVo = new AdamUserMemberVo();

        LambdaQueryWrapper<AdamMemberOrder> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.eq(AdamMemberOrder::getOrderNo,orderNo);
        AdamMemberOrder adamMemberOrder = adamMemberOrderMapper.selectOne(queryWrapper);
        BeanUtil.copy(adamMemberOrder,adamMemberOrderVo);

        //获取用户会员信息
        LambdaQueryWrapper<AdamUserMember> adamUserMemberWrapper = new LambdaQueryWrapper();
        adamUserMemberWrapper.eq(AdamUserMember::getUid,adamMemberOrderVo.getUid());
        AdamUserMember adamUserMember = adamUserMemberMapper.selectOne(adamUserMemberWrapper);
        BeanUtil.copy(adamUserMember,adamUserMemberVo);
        //获取用户信息表
        LambdaQueryWrapper<AdamUserInfo> adamUserInfoWrapper = new LambdaQueryWrapper();
        adamUserInfoWrapper.eq(AdamUserInfo::getUid,adamMemberOrderVo.getUid());
        AdamUserInfo adamUserInfo = adamUserInfoMapper.selectOne(adamUserInfoWrapper);
        BeanUtil.copy(adamUserInfo,adamUserInfoVo);
        //获取用户表信息
        LambdaQueryWrapper<AdamUser> adamUserWrapper = new LambdaQueryWrapper();
        adamUserWrapper.eq(AdamUser::getUid,adamMemberOrderVo.getUid());
        adamUser = adamUserMapper.selectOne(adamUserWrapper);
        // 查取快递信息
        AdamMemberOrderExt adamMemberOrderExt = adamMemberOrderExtMapper.selectOne(Wrappers.lambdaQuery(AdamMemberOrderExt.class).eq(AdamMemberOrderExt::getOrderNo, orderNo));

        adamUserMemberVo.setState(adamUserMemberVo.isActive() ? 1 : 2);
        detailAdminVo.setAdamMemberOrderVo(adamMemberOrderVo);
        detailAdminVo.setAdamUserMemberVo(adamUserMemberVo);
        detailAdminVo.setAdamUserInfoVo(adamUserInfoVo);
        detailAdminVo.setAdamUser(adamUser);
        detailAdminVo.setAdamMemberOrderExtVo(AdamMemberOrderExtVo.getNew().copy(adamMemberOrderExt));
        detailAdminVo.setPriorityCouponList(buildPriorityCouponList(adamMemberOrderVo.getUid()));
        return detailAdminVo;
    }

    private List<AdamMemberPriorityCouponAdminVo> buildPriorityCouponList(String uid) {
        List<AdamMemberPriorityCouponAdminVo> result = new ArrayList<>();
        if (uid == null || uid.isEmpty()) {
            return result;
        }
        List<CandyPriorityCouponUsageDto> usageList = candyUserCouponMapper.selectPriorityCouponUsageByUid(uid);
        if (CollectionUtils.isEmpty(usageList)) {
            return result;
        }
        for (CandyPriorityCouponUsageDto usage : usageList) {
            AdamMemberPriorityCouponAdminVo vo = new AdamMemberPriorityCouponAdminVo();
            vo.setUcouponId(usage.getUcouponId());
            vo.setName(usage.getName());
            vo.setMobile(usage.getMobile());
            vo.setExclusive(usage.getExclusive());
            vo.setExclusiveLabel(resolveExclusiveLabel(usage.getExclusive()));
            vo.setState(usage.getState());
            vo.setStateLabel(resolveCouponStateLabel(usage.getState()));
            vo.setTitle(usage.getTitle());
            vo.setCouType(usage.getCouType());
            vo.setCouTypeLabel(resolveCouTypeLabel(usage.getCouType()));
            vo.setBindAt(usage.getBindAt());
            vo.setDuedAt(usage.getDuedAt());
            vo.setUsedAt(usage.getUsedAt());
            result.add(vo);
        }
        return result;
    }

    private String resolveExclusiveLabel(Integer exclusive) {
        if (null == exclusive) {
            return "-";
        }
        if (exclusive == 1) {
            return "会员礼包";
        }
        if (exclusive == 0) {
            return "常规";
        }
        return String.valueOf(exclusive);
    }

    private String resolveCouponStateLabel(Integer state) {
        if (null == state) {
            return "-";
        }
        switch (state) {
            case 1:
                return "可用";
            case 2:
                return "无效";
            case 3:
                return "已过期";
            case 5:
                return "已使用";
            case 9:
                return "移除不展示（过期或已使用）";
            default:
                return String.valueOf(state);
        }
    }

    private String resolveCouTypeLabel(Integer couType) {
        if (null == couType) {
            return "-";
        }
        switch (couType) {
            case 1:
                return "代金卷";
            case 2:
                return "满减卷";
            case 3:
                return "兑换卷";
            case 4:
                return "折扣卷";
            case 101:
                return "优先卷";
            default:
                return String.valueOf(couType);
        }
    }

    @Override
    @Transactional
    public AjaxResult refundProcessing(AdamMemberOrderRefundParam param, AdamMemberOrder memberOrder) {
        String refundNo, price, reason;
        AdamMemberRefund existsRefund = adamMemberRefundMapper.selectOne(Wrappers.lambdaQuery(AdamMemberRefund.class)
                .eq(AdamMemberRefund::getOrderNo, memberOrder.getOrderNo()).eq(AdamMemberRefund::getRefundState, 9));
        if (null == existsRefund) {
            refundNo = IDGenerator.nextTimeId2().concat("VR");
            price = String.valueOf(param.getRefundAmt());
            reason = param.getReason();

            {// 修改订单状态，同步REDIS
                LocalDateTime now = LocalDateTime.now();

                AdamMemberRefund memberRefund = new AdamMemberRefund();
                memberRefund.setRefundNo(refundNo);
                memberRefund.setOrderNo(memberOrder.getOrderNo());
                memberRefund.setRefundPrice(param.getRefundAmt());
                memberRefund.setRefundReason(param.getReason());
                memberRefund.setRenewable(param.getRenewable());
                memberRefund.setRefundState(9);
                memberRefund.setOperator(ShiroUtils.getLoginName());
                memberRefund.setCreatedAt(now);

                adamMemberRefundMapper.insert(memberRefund);

                AdamMemberOrder updateInfoMemberOrder = new AdamMemberOrder();
                updateInfoMemberOrder.setMid(memberOrder.getMid());
                updateInfoMemberOrder.setState(4);
                updateInfoMemberOrder.setUpdatedAt(now);
                updateInfoMemberOrder.setComment("R");
                adamMemberOrderMapper.updateById(updateInfoMemberOrder);

                String moKey = AdamRedisConst.INFO_MEMBER_ORDER + memberOrder.getUid();
                ArrayList<AdamMemberOrderVo> vos = (ArrayList<AdamMemberOrderVo>) redisDataSourceUtil.getRedisAdamUtil().get(moKey);
                if (!CollectionUtils.isEmpty(vos)) {
                    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(4);
                    vo.setUpdatedAt(now);
                    vos.set(idx, vo);
                    redisDataSourceUtil.getRedisAdamUtil().set(moKey, vos);
                }

                if (memberRefund.getRenewable() == 2) {// 拉黑用户，直接更新用户会员状态信息
                    AdamUserMember updateUserMember = new AdamUserMember();
                    updateUserMember.setState(2);
                    updateUserMember.setExpiryAt(now);
                    updateUserMember.setUpdatedAt(now);
                    updateUserMember.setComment("R");

                    LambdaUpdateWrapper<AdamUserMember> userMemberLambdaUpdateWrapper = Wrappers.lambdaUpdate(AdamUserMember.class);
                    userMemberLambdaUpdateWrapper.eq(AdamUserMember::getUid, memberOrder.getUid());
                    adamUserMemberMapper.update(updateUserMember, userMemberLambdaUpdateWrapper);

                    String umkey = AdamRedisConst.INFO_USER_MEMBER + memberOrder.getUid();
                    AdamUserMemberVo userMemberVo = (AdamUserMemberVo) redisDataSourceUtil.getRedisAdamUtil().get(umkey);
                    if (null != userMemberVo) {
                        userMemberVo.setState(2);
                        userMemberVo.setExpiryAt(now);
                        userMemberVo.setUpdatedAt(now);
                        redisDataSourceUtil.getRedisAdamUtil().set(umkey, userMemberVo);

                        List<String> uidBlackList = (List<String>) redisDataSourceUtil.getRedisAdamUtil().get(AdamRedisConst.BLK_LIST_MEMBER_UID);
                        if (CollectionUtils.isEmpty(uidBlackList)) {
                            uidBlackList = CollectionUtil.arrayListString();
                        }
                        uidBlackList.add(memberOrder.getUid());
                        redisDataSourceUtil.getRedisAdamUtil().set(AdamRedisConst.BLK_LIST_MEMBER_UID, uidBlackList);
                    }
                }
            }
        } else {
            log.warn("会员管理:会员订单:退款:该订单正在退款中[AdamMemberOrderRefundParam={}]", JsonUtils.toJson(param));
            refundNo = existsRefund.getRefundNo();
            price = String.valueOf(existsRefund.getRefundPrice());
            reason = existsRefund.getRefundReason();
        }

        LinkedMultiValueMap<String, String> linkedMultiValueMap = new LinkedMultiValueMap<>();
        linkedMultiValueMap.add("code", memberOrder.getPayNo());
        linkedMultiValueMap.add("notifyUrl", notifyUrl);
        linkedMultiValueMap.add("orderCode", memberOrder.getOrderNo());
        linkedMultiValueMap.add("orderRefundCode", refundNo);
        linkedMultiValueMap.add("paymentId", memberOrder.getPaymentId());
        linkedMultiValueMap.add("paymentType", (memberOrder.getDeviceFrom() + memberOrder.getPayType()).toUpperCase());
        linkedMultiValueMap.add("price", price);
        linkedMultiValueMap.add("priceTotal", String.valueOf(memberOrder.getPricePaid()));
        linkedMultiValueMap.add("reason", reason);
        LinkedMultiValueMap<String, String> linkedMultiheadersMap = new LinkedMultiValueMap<>();
        linkedMultiheadersMap.add("Accept", MediaType.APPLICATION_JSON_UTF8_VALUE);

        log.info("会员管理:会员订单:退款:支付中心请求参数:{}", linkedMultiValueMap);
        String postResult = null;
        try {
            postResult = HttpUtil.post(applyUrl, linkedMultiValueMap, linkedMultiheadersMap);
            log.info("会员管理:会员订单:退款:支付中心返回数据:{}", postResult);
        } catch (Exception e) {
            log.error("会员管理:会员订单:退款:支付中心请求异常");
        }

        JsonNode postResultJNode = JsonUtils.fromJson(postResult, JsonNode.class);
        if (null == postResultJNode || !postResultJNode.get("success").asBoolean()) {
            return AjaxResult.warn("会员退款请求支付中心失败");
        }

        JsonNode dataNode = postResultJNode.get("data");
        if (null != dataNode && null != dataNode.get("refundCode") && (null == existsRefund || null == existsRefund.getRepayNo())) {
            AdamMemberRefund updateMemberRefund = new AdamMemberRefund();
            updateMemberRefund.setRepayNo(dataNode.get("refundCode").asText());
            adamMemberRefundMapper.update(updateMemberRefund, Wrappers.lambdaUpdate(AdamMemberRefund.class).eq(AdamMemberRefund::getRefundNo, refundNo));
        }
        return AjaxResult.success();
    }

}
