package com.sckw.report.consumer;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.sckw.core.exception.BusinessException;
import com.sckw.core.utils.BeanUtils;
import com.sckw.core.utils.StringUtils;
import com.sckw.mongo.model.SckwLogisticsOrder;
import com.sckw.mongo.model.SckwTradeOrder;
import com.sckw.mongo.model.SckwWaybillOrder;
import com.sckw.report.dao.SckwLogisticsOrderRepository;
import com.sckw.report.dao.SckwTradeOrderRepository;
import com.sckw.report.dao.SckwWaybillOrderRepository;
import com.sckw.stream.model.SckwBusSum;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.annotation.Transient;
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.mongodb.core.query.Update;
import org.springframework.util.ReflectionUtils;

import java.lang.reflect.Modifier;
import java.util.Optional;
import java.util.function.Consumer;

/**
 * @author zk
 * @desc 接收业务汇总消息
 * @date 2023/7/8 0008
 */
@Configuration
@RequiredArgsConstructor
@Slf4j
public class SckwBusSumConsumer {
    @Autowired
    SckwTradeOrderRepository tradeOrderRepository;
    @Autowired
    SckwLogisticsOrderRepository logisticsOrderRepository;
    @Autowired
    SckwWaybillOrderRepository waybillOrderRepository;
    @Autowired
    private MongoTemplate mongoTemplate;

    private String TRADE_ORDER = "tradeOrder";

    private String LOGISTICS_ORDER = "logisticsOrder";

    private String WAYBILL_ORDER = "waybillOrder";

    /**
     * @desc 消息订阅
     * @author zk
     * @date 2023/7/8
     **/
    @Bean
    public Consumer<SckwBusSum> sckwBusSum() {
        return sckwBusSum -> {
            try {
                addMongodb(sckwBusSum);
            } catch (Exception e) {
                log.error("处理业务数据汇总消息:{}异常", JSON.toJSONString(sckwBusSum), e);
            }
        };
    }

    /**
     * @param busSum rabbitMq业务汇总数据发送/消费对象
     * @desc 业务存储处理
     * @author zk
     * @date 2023/7/8
     **/
    public void addMongodb(SckwBusSum busSum) {
        log.info("busSum:{}", JSONObject.toJSONString(busSum));
        /**初级校验**/
        if (busSum.getObject() == null || StringUtils.isBlank(busSum.getBusSumType()) || busSum.getMethod() == 0) {
            return;
        }

        /**业务存储**/
        /**贸易订单**/
        if (busSum.getBusSumType().equals(TRADE_ORDER)) {
            SckwTradeOrder order = JSONObject.parseObject(JSON.toJSONString(busSum.getObject()), SckwTradeOrder.class);
            order.set_id(order.getTOrderId());
            if (busSum.getMethod() == 1) {
                /**新增**/
                tradeOrderRepository.insert(order);
            } else if (busSum.getMethod() == 2) {
                /**更新**/
                Optional<SckwTradeOrder> optional = tradeOrderRepository.findById(order.get_id());
                SckwTradeOrder order1 = optional.get();
                BeanUtils.copyPropertiesValue(order, order1);
                tradeOrderRepository.save(order1);
            } else {
                Optional<SckwTradeOrder> sckwTradeOrder = tradeOrderRepository.findById(order.get_id());
                if (sckwTradeOrder.isPresent()) {
                    updateById(order, order.get_id(), SckwTradeOrder.class);
                } else {
                    throw new BusinessException("更新交易订单失败，订单：" + order.getTOrderId() + "不存在");
                }
            }
        }

        /**物流订单**/
        if (busSum.getBusSumType().equals(LOGISTICS_ORDER)) {
            SckwLogisticsOrder order = JSONObject.parseObject(JSON.toJSONString(busSum.getObject()), SckwLogisticsOrder.class);
            if (busSum.getMethod() == 1) {
                /**新增**/
                order.set_id(order.getLOrderId() == null ? order.get_id() : order.getLOrderId());
                logisticsOrderRepository.insert(order);
            } else {
                /**更新**/
                order.set_id(order.getLOrderId() == null ? order.get_id() : order.getLOrderId());
                Optional<SckwLogisticsOrder> optional = logisticsOrderRepository.findById(order.get_id());
                SckwLogisticsOrder order1 = optional.get();
                BeanUtils.copyPropertiesValue(order, order1);
                logisticsOrderRepository.save(order1);
            }
        }

        /**车辆运单**/
        if (busSum.getBusSumType().equals(WAYBILL_ORDER)) {
            SckwWaybillOrder order = JSONObject.parseObject(JSON.toJSONString(busSum.getObject()), SckwWaybillOrder.class);
            if (busSum.getMethod() == 1) {
                /**新增**/
                order.set_id(order.getWOrderId() == null ? order.get_id() : order.getWOrderId());
                waybillOrderRepository.insert(order);
            } else if (busSum.getMethod() == 2){
                /**更新**/
                order.set_id(order.getWOrderId() == null ? order.get_id() : order.getWOrderId());
                Optional<SckwWaybillOrder> optional = waybillOrderRepository.findById(order.get_id());
                SckwWaybillOrder order1 = optional.get();
                BeanUtils.copyPropertiesValue(order, order1);
                waybillOrderRepository.save(order1);
            } else {
                /**替换**/
                Optional<SckwWaybillOrder> optional = waybillOrderRepository.findById(order.getWOrderId());
                SckwWaybillOrder order1 = optional.get();

                //新增
                BeanUtils.copyPropertiesValue(order, order1);
                order1.setWOrderId(null);
                order1.setWOrderNo(null);
                order1.setLoadTime(null);
                order1.setUnloadTime(null);
                waybillOrderRepository.insert(order1);
            }
        }
    }

    /**
     * @desc: 根据id非空更新
     * @author: yzc
     * @date: 2023-07-19 8:58
     * @Param obj:
     * @Param clazz:
     * @Param id:
     * @return: void
     */
    private void updateById(Object obj, Long id, Class<?> clazz) {
        // 生成 Update 条件
        final Update update = new Update();
        // 反射遍历 entity 对象，将非空字段设置到 Update 中
        ReflectionUtils.doWithFields(clazz, field -> {
            // 排除指定条件
            if ("_id".equals(field.getName()) // 排除 id 字段，因为作为查询主键
                    || field.getAnnotation(Transient.class) != null // 排除 @Transient 注解的字段，因为非存储字段
                    || Modifier.isStatic(field.getModifiers())) { // 排除静态字段
                return;
            }
            // 设置字段可反射
            if (!field.isAccessible()) {
                field.setAccessible(true);
            }
            // 排除字段为空的情况
            if (field.get(obj) == null) {
                return;
            }
            // 设置更新条件
            update.set(field.getName(), field.get(obj));
        });
        // 防御，避免有业务传递空的 Update 对象
        if (update.getUpdateObject().isEmpty()) {
            return;
        }
        // 执行更新
        mongoTemplate.updateFirst(new Query(Criteria.where("_id").is(id)), update, clazz);
    }

}
