package com.liquidnet.service.order.utils;

import com.liquidnet.common.cache.redis.util.RedisUtil;
import com.liquidnet.commons.lang.util.DateUtil;
import com.liquidnet.service.kylin.constant.KylinRedisConst;
import com.liquidnet.service.kylin.dto.vo.middle.KylinTicketTimesVo;
import com.liquidnet.service.kylin.dto.vo.middle.KylinTicketVo;
import com.liquidnet.service.kylin.dto.vo.mongo.*;
import com.liquidnet.service.kylin.dto.vo.returns.KylinOrderListVo;
import com.liquidnet.service.kylin.dto.vo.returns.KylinOrderRefundsVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.regex.Pattern;

@Component
public class DataUtils {

    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private RedisUtil redisUtil;

    /**
     * 修改普通库存 并 返回修改后的数量
     *
     * @param ticketId       票id
     * @param surplusGeneral 普通库存
     * @return 普通剩余库存
     */
    public int changeSurplusGeneral(String ticketId, int surplusGeneral) {
        if (surplusGeneral > 0) {
            return (int) redisUtil.incr(KylinRedisConst.PERFORMANCES_INVENTORY + ticketId + ":" + KylinRedisConst.SURPLUS_GENERAL, surplusGeneral);
        } else {
            return (int) redisUtil.decr(KylinRedisConst.PERFORMANCES_INVENTORY + ticketId + ":" + KylinRedisConst.SURPLUS_GENERAL, Math.abs(surplusGeneral));
        }
    }


    public void setOrderList(String userId, List<KylinOrderListVo> vo) {
        redisUtil.set(KylinRedisConst.ORDER_LIST + userId, vo);
    }

    public List<KylinOrderListVo> getOrderList(String userId) {
        if (redisUtil.hasKey(KylinRedisConst.ORDER_LIST + userId)) {
        } else {
            List<KylinOrderListVo> voList = mongoTemplate.find(Query.query(Criteria.where("userId").is(userId))
                            .with(Sort.by(Sort.Direction.DESC, "createdAt")).limit(40),
                    KylinOrderListVo.class, KylinOrderTicketVo.class.getSimpleName());
            redisUtil.set(KylinRedisConst.ORDER_LIST + userId, voList);
        }
        return (List<KylinOrderListVo>) redisUtil.get(KylinRedisConst.ORDER_LIST + userId);
    }

    /**
     * 根据订单id 获取 订单vo 详情
     *
     * @param orderId
     * @return
     */
    public KylinOrderTicketVo getOrderTicketVo(String orderId) {
        if (redisUtil.hasKey(KylinRedisConst.ORDER + orderId)) {
        } else {
            KylinOrderTicketVo ticketData = mongoTemplate.findOne(Query.query(Criteria.where("orderTicketsId").is(orderId)), KylinOrderTicketVo.class, KylinOrderTicketVo.class.getSimpleName());
            List<KylinOrderTicketEntitiesVo> kylinOrderTicketEntitiesVoList = mongoTemplate.find(Query.query(Criteria.where("orderId").is(orderId)), KylinOrderTicketEntitiesVo.class, KylinOrderTicketEntitiesVo.class.getSimpleName());
            ticketData.setEntitiesVoList(kylinOrderTicketEntitiesVoList);
            redisUtil.set(KylinRedisConst.ORDER + orderId, ticketData);
        }
        return (KylinOrderTicketVo) redisUtil.get(KylinRedisConst.ORDER + orderId);
    }

    /**
     * 删除订单redis
     *
     * @param orderId
     */
    public void delOrderTicketRedis(String orderId) {
        redisUtil.del(KylinRedisConst.ORDER + orderId);
    }

    /**
     * 获取入场须知
     *
     * @param enterInfoId
     * @return
     */
    public String getEnterInfo(String enterInfoId) {
        if (redisUtil.hasKey(KylinRedisConst.ENTER_INFO + enterInfoId)) {
        } else {
            return "入场须知";
        }
        return (String) redisUtil.get(KylinRedisConst.ENTER_INFO + enterInfoId);
    }


    /**
     * @param performanceId 演出id
     * @param ticketId      票种id
     * @param buyCount      购买数量 大于 0 增加 小于 0 减少 对应 支付 退款表
     */
    public void changeBuyInfo(String userId, String idCard, String performanceId, String ticketId, int buyCount) {
        String redisKey;

        KylinPerformanceVo vo = getPerformanceVo(performanceId);
        int isTrueName = vo.getIsTrueName();
        String useTime = "";
        HashMap<String, ArrayList<String>> allTicketId = new HashMap<>();
        for (int x = 0; x < vo.getTicketTimeList().size(); x++) {
            KylinTicketTimesVo timeItem = vo.getTicketTimeList().get(x);
            ArrayList<String> ticketList = new ArrayList<>();
            for (int y = 0; y < timeItem.getTicketList().size(); y++) {
                KylinTicketVo ticketItem = timeItem.getTicketList().get(y);
                if (ticketItem.getType() == 1) {
                    ticketList.add(ticketItem.getTicketsId());
                }
                if (ticketItem.getTicketsId().equals(ticketId)) {
                    useTime = ticketItem.getUseStart();
                }
            }
            allTicketId.put(timeItem.getUseStart(), ticketList);
        }

        if (0 == isTrueName) {
            redisKey = KylinRedisConst.USERID_BUY_INFO + userId;
        } else {
            redisKey = KylinRedisConst.IDCARD_BUY_INFO + idCard;
        }

        String performanceIdKey = redisKey + ":" + KylinRedisConst.PERFORMANCE_ID + ":" + performanceId;
        String ticketIdKey = redisKey + ":" + KylinRedisConst.TICKET_ID + ":" + ticketId;
        String ticketUseTimeKey = ticketIdKey + ":" + KylinRedisConst.USE_TIME;
        redisUtil.set(ticketUseTimeKey, useTime);

        if (buyCount > 0) {
            redisUtil.incr(ticketIdKey, buyCount);
            redisUtil.incr(performanceIdKey, buyCount);
        }else{
            redisUtil.decr(ticketIdKey, Math.abs(buyCount));
            redisUtil.decr(performanceIdKey, Math.abs(buyCount));
        }
    }




    // 获取 用户维度 演出购买数量
    public int getUserPBuyCount(String userId, String performanceId) {
        try {
            return (int) redisUtil.get(KylinRedisConst.USERID_BUY_INFO + userId + ":" + KylinRedisConst.PERFORMANCE_ID + ":" + performanceId);
        } catch (Exception e) {
            return 0;
        }
    }

    // 获取 用户维度 票种购买数量
    public int getUserTBuyCount(String userId, String ticketId) {
        try {
            return (int) redisUtil.get(KylinRedisConst.USERID_BUY_INFO + userId + ":" + KylinRedisConst.TICKET_ID + ":" + ticketId);
        } catch (Exception e) {
            return 0;
        }
    }

    // 获取 证件维度 演出购买数量
    public int getIdCardPBuyCount(String idCard, String performanceId) {
        try {
            return (int) redisUtil.get(KylinRedisConst.IDCARD_BUY_INFO + idCard + ":" + KylinRedisConst.PERFORMANCE_ID + ":" + performanceId);
        } catch (Exception e) {
            return 0;
        }
    }

    // 获取 证件维度 票种购买数量
    public int getIdCardTBuyCount(String idCard, String ticketId) {
        try {
            return (int) redisUtil.get(KylinRedisConst.IDCARD_BUY_INFO + idCard + ":" + KylinRedisConst.TICKET_ID + ":" + ticketId);
        } catch (Exception e) {
            return 0;
        }
    }

    /**
     * 删除订单redis
     *
     * @param orderEntitiesId
     */
    public void delOrderTicketEntitiesRedis(String orderEntitiesId) {
        redisUtil.del(KylinRedisConst.ORDER_ENTITIES + orderEntitiesId);
    }

    /**
     * 根据演出id 获取 演出vo 详情
     *
     * @param performanceId
     * @return
     */
    public KylinPerformanceVo getPerformanceVo(String performanceId) {
        if (redisUtil.hasKey(KylinRedisConst.PERFORMANCES + performanceId)) {
        } else {
            KylinPerformanceVo performanceData = mongoTemplate.findOne(Query.query(Criteria.where("performancesId").is(performanceId)), KylinPerformanceVo.class, KylinPerformanceVo.class.getSimpleName());
            redisUtil.set(KylinRedisConst.PERFORMANCES + performanceId, performanceData);
        }
        return (KylinPerformanceVo) redisUtil.get(KylinRedisConst.PERFORMANCES + performanceId);
    }

    public KylinOrderRefundsVo getOrderRefundVo(String orderRefundsId){
        if (redisUtil.hasKey(KylinRedisConst.ORDER_REFUND + orderRefundsId)) {
        } else {
            KylinOrderRefundsVo orderRefundsVo = mongoTemplate.findOne(Query.query(Criteria.where("orderRefundsId").is(orderRefundsId)), KylinOrderRefundsVo.class, KylinOrderRefundsVo.class.getSimpleName());
            List<KylinOrderRefundEntitiesVo> kylinOrderTicketEntitiesVoList = mongoTemplate.find(Query.query(Criteria.where("orderRefundsId").is(orderRefundsId)), KylinOrderRefundEntitiesVo.class, KylinOrderRefundEntitiesVo.class.getSimpleName());
            List<KylinOrderRefundPicVo> picVos = mongoTemplate.find(Query.query(Criteria.where("orderRefundsId").is(orderRefundsId)),KylinOrderRefundPicVo.class,KylinOrderRefundPicVo.class.getSimpleName());
            orderRefundsVo.setOrderRefundEntitiesVoList(kylinOrderTicketEntitiesVoList);
            orderRefundsVo.setOrderRefundPicVos(picVos);
            redisUtil.set(KylinRedisConst.ORDER_REFUND + orderRefundsId, orderRefundsVo);
        }
        return (KylinOrderRefundsVo) redisUtil.get(KylinRedisConst.ORDER_REFUND + orderRefundsId);
    }

    public List<KylinOrderRefundsVo> getOrderRefundVoByOrderId(String orderId){
        if (redisUtil.hasKey(KylinRedisConst.ORDER_REFUND_BY_ORDER_ID + orderId)) {
        } else {
            List<KylinOrderRefundsVo> orderRefundsVoList = new ArrayList<>();
            List<KylinOrderRefundsVo> data = mongoTemplate.find(Query.query(Criteria.where("orderTicketsId").is(orderId)), KylinOrderRefundsVo.class, KylinOrderRefundsVo.class.getSimpleName());
            for (KylinOrderRefundsVo item : data) {
                List<KylinOrderRefundEntitiesVo> kylinOrderTicketEntitiesVoList = mongoTemplate.find(Query.query(Criteria.where("orderRefundsId").is(item.getOrderRefundsId())), KylinOrderRefundEntitiesVo.class, KylinOrderRefundEntitiesVo.class.getSimpleName());
                if(kylinOrderTicketEntitiesVoList.size()>1){
                    continue;
                }
                item.setOrderRefundEntitiesVoList(kylinOrderTicketEntitiesVoList);
                List<KylinOrderRefundPicVo> picVos = mongoTemplate.find(Query.query(Criteria.where("orderRefundsId").is(item.getOrderRefundsId())),KylinOrderRefundPicVo.class,KylinOrderRefundPicVo.class.getSimpleName());
                item.setOrderRefundPicVos(picVos);
                orderRefundsVoList.add(item);
            }
            redisUtil.set(KylinRedisConst.ORDER_REFUND_BY_ORDER_ID + orderId, orderRefundsVoList);
        }
        return (List<KylinOrderRefundsVo>) redisUtil.get(KylinRedisConst.ORDER_REFUND_BY_ORDER_ID + orderId);
    }

    public void delOrderRefundVo(String orderRefundsId){
        redisUtil.del(KylinRedisConst.ORDER_REFUND + orderRefundsId);
    }

    public void delOrderRefundVoByOrderId(String orderId){
        redisUtil.del(KylinRedisConst.ORDER_REFUND_BY_ORDER_ID + orderId);
    }

    /**
     * 获取可退款票单价格
     * @param orderTicketVo         订单vo数据
     * @param orderTicketEntitiesId 票单id
     * @return
     */
    public BigDecimal getCanRefundOrderEntitiesPrice(KylinOrderTicketVo orderTicketVo, List<KylinOrderRefundsVo> kylinOrderRefundsVoBaseList, String orderTicketEntitiesId){
        //单票实付价格
        BigDecimal singlePrice = orderTicketVo.getPriceActual().subtract(orderTicketVo.getPriceExpress()).divide(BigDecimal.valueOf(orderTicketVo.getNumber()));
        //单票剩余未退款金额
        BigDecimal canRefundSinglePrice = new BigDecimal("0.00");
        for (KylinOrderTicketEntitiesVo item : orderTicketVo.getEntitiesVoList()) {
            if (item.getOrderTicketEntitiesId().equals(orderTicketEntitiesId)) {
                canRefundSinglePrice = singlePrice.subtract(item.getRefundPrice()==null?BigDecimal.valueOf(0.00):item.getRefundPrice());
            }
        }
        //订单锁定金额
        BigDecimal orderLockPrice = new BigDecimal("0.00");
        for (KylinOrderRefundsVo refundVo : kylinOrderRefundsVoBaseList) {
            int status = refundVo.getStatus();
            if (status == 0 || status == 3 || status == 5 || status == 7) { //退款流程未完成 金额锁定
                List<KylinOrderRefundEntitiesVo> refundEntitiesVos = refundVo.getOrderRefundEntitiesVoList();
                for (KylinOrderRefundEntitiesVo refundEntitiesVo : refundEntitiesVos) {
                    if (refundEntitiesVo.getOrderTicketEntitiesId().equals(orderTicketEntitiesId)) {
                        orderLockPrice = orderLockPrice.add(refundEntitiesVo.getRefundPrice());
                    }
                }
            }
        }
        //订单可退金额
        BigDecimal refundSinglePrice = canRefundSinglePrice.subtract(orderLockPrice);
        //是否包含快递费
        if (orderTicketVo.getPriceActual().subtract(orderTicketVo.getPriceExpress()).subtract(orderTicketVo.getPriceRefund()).compareTo(canRefundSinglePrice) == 0) {
            refundSinglePrice = refundSinglePrice.add(orderTicketVo.getPriceExpress());
        }
        return refundSinglePrice;
    }
}
