package com.liquidnet.service.order.service.impl;

import com.alibaba.fastjson.JSON;
import com.liquidnet.common.mq.constant.MQConst;
import com.liquidnet.commons.lang.util.CollectionUtil;
import com.liquidnet.commons.lang.util.DateUtil;
import com.liquidnet.commons.lang.util.IDGenerator;
import com.liquidnet.commons.lang.util.JsonUtils;
import com.liquidnet.service.base.SqlMapping;
import com.liquidnet.service.kylin.constant.KylinTableStatusConst;
import com.liquidnet.service.kylin.dto.vo.mongo.KylinOrderRefundEntitiesVo;
import com.liquidnet.service.kylin.dto.vo.mongo.KylinOrderRefundPicVo;
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.returns.KylinOrderRefundsVo;
import com.liquidnet.service.kylin.entity.*;
import com.liquidnet.service.order.utils.DataUtils;
import com.liquidnet.service.order.utils.ObjectUtil;
import com.liquidnet.service.order.utils.OrderUtils;
import com.mongodb.BasicDBObject;
import com.mongodb.client.result.UpdateResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
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.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.LinkedList;
import java.util.List;

/**
 * <p>
 * 订单退款表 服务实现类 处理数据 退款后状态的变化
 * </p>
 *
 * @author jiaangxiulong
 * @since 2021-05-26
 */
@Slf4j
@Service
public class KylinRefundsStatusServiceImpl {

    @Autowired
    MongoTemplate mongoTemplate;

    @Autowired
    private DataUtils dataUtils;

    @Autowired
    private OrderUtils orderUtils;
    @Autowired
    private RabbitTemplate rabbitTemplate;

    public Boolean orderTicketRefunding(
            KylinOrderTicketVo orderInfo, String orderTicketsId,
            BigDecimal RefundPriceExpress,
            List<String> ticketEntityIds, List<BigDecimal> entitiesPrice
    ) {
        if (CollectionUtil.isEmpty(ticketEntityIds)) {
            return false;
        }
        // 基础数据
        String authId = "";
        String authName = "system_overtime_order_refund";
        String reason = "订单支付超时自动退款";
        // 本次退款票总金额
        BigDecimal entitiesPriceSum = entitiesPrice.stream().reduce(BigDecimal.ZERO, BigDecimal::add);

        // 更新数据
        // 订单状态表 和 缓存
        LocalDateTime nowTime = LocalDateTime.now();
        String nowTimeStr = DateUtil.Formatter.yyyyMMddHHmmss.format(nowTime);
        KylinOrderTicketStatus orderStatusTable = KylinOrderTicketStatus.getNew();
        orderStatusTable.setStatus(KylinTableStatusConst.ORDER_STATUS3);
        orderStatusTable.setUpdatedAt(nowTime);

        KylinOrderTicketVo kylinOrderTicketVo = KylinOrderTicketVo.getNew();
        kylinOrderTicketVo.setStatus(KylinTableStatusConst.ORDER_STATUS3);
        kylinOrderTicketVo.setUpdatedAt(nowTimeStr);
        BasicDBObject orderObject = new BasicDBObject("$set", JSON.parse(JsonUtils.toJson(kylinOrderTicketVo)));
        mongoTemplate.getCollection(KylinOrderTicketVo.class.getSimpleName()).updateOne(
                Query.query(Criteria.where("orderTicketsId").is(orderTicketsId)).getQueryObject(),
                orderObject
        );
        dataUtils.delOrderTicketRedis(orderTicketsId);
        orderUtils.resetOrderListVo(orderInfo.getUserId(), 2, orderTicketsId, null);


        // 订单入场人表 和 缓存
        KylinOrderTicketEntities entitiesTable = KylinOrderTicketEntities.getNew();
        entitiesTable.setIsPayment(KylinTableStatusConst.ENTITIES_IS_PAYMENT2);
        entitiesTable.setUpdatedAt(nowTime);

        KylinOrderTicketEntitiesVo kylinOrderTicketEntitiesVo = KylinOrderTicketEntitiesVo.getNew();
        kylinOrderTicketEntitiesVo.setIsPayment(KylinTableStatusConst.ENTITIES_IS_PAYMENT2);
        kylinOrderTicketEntitiesVo.setUpdatedAt(nowTimeStr);
        BasicDBObject entitiesObject = new BasicDBObject("$set", JSON.parse(JsonUtils.toJson(kylinOrderTicketEntitiesVo)));

        LinkedList<Object[]> sqlsDataB = ObjectUtil.cloneLinkedListObj();
        for (String v : ticketEntityIds) {
            Object[] objectB = ObjectUtil.cloneObjectsArray();
            objectB[0] = entitiesTable.getIsPayment();
            objectB[1] = entitiesTable.getUpdatedAt();
            objectB[2] = v;
            objectB[3] = orderInfo.getChangeDate();
            objectB[4] = orderInfo.getChangeDate();
            sqlsDataB.add(objectB);

            mongoTemplate.getCollection(KylinOrderTicketEntitiesVo.class.getSimpleName()).updateOne(
                    Query.query(Criteria.where("orderTicketEntitiesId").is(v)).getQueryObject(),
                    entitiesObject
            );
            dataUtils.delOrderTicketEntitiesRedis(v);
        }

        // 退款明细
        KylinOrderRefunds kylinOrderRefunds = KylinOrderRefunds.getNew();
        String orderRefundsId = IDGenerator.nextSnowId();
        kylinOrderRefunds.setOrderRefundsId(orderRefundsId);
        kylinOrderRefunds.setOrderTicketsId(orderTicketsId);
        String orderRefundCode = orderInfo.getOrderCode();
        String codeNum = StringUtils.leftPad(String.valueOf(5), 3, "0");
        kylinOrderRefunds.setOrderRefundCode(orderRefundCode.concat(codeNum));
        kylinOrderRefunds.setPrice(entitiesPriceSum);
        kylinOrderRefunds.setPriceExpress(RefundPriceExpress);
        kylinOrderRefunds.setStatus(KylinTableStatusConst.ORDER_REFUND_STATUS_APPLY);
        kylinOrderRefunds.setType(KylinTableStatusConst.ORDER_REFUND_TYPE_AUTO);
        kylinOrderRefunds.setApplicantId(authId);
        kylinOrderRefunds.setApplicantName(authName);
        kylinOrderRefunds.setApplicantAt(nowTime);
        kylinOrderRefunds.setReason(reason);
        if (RefundPriceExpress.compareTo(BigDecimal.ZERO) > 0 && entitiesPriceSum.compareTo(BigDecimal.ZERO) > 0) {
            kylinOrderRefunds.setRefundCate(KylinTableStatusConst.ORDER_REFUND_CATE3);
        } else if (RefundPriceExpress.compareTo(BigDecimal.ZERO) > 0) {
            kylinOrderRefunds.setRefundCate(KylinTableStatusConst.ORDER_REFUND_CATE2);
        } else if (entitiesPriceSum.compareTo(BigDecimal.ZERO) > 0) {
            kylinOrderRefunds.setRefundCate(KylinTableStatusConst.ORDER_REFUND_CATE1);
        }
        kylinOrderRefunds.setCreatedAt(nowTime);

        /*int rows = kylinOrderRefundsMapper.insert(kylinOrderRefunds);*/

        KylinOrderRefundsVo orderRefundsVo = KylinOrderRefundsVo.getNew();
        BeanUtils.copyProperties(kylinOrderRefunds, orderRefundsVo);
        mongoTemplate.insert(orderRefundsVo, KylinOrderRefundsVo.class.getSimpleName());

        // 退款入场人表
        KylinOrderRefundEntities kylinOrderRefundEntities = KylinOrderRefundEntities.getNew();
        kylinOrderRefundEntities.setOrderRefundsId(orderRefundsId);
        kylinOrderRefundEntities.setCreatedAt(LocalDateTime.now());
        LinkedList<Object[]> sqlsDataD = ObjectUtil.cloneLinkedListObj();
        for (int i = 0; i <= ticketEntityIds.size() - 1; i++) {
            String orderRefundsEntitiesId = IDGenerator.nextSnowId();
            kylinOrderRefundEntities.setOrderRefundsEntitiesId(orderRefundsEntitiesId);
            kylinOrderRefundEntities.setRefundPrice(entitiesPrice.get(i));
            kylinOrderRefundEntities.setOrderTicketEntitiesId(ticketEntityIds.get(i));

            Object[] objectD = ObjectUtil.cloneObjectsArray();
            objectD[0]=kylinOrderRefundEntities.getOrderRefundsEntitiesId();
            objectD[1]=kylinOrderRefundEntities.getOrderRefundsId();
            objectD[2]=kylinOrderRefundEntities.getRefundPrice();
            objectD[3]=kylinOrderRefundEntities.getOrderTicketEntitiesId();
            objectD[4]=kylinOrderRefundEntities.getCreatedAt();
            sqlsDataD.add(objectD);

            KylinOrderRefundEntitiesVo orderRefundEntitiesVo = KylinOrderRefundEntitiesVo.getNew();
            BeanUtils.copyProperties(kylinOrderRefundEntities, orderRefundEntitiesVo);
            mongoTemplate.insert(orderRefundEntitiesVo, KylinOrderRefundEntitiesVo.class.getSimpleName());
        }

        //mq更改数据库
        LinkedList<String> sqls = ObjectUtil.cloneLinkedListStr();
        LinkedList<Object[]> sqlsDataA = ObjectUtil.cloneLinkedListObj();
        LinkedList<Object[]> sqlsDataC = ObjectUtil.cloneLinkedListObj();

        sqls.add(SqlMapping.get("kylin_order_ticket_status.overtimeRefund"));
        sqls.add(SqlMapping.get("kylin_order_ticket_entities.overtimeRefund"));
        sqls.add(SqlMapping.get("kylin_order_refund.overtimeRefund"));
        sqls.add(SqlMapping.get("kylin_order_refund_entities.overtimeRefund"));

        Object[] objectA = ObjectUtil.cloneObjectsArray();
        objectA[0]=orderStatusTable.getStatus();
        objectA[1]=orderStatusTable.getUpdatedAt();
        objectA[2]=orderInfo.getOrderTicketsId();
        objectA[3]=orderInfo.getChangeDate();
        objectA[4]=orderInfo.getChangeDate();
        sqlsDataA.add(objectA);

        Object[] objectC = ObjectUtil.cloneObjectsArray();
        objectC[0]=kylinOrderRefunds.getOrderRefundsId();
        objectC[1]=kylinOrderRefunds.getOrderTicketsId();
        objectC[2]= kylinOrderRefunds.getOrderRefundCode();
        objectC[3]=kylinOrderRefunds.getPrice();
        objectC[4]=kylinOrderRefunds.getPriceExpress();
        objectC[5]=kylinOrderRefunds.getStatus();
        objectC[6]=kylinOrderRefunds.getType();
        objectC[7]=kylinOrderRefunds.getApplicantId();
        objectC[8]=kylinOrderRefunds.getApplicantName();
        objectC[9]=kylinOrderRefunds.getApplicantAt();
        objectC[10]=kylinOrderRefunds.getReason();
        objectC[11]=kylinOrderRefunds.getRefundCate();
        objectC[12]=kylinOrderRefunds.getCreatedAt();
        sqlsDataC.add(objectC);

        rabbitTemplate.convertAndSend(MQConst.EXCHANGES_LIQUIDNET_SQL_ORDER_OVERTIME_REFUND, MQConst.ROUTING_KEY_SQL_ORDER_OVERTIME_REFUND,
                SqlMapping.gets(sqls, sqlsDataA, sqlsDataB, sqlsDataC, sqlsDataD));

        return true;
    }
}
