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.MemberOrderDetailAdminVo;
import com.liquidnet.service.adam.entity.*;
import com.liquidnet.service.adam.mapper.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
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 RedisDataSourceUtil redisDataSourceUtil;

    @Value("${liquidnet.url-refund.apply}")
    private String applyUrl;
    @Value("${liquidnet.url-refund.notify-member}")
    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));
        return detailAdminVo;
    }

    @Override
    @Transactional
    public AjaxResult refundProcessing(AdamMemberOrderRefundParam param, AdamMemberOrder memberOrder) {
        LinkedMultiValueMap<String, String> linkedMultiValueMap = new LinkedMultiValueMap<>();

        String refundNo = IDGenerator.nextTimeId2().concat("VR");

        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", String.valueOf(param.getRefundAmt()));
        linkedMultiValueMap.add("priceTotal", String.valueOf(memberOrder.getPricePaid()));
        linkedMultiValueMap.add("reason", param.getReason());

        log.info("会员退款:支付中心请求参数:{}", linkedMultiValueMap);
        String postResult = HttpUtil.post(applyUrl, linkedMultiValueMap);
        log.info("会员退款:支付中心返回数据:{}", postResult);

        JsonNode postResultJNode = JsonUtils.fromJson(postResult, JsonNode.class);
        if (!postResultJNode.get("success").asBoolean()) {
            return AjaxResult.warn("会员退款请求支付中心失败");
        }
        // 退款请求成功，修改订单状态，同步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.setRefundNo(refundNo);
        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);
        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);

            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);
        }

        return AjaxResult.success();
    }

}
