package com.liquidnet.service.platform.utils;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.liquidnet.common.cache.redis.util.RedisDataSourceUtil;
import com.liquidnet.commons.lang.util.CollectionUtil;
import com.liquidnet.commons.lang.util.HttpUtil;
import com.liquidnet.commons.lang.util.JsonUtils;
import com.liquidnet.service.base.constant.RedisKeyExpireConst;
import com.liquidnet.service.candy.param.BackCouponParam;
import com.liquidnet.service.kylin.constant.KylinRedisConst;
import com.liquidnet.service.kylin.dto.vo.KylinApiCameraDevicesVo;
import com.liquidnet.service.kylin.dto.vo.KylinTimePerformanceVo;
import com.liquidnet.service.kylin.dto.vo.express.KylinOrderExpressRouteVo;
import com.liquidnet.service.kylin.dto.vo.express.KylinOrderExpressVo;
import com.liquidnet.service.kylin.dto.vo.mongo.KylinOrderTicketEntitiesVo;
import com.liquidnet.service.kylin.dto.vo.mongo.KylinOrderTicketVo;
import com.liquidnet.service.kylin.dto.vo.mongo.KylinPerformanceVo;
import com.liquidnet.service.kylin.dto.vo.returns.KylinOrderListVo;
import com.liquidnet.service.kylin.entity.KylinBuyNotice;
import com.liquidnet.service.kylin.entity.KylinCamera;
import com.liquidnet.service.kylin.entity.KylinOrderCoupons;
import com.liquidnet.service.kylin.mapper.KylinBuyNoticeMapper;
import com.liquidnet.service.slime.constant.SlimeRedisConst;
import com.liquidnet.service.slime.dto.vo.SlimeFieldsVo;
import com.liquidnet.service.sweet.constant.SweetConstant;
import com.liquidnet.service.sweet.vo.SweetAppletUsersVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
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.stereotype.Component;
import org.springframework.util.MultiValueMap;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

@Component
@Slf4j
public class DataUtils {

    @Autowired
    private KylinBuyNoticeMapper buyNoticeMapper;
    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private RedisDataSourceUtil redisDataSourceUtil;
    @Autowired
    private MongoVoUtils mongoVoUtils;

    @Value("${liquidnet.service.candy.url}")
    private String candyUrl;

    /**
     * 根据 购票须知 id 获取 购票须知文案
     *
     * @param buyNoticeIds 购票须知 数组
     * @return 购票须知 json串
     */
    public String getBuyNoticeJsonString(String[] buyNoticeIds) {
        List<KylinBuyNotice> data = buyNoticeMapper.selectList(new UpdateWrapper<KylinBuyNotice>().in("buy_notice_id", buyNoticeIds));
        return JsonUtils.toJson(data);
    }

    //获取场地redis
    public SlimeFieldsVo getFieldVo(String fieldId) {
        String key = SlimeRedisConst.INFO_FIELD.concat(fieldId);
        SlimeFieldsVo vo = (SlimeFieldsVo) redisDataSourceUtil.getRedisKylinUtil().get(key);
        if (null == vo) {
            vo = mongoTemplate.findOne(Query.query(Criteria.where("fieldId").is(fieldId)), SlimeFieldsVo.class, SlimeFieldsVo.class.getSimpleName());
            redisDataSourceUtil.getRedisKylinUtil().set(key, vo);
        }
        return vo;
    }

    /**
     * 初始化普通库存
     *
     * @param ticketId     票id
     * @param totalGeneral 普通库存
     */
    public void setSurplusGeneral(String ticketId, int totalGeneral) {
        redisDataSourceUtil.getRedisKylinUtil().set(KylinRedisConst.PERFORMANCES_INVENTORY + ticketId + ":" + KylinRedisConst.SURPLUS_GENERAL, totalGeneral);
    }

    /**
     * 获取普通剩余库存
     *
     * @param ticketId 票id
     * @return 普通剩余库存
     */
    public int getSurplusGeneral(String ticketId) {
        return (int) redisDataSourceUtil.getRedisKylinUtil().get(KylinRedisConst.PERFORMANCES_INVENTORY + ticketId + ":" + KylinRedisConst.SURPLUS_GENERAL);
    }

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

    /**
     * 判断 当前库存是否售罄
     *
     * @param ticketId 票id
     * @return boolean
     */
    public boolean ticketIsSoldOut(String ticketId) {
        if (0 >= getSurplusGeneral(ticketId)) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 初始化兑换库存
     *
     * @param ticketId      票id
     * @param totalExchange 兑换库存
     */
    public void setSurplusExchange(String ticketId, int totalExchange) {
        redisDataSourceUtil.getRedisKylinUtil().set(KylinRedisConst.PERFORMANCES_INVENTORY + ticketId + ":" + KylinRedisConst.SURPLUS_EXCHANGE, totalExchange);
    }

    /**
     * 获取兑换剩余库存
     *
     * @param ticketId 票id
     * @return 兑换剩余库存
     */
    public int getSurplusExchange(String ticketId) {
        return (int) redisDataSourceUtil.getRedisKylinUtil().get(KylinRedisConst.PERFORMANCES_INVENTORY + ticketId + ":" + KylinRedisConst.SURPLUS_EXCHANGE);
    }

    /**
     * 变更兑换库存 并 返回 修改后的数量
     *
     * @param ticketId        票id
     * @param surplusExchange 普通库存
     * @return 兑换剩余库存
     */
    public int changeSurplusExchange(String ticketId, int surplusExchange) {
        if (surplusExchange > 0) {
            return (int) redisDataSourceUtil.getRedisKylinUtil().incr(KylinRedisConst.PERFORMANCES_INVENTORY + ticketId + ":" + KylinRedisConst.SURPLUS_EXCHANGE, surplusExchange);
        } else {
            return (int) redisDataSourceUtil.getRedisKylinUtil().decr(KylinRedisConst.PERFORMANCES_INVENTORY + ticketId + ":" + KylinRedisConst.SURPLUS_EXCHANGE, Math.abs(surplusExchange));
        }
    }

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

    public List<KylinOrderListVo> getOrderList(String userId) {
        Object obj = redisDataSourceUtil.getRedisKylinUtil().get(KylinRedisConst.ORDER_LIST + userId);
        if (obj != null) {
            return (List<KylinOrderListVo>) obj;
        } 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());
            for (KylinOrderListVo item : voList) {
                item.setStatus(item.getStatus());
            }
            redisDataSourceUtil.getRedisKylinUtil().set(KylinRedisConst.ORDER_LIST + userId, voList, RedisKeyExpireConst.KYLIN_ORDER_LIST_USERID_EXPIRE);
            return voList;
        }
    }

    /**
     * 演出是否实名
     *
     * @param performanceId
     * @param isTrueName
     */
    public void setPerformanceIsTrueName(String performanceId, int isTrueName) {
        redisDataSourceUtil.getRedisKylinUtil().set(KylinRedisConst.PERFORMANCES_TRUE_NAME + performanceId, isTrueName);
    }

    /**
     * 根据订单id 获取 订单vo 详情
     *
     * @param orderId
     * @return
     */
    public KylinOrderTicketVo getOrderTicketVo(String orderId) {
        Object obj = redisDataSourceUtil.getRedisKylinUtil().get(KylinRedisConst.ORDER + orderId);
        if (obj != null) {
            return (KylinOrderTicketVo) obj;
        } 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);
            redisDataSourceUtil.getRedisKylinUtil().set(KylinRedisConst.ORDER + orderId, ticketData, RedisKeyExpireConst.KYLIN_ORDER_ID_EXPIRE);
            return ticketData;
        }
    }

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


    /**
     * 删除 验票账号 redis
     *
     * @param checkUserId
     */
    public void delCheckUserRedis(String checkUserId) {
        redisDataSourceUtil.getRedisKylinUtil().del(KylinRedisConst.CHECK_USER + checkUserId);
    }


    /**
     * 删除 验票账号关系 vo
     *
     * @param checkUserId
     */
    public void delCheckUserRelationRedis(String checkUserId) {
        redisDataSourceUtil.getRedisKylinUtil().del(KylinRedisConst.CHECK_USER_RELATION + checkUserId);
    }


    public void updatePerformanceMongo(String performanceIds, KylinPerformanceVo paramVo) {
        //查询 mysql 数据
        KylinPerformanceVo vo;
        if (null == paramVo) {
            vo = mongoVoUtils.combinePerformanceVoData(performanceIds);
        } else {
            vo = paramVo;
        }
        if (vo != null) {
            try {
                //删除 mongo数据
                mongoTemplate.remove(Query.query(Criteria.where("performancesId").is(performanceIds)), KylinPerformanceVo.class, KylinPerformanceVo.class.getSimpleName());
            } catch (Exception e) {
                e.printStackTrace();
            }
            try {
                //新增 mongo数据
                mongoTemplate.insert(vo, KylinPerformanceVo.class.getSimpleName());
            } catch (Exception e) {
                e.printStackTrace();
            }
            try {
                //删除redis
                redisDataSourceUtil.getRedisKylinUtil().del(KylinRedisConst.PERFORMANCES + performanceIds);
                // 大龙相关 演出列表
                redisDataSourceUtil.getRedisKylinUtil().del(KylinRedisConst.PERFORMANCES_LIST_CITY.concat(String.valueOf(vo.getCityId())));
                redisDataSourceUtil.getRedisKylinUtil().del(KylinRedisConst.PERFORMANCES_ROADLIST + vo.getRoadShowId());
                redisDataSourceUtil.getRedisKylinUtil().del(KylinRedisConst.PERFORMANCES_LIST_SYSTEM_RECOMMEND);
                redisDataSourceUtil.getRedisKylinUtil().del(KylinRedisConst.PERFORMANCES_LIST_RECOMMEND);
                redisDataSourceUtil.getRedisKylinUtil().del(KylinRedisConst.PERFORMANCES_LIST_NOTICE);
                redisDataSourceUtil.getRedisKylinUtil().del(KylinRedisConst.PERFORMANCES_LIST_EXCLUSIVE);
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
        }
    }

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

        int isTrueName = getPerformanceIsTrueName(performanceId);

        redisKeyUid = KylinRedisConst.USERID_BUY_INFO + userId;
        redisKeyIdCard = KylinRedisConst.IDCARD_BUY_INFO + idCard;
        String performanceIdKeyUid = redisKeyUid + ":" + KylinRedisConst.PERFORMANCE_ID + ":" + performanceId;
        String ticketIdKeyUid = redisKeyUid + ":" + KylinRedisConst.TICKET_ID + ":" + ticketId;
        if (isTrueName != 0) {
            performanceIdKeyIdCard = redisKeyIdCard + ":" + KylinRedisConst.PERFORMANCE_ID + ":" + performanceId;
            ticketIdKeyIdCard = redisKeyIdCard + ":" + KylinRedisConst.TICKET_ID + ":" + ticketId;
        }

        if (buyCount > 0) {
            redisDataSourceUtil.getRedisKylinUtil().incr(ticketIdKeyUid, buyCount);
            redisDataSourceUtil.getRedisKylinUtil().incr(performanceIdKeyUid, buyCount);
            if (isTrueName != 0) {
                redisDataSourceUtil.getRedisKylinUtil().incr(ticketIdKeyIdCard, buyCount);
                redisDataSourceUtil.getRedisKylinUtil().incr(performanceIdKeyIdCard, buyCount);
            }
        } else {
            if (isTrueName != 0) {
                redisDataSourceUtil.getRedisKylinUtil().decr(ticketIdKeyIdCard, Math.abs(buyCount));
                redisDataSourceUtil.getRedisKylinUtil().decr(performanceIdKeyIdCard, Math.abs(buyCount));
            }
            redisDataSourceUtil.getRedisKylinUtil().decr(ticketIdKeyUid, Math.abs(buyCount));
            redisDataSourceUtil.getRedisKylinUtil().decr(performanceIdKeyUid, Math.abs(buyCount));
        }
    }


    // 获取 用户维度 演出购买数量
    public int getUserPBuyCount(String userId, String performanceId) {
        try {
            return (int) redisDataSourceUtil.getRedisKylinUtil().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) redisDataSourceUtil.getRedisKylinUtil().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) redisDataSourceUtil.getRedisKylinUtil().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) redisDataSourceUtil.getRedisKylinUtil().get(KylinRedisConst.IDCARD_BUY_INFO + idCard + ":" + KylinRedisConst.TICKET_ID + ":" + ticketId);
        } catch (Exception e) {
            return 0;
        }
    }

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

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

    /**
     * 演出是否实名
     *
     * @param performanceId
     */
    public int getPerformanceIsTrueName(String performanceId) {
        Object obj = redisDataSourceUtil.getRedisKylinUtil().get(KylinRedisConst.PERFORMANCES_TRUE_NAME + performanceId);
        if (obj != null) {
            return (int) obj;
        } else {
            int isTrueName = getPerformanceVo(performanceId).getIsTrueName();
            redisDataSourceUtil.getRedisKylinUtil().set(KylinRedisConst.PERFORMANCES_TRUE_NAME + performanceId, isTrueName);
            return isTrueName;
        }
    }


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

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

    /**
     * 演出订单快递信息
     *
     * @param orderId
     * @param kylinOrderExpressVo
     */
    public void setOrderExpressInfo(String orderId, KylinOrderExpressVo kylinOrderExpressVo) {
        String redisKey = KylinRedisConst.ORDER_EXPRESS_INFO.concat(orderId);
        redisDataSourceUtil.getRedisKylinUtil().set(redisKey, kylinOrderExpressVo);
    }

    /**
     * 演出订单快递路由
     */
    public LinkedList<KylinOrderExpressRouteVo> getOrderExpressRoute(String orderTicketsId) { // 获取
        String redisKey = KylinRedisConst.ORDER_ROUTE_INFO.concat(orderTicketsId);
        return (LinkedList<KylinOrderExpressRouteVo>) redisDataSourceUtil.getRedisKylinUtil().get(redisKey);
    }

    public void setOrderExpressRoute(String orderTicketsId, LinkedList<KylinOrderExpressRouteVo> routeList) {
        String redisKey = KylinRedisConst.ORDER_ROUTE_INFO.concat(orderTicketsId);
        redisDataSourceUtil.getRedisKylinUtil().set(redisKey, routeList);
    }

    // 获取订单券的使用情况
    public ArrayList<KylinOrderCoupons> getOrderCoupon(String orderId) {
        String redisKey = KylinRedisConst.ORDER_COUPON.concat(orderId);
        Object obj = redisDataSourceUtil.getRedisKylinUtil().get(redisKey);
        if (obj == null) {
            return ObjectUtil.getKylinOrderCouponsArrayList();
        } else {
            return (ArrayList<KylinOrderCoupons>) obj;
        }
    }

    //删除 演出定时任务
    public Object delTimeLine(String performances) {
        return mongoTemplate.remove(Query.query(Criteria.where("performance").is(performances)), KylinTimePerformanceVo.class, KylinTimePerformanceVo.class.getSimpleName());
    }

    //获取SessionCode
    public String getSessionCode(String ticketTimeId) {
        return (String) redisDataSourceUtil.getRedisKylinUtil().get(KylinRedisConst.TIMES_SESSION_CODE.concat(ticketTimeId));
    }

    public SweetAppletUsersVo getSweetAppletUsersOfUnionId(String unionId) {
        String redisKey = SweetConstant.REDIS_KEY_SWEET_APPLET_USERS_UNIONID.concat(unionId);
        Object obj = redisDataSourceUtil.getRedisSweetUtil().get(redisKey);
        if (null == obj) {
            return null;
        } else {
            SweetAppletUsersVo sweetAppletUsersVo = (SweetAppletUsersVo) obj;
            return sweetAppletUsersVo;
        }
    }

    public void setCameraDevices(String fieldId, ArrayList<KylinApiCameraDevicesVo> kylinApiCameraDevicesVoArrayList) {
        String redisKey = KylinRedisConst.CAMERA_DEVICES_FIELD.concat(fieldId);
        redisDataSourceUtil.getRedisKylinUtil().set(redisKey, kylinApiCameraDevicesVoArrayList);
    }

    public void setCameraDevicePersonNum(String cameraId, long count) {
        String redisKey = KylinRedisConst.CAMERA_DEVICE_PERSON_NUM.concat(cameraId);
        redisDataSourceUtil.getRedisKylinUtil().set(redisKey, count);
    }

    public List<KylinCamera> getCameraDevicesList() {
        String redisKey = KylinRedisConst.CAMERA_DEVICES;
        Object obj = redisDataSourceUtil.getRedisKylinUtil().get(redisKey);
        if (null == obj) {
            return null;
        } else {
            return (List<KylinCamera>) obj;
        }
    }

    public void setCameraDevicesList(List<KylinCamera> cameraList) {
        String redisKey = KylinRedisConst.CAMERA_DEVICES;
        redisDataSourceUtil.getRedisKylinUtil().set(redisKey, cameraList);
    }

    public void delCameraDevicesList() {
        String redisKey = KylinRedisConst.CAMERA_DEVICES;
        redisDataSourceUtil.getRedisKylinUtil().del(redisKey);
    }

    public void setCameraDeviceInfo(KylinCamera camera) {
        String redisKey = KylinRedisConst.CAMERA_DEVICE_GB_INFO.concat(camera.getGbId());
        redisDataSourceUtil.getRedisKylinUtil().set(redisKey, camera);
    }

    public KylinCamera getCameraDeviceInfo(String streamName) {
        String redisKey = KylinRedisConst.CAMERA_DEVICE_GB_INFO.concat(streamName);
        Object obj = redisDataSourceUtil.getRedisKylinUtil().get(redisKey);
        if (null == obj) {
            return null;
        } else {
            return (KylinCamera) obj;
        }
    }

    public void backCoupon(String uCouponId, String uid) {
        try {
            BackCouponParam param = BackCouponParam.getNew();
            param.setuCouponIds(uCouponId);
            param.setUid(uid);
            MultiValueMap<String, String> header = CollectionUtil.linkedMultiValueMapStringString();
            ArrayList<BackCouponParam> params = new ArrayList();
            params.add(param);
            String jsonString = JSON.toJSONString(params);
            String returnData = HttpUtil.postRaw(candyUrl + "/candy-coupon/useBack", jsonString, header);
        } catch (Exception e) {
            log.error("回退券ERROR:{}", e);
        }
    }
}
