package com.liquidnet.service.order.utils;

import brave.http.HttpRequest;
import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.core.type.TypeReference;
import com.liquidnet.common.cache.redis.util.RedisUtil;
import com.liquidnet.commons.lang.util.CollectionUtil;
import com.liquidnet.commons.lang.util.CurrentUtil;
import com.liquidnet.commons.lang.util.HttpUtil;
import com.liquidnet.commons.lang.util.JsonUtils;
import com.liquidnet.service.adam.constant.AdamRedisConst;
import com.liquidnet.service.adam.dto.vo.AdamAddressesVo;
import com.liquidnet.service.adam.dto.vo.AdamEntersVo;
import com.liquidnet.service.adam.dto.vo.AdamUserMemberVo;
import com.liquidnet.service.candy.param.BackCouponParam;
import com.liquidnet.service.candy.vo.CandyUseResultVo;
import com.liquidnet.service.kylin.dto.param.SysDamaiParam;
import com.liquidnet.service.kylin.dto.vo.mongo.KylinOrderTicketVo;
import com.liquidnet.service.kylin.dto.vo.returns.InnerReturnVo;
import com.liquidnet.service.kylin.dto.vo.returns.KylinOrderListVo;
import com.liquidnet.service.kylin.dto.vo.returns.PayResultVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.HttpRequestBase;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

@Component
@Slf4j
public class OrderUtils {

    @Autowired
    private DataUtils dataUtils;
    //    @Value("${liquidnet.adam.url}")
//    private String adamUrl;
    @Value("${liquidnet.candy.url}")
    private String candyUrl;
    @Autowired
    private RedisUtil redisUtil;

    public String judgeOrderLimit(
            int type,
            String userId,
            String idCard,
            String performanceId,
            String ticketId,
            int performanceLimitCount,
            int performanceMemberLimitCount,
            int ticketLimitCount,
            int ticketMemberLimitCount,
            int performanceBuyCount,
            int ticketBuyCount,
            int memberType,
            int isTrueName
    ) {
        Integer[] integers;
        if (101 == type) {
            integers = festivalOrderLimit(userId, idCard, performanceId, ticketId, performanceBuyCount, ticketBuyCount, isTrueName);
        } else {
            integers = roadShowOrderLimit(userId, idCard, performanceId, ticketId, performanceBuyCount, ticketBuyCount, isTrueName);
        }
        return judgeMemberType(performanceLimitCount, performanceMemberLimitCount, ticketLimitCount, ticketMemberLimitCount, memberType, integers[0], integers[1], isTrueName);
    }

    public Integer[] roadShowOrderLimit(
            String userId,
            String idCard,
            String performanceId,
            String ticketId,
            int performanceBuyCount,
            int ticketBuyCount,
            int isTrueName
    ) {
        if (1 == isTrueName) {//实名
            performanceBuyCount += dataUtils.getIdCardPBuyCount(idCard, performanceId);
            ticketBuyCount += dataUtils.getIdCardTBuyCount(idCard, ticketId);
        } else {//非实名
            performanceBuyCount += dataUtils.getUserPBuyCount(userId, performanceId);
            ticketBuyCount += dataUtils.getUserTBuyCount(userId, ticketId);
        }
        Integer[] array = ObjectUtil.cloneInteger2Array();
        array[0] = performanceBuyCount;
        array[1] = ticketBuyCount;
        return array;
    }

    public Integer[] festivalOrderLimit(
            String userId,
            String idCard,
            String performanceId,
            String ticketId,
            int performanceBuyCount,
            int ticketBuyCount,
            int isTrueName
    ) {
        if (1 == isTrueName) {//实名
            performanceBuyCount += dataUtils.getIdCardPBuyCount(idCard, performanceId);
            ticketBuyCount += dataUtils.getIdCardTBuyCount(idCard, ticketId);
        } else {//非实名
            performanceBuyCount += dataUtils.getUserPBuyCount(userId, performanceId);
            ticketBuyCount += dataUtils.getUserTBuyCount(userId, ticketId);
        }

        Integer[] array = ObjectUtil.cloneInteger2Array();
        array[0] = performanceBuyCount;
        array[1] = ticketBuyCount;
        return array;
    }

    public String judgeMemberType(int performanceLimitCount, int performanceMemberLimitCount, int ticketLimitCount, int ticketMemberLimitCount, int memberType, int performanceBuyCount, int ticketBuyCount, int isTrueName) {
        if (memberType == 1 || memberType == 2) {
            if (performanceBuyCount > performanceMemberLimitCount && performanceMemberLimitCount != 0) {
                return (1 == isTrueName ? "实名制" : "本场") + "演出限购" + performanceMemberLimitCount + "张，已超出";//超过演出维度购买量
            }
            if (ticketBuyCount > ticketMemberLimitCount && ticketMemberLimitCount != 0) {
                return (1 == isTrueName ? "实名制" : "该") + "票种限购" + ticketMemberLimitCount + "张，已超出";//超过票维度购买量
            }
        } else {//非会员区间
            if (performanceBuyCount > performanceLimitCount && performanceLimitCount != 0) {
                return (1 == isTrueName ? "实名制" : "本场") + "演出限购" + performanceLimitCount + "张，已超出";//超过演出维度购买量
            }
            if (ticketBuyCount > ticketLimitCount && ticketLimitCount != 0) {
                return (1 == isTrueName ? "实名制" : "该") + "票种限购" + ticketLimitCount + "张，已超出";//超过票维度购买量
            }
        }
        return "";
    }


    //判断 操作 普通库存还是兑换库存
    public int changeSurplus(boolean isPay, String ticketId, int number) {
        int surplusGeneral;
        if (isPay) {
            surplusGeneral = dataUtils.changeSurplusGeneral(ticketId, number);
        } else {
            surplusGeneral = dataUtils.changeSurplusExchange(ticketId, number);
        }
        return surplusGeneral;
    }

    public AdamUserMemberVo isMember(String uid) {
//        String resultData = HttpUtil.get("/adam/member/check/depth?uid=" + uid, null);
//        AdamUserMemberVo vo = JsonUtils.fromJson(resultData, AdamUserMemberVo.class);

        String rk = AdamRedisConst.INFO_USER_MEMBER.concat(uid);
        AdamUserMemberVo vo = (AdamUserMemberVo) redisUtil.get(rk);
        if(null != vo && vo.isActive()){
            return vo;
        }else{
            return null;
        }
    }


    public AdamAddressesVo getAddress(String uid, String addressesId) {
//        String resultData = HttpUtil.get("/adam/addr/query/depth?uid=" + uid + "&addrId=" + addressesId, null);
//        List<AdamAddressesVo> vos = JsonUtils.fromJson(resultData, new TypeReference<List<AdamAddressesVo>>() {
//        });
        String rk = AdamRedisConst.INFO_ADDRESSES.concat(uid);
        List<AdamAddressesVo> vos = (List<AdamAddressesVo>) redisUtil.get(rk);
        return vos.stream().filter(r -> r.getAddressesId().equals(addressesId)).findAny().orElse(null);
    }

    public AdamEntersVo getEnters(String uid, String entersId) {
//        String resultData = HttpUtil.get("/adam/enters/query/depth?uid=" + uid + "&entersId=" + entersId, null);
//        List<AdamEntersVo> vos = JsonUtils.fromJson(resultData, new TypeReference<List<AdamEntersVo>>() {
//        });
        String rk = AdamRedisConst.INFO_ENTERS.concat(uid);
        List<AdamEntersVo> vos = (List<AdamEntersVo>) redisUtil.get(rk);
        return vos.stream().filter(r -> r.getEntersId().equals(entersId)).findAny().orElse(null);
    }

    /**
     * 使用优惠券
     *
     * @param uCouponId  券id
     * @param content    消费内容
     * @param totalPrice 订单总价
     * @return
     */
    public HashMap<String, Object> useCoupon(String uCouponId, String content, BigDecimal totalPrice, String performanceId, String timesId, String ticketId) {
        MultiValueMap<String, String> params = CollectionUtil.linkedMultiValueMapStringString();
        params.add("uCouponId", uCouponId);
        params.add("content", content);
        params.add("totalPrice", totalPrice.toString());

        params.add("goodId", "-1");
        params.add("performanceId", performanceId);
        params.add("timeId", timesId);
        params.add("ticketId", ticketId);

        MultiValueMap<String, String> header = CollectionUtil.linkedMultiValueMapStringString();
        header.add("Authorization", "Bearer " + CurrentUtil.getToken());
        log.info("url="+candyUrl + "/candy-coupon/use");
        log.info("params="+JSON.toJSONString(params));
        String returnData = HttpUtil.post(candyUrl + "/candy-coupon/use", params, header);
        InnerReturnVo<CandyUseResultVo> innerReturnVo = JsonUtils.fromJson(returnData, new TypeReference<InnerReturnVo<CandyUseResultVo>>() {
        });
        log.info("returnData="+returnData);
        CandyUseResultVo candyUseResultVo = innerReturnVo.getData();
        Integer type = candyUseResultVo.getCouType();
        BigDecimal value = candyUseResultVo.getValue();
        BigDecimal voucher = BigDecimal.ZERO;
        switch (type) {
            case -1:
                voucher = BigDecimal.valueOf(-1);
                break;
            case 1:
                voucher = voucher.add(value);
                break;
            case 2:
                voucher = voucher.add(value);
                break;
            case 3:
                voucher = voucher.add(totalPrice);
                break;
            case 4:
                voucher = totalPrice.subtract(totalPrice.multiply(value));
                break;
            default:
                voucher = BigDecimal.ZERO;
                break;
        }
        HashMap<String, Object> hashMap = CollectionUtil.mapStringObject();
        hashMap.put("type", type);
        hashMap.put("voucher", voucher.setScale(2,BigDecimal.ROUND_HALF_UP));
        return hashMap;
    }

    public void backAdvanceCoupon(String advanceCode,String uid) {
        if (advanceCode != null) {
            backCoupon(advanceCode.toString(), uid);
        }
    }

    public void backCoupon(String uCouponId, String uid) {
        BackCouponParam param = BackCouponParam.getNew();
        param.setuCouponIds(uCouponId);
        param.setUid(uid);

        MultiValueMap<String, String> header = CollectionUtil.linkedMultiValueMapStringString();
        header.add("Authorization", "Bearer " + CurrentUtil.getToken());

        ArrayList<BackCouponParam> params = new ArrayList();
        params.add(param);
        String jsonString = JSON.toJSONString(params);
        System.out.println("jsonString = " + jsonString);
        String returnData = HttpUtil.postRaw(candyUrl + "/candy-coupon/useBack", jsonString, header);

        System.out.println("returnData = " + returnData);
    }

    /**
     * @param userId  用户id
     * @param type    1新增 2修改
     * @param orderId 订单id [需要新增或者修改的订单id]
     */
    public Boolean resetOrderListVo(String userId, Integer type, String orderId, KylinOrderTicketVo dataSingle) {
        List<KylinOrderListVo> vo = ObjectUtil.cloneArrayKylinOrderListVo();
        List<KylinOrderListVo> redisVo = ObjectUtil.cloneArrayKylinOrderListVo();
        KylinOrderListVo voItem = KylinOrderListVo.getNew();
        KylinOrderTicketVo data;
        if (dataSingle == null) {
            data = dataUtils.getOrderTicketVo(orderId);
        } else {
            data = dataSingle;
        }
        BeanUtils.copyProperties(data, voItem);
        List<KylinOrderListVo> redisData = dataUtils.getOrderList(userId);
        if (type == 1) {
            redisVo.add(voItem);
            if (redisData.size() > 0) {
                if (redisData.get(0).getOrderTicketsId().equals(orderId)) {
                    redisData.remove(0);
                }
            }
        }

        redisVo.addAll(redisData);

        switch (type) {
            case 1:
                for (int i = 0; i < redisVo.size(); i++) {
                    if (i == 40) {
                        break;
                    }
                    if (i == 0) {
                        vo.add(voItem);
                    } else {
                        vo.add(redisVo.get(i));
                    }
                }
                if (redisVo.size() == 0) {
                    vo.add(voItem);
                }
                dataUtils.setOrderList(userId, vo);
                return true;
            case 2:
                for (int i = 0; i < redisVo.size(); i++) {
                    if (i == 40) {
                        break;
                    }
                    if (redisVo.get(i).getOrderTicketsId().equals(orderId)) {
                        vo.add(voItem);
                    } else {
                        vo.add(redisVo.get(i));
                    }
                }
                dataUtils.setOrderList(userId, vo);
                return true;
            default:
                return false;
        }
    }
}
