package com.clx.performance.listener;

import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.clx.open.sdk.callback.OpenCallBackClient;
import com.clx.open.sdk.callback.message.OrderChildLastOneMessage;
import com.clx.open.sdk.callback.message.OrderChildMessage;
import com.clx.open.sdk.callback.message.OrderChildSyncMessage;
import com.clx.open.sdk.enums.ResultStatusEnum;
import com.clx.order.enums.OrderEnum;
import com.clx.order.enums.SyncPlatformEnum;
import com.clx.order.feign.OrderFeign;
import com.clx.order.vo.feign.FeignOrderVO;
import com.clx.performance.common.MqWrapper;
import com.clx.performance.config.ThirdAppConfig;
import com.clx.performance.constant.RabbitKeyConstants;
import com.clx.performance.dao.OrderGoodsDao;
import com.clx.performance.dao.OrderChildImageDao;
import com.clx.performance.dto.dts.DataTransportDTO;
import com.clx.performance.enums.DtsOperationTypeEnum;
import com.clx.performance.enums.OrderChildEnum;
import com.clx.performance.enums.PerformanceResultEnum;
import com.clx.performance.enums.OrderChildPoundAuditEnum;
import com.clx.performance.event.OrderChildCancelEvent;
import com.clx.performance.extranal.user.DriverService;
import com.clx.performance.model.OrderChild;
import com.clx.performance.model.OrderGoods;
import com.clx.performance.model.OrderChildImage;
import com.clx.performance.service.LastTruckService;
import com.clx.performance.struct.OrderChildStruct;
import com.clx.user.feign.TruckFeign;
import com.clx.user.vo.feign.FeignDriverTruckModelVo;
import com.clx.user.vo.feign.TruckInfoFeignVo;
import com.msl.common.enums.ResultCodeEnum;
import com.msl.common.result.Result;
import com.msl.common.utils.DtsMapConvertUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

import static com.clx.performance.constant.RabbitKeyConstants.*;

@Slf4j
@Component
@AllArgsConstructor
public class OrderChildDtsListener  {
    private final OrderFeign orderFeign;
    private final LastTruckService lastTruckService;
    private final DriverService driverService;
    private final ApplicationEventPublisher applicationEventPublisher;
    private final ThirdAppConfig thirdAppConfig;
    private final OrderChildStruct orderChildStruct;
    private final RabbitTemplate rabbitTemplate;

    private final OrderGoodsDao orderGoodsDao;
    private final TruckFeign truckFeign;
    private final OrderChildImageDao orderChildImageDao;



    @RabbitListener(queues = RabbitKeyConstants.CLX_PERFORMANCE_ORDER_CHILD_QUEUE)
    public void onMessage(Message message) {
        try {
            String msg = new String(message.getBody());
            log.info("DTS消息同步开始, database:clx_performance.order_child, msg:{}", msg);
            DataTransportDTO dataTransportDTO = JSON.parseObject(msg, DataTransportDTO.class);
            log.info("DTS消息同步开始, database:clx_performance.order_child, 实体:{}", dataTransportDTO);
            log.info("操作类型：{}",dataTransportDTO.getOperationType().getCode());
            OrderChild before = DtsMapConvertUtil.convert(dataTransportDTO.getBeforeMap(), new OrderChild());
            OrderChild after = DtsMapConvertUtil.convert(dataTransportDTO.getAfterMap(), new OrderChild());

            thirdpartySync(DtsMapConvertUtil.convert(dataTransportDTO.getAfterMap(), new OrderChildSyncMessage()));

            if(Objects.equals(DtsOperationTypeEnum.INSERT.getCode(),dataTransportDTO.getOperationType().getCode())){
                syncPerformanceProgress(before,after,DtsOperationTypeEnum.INSERT.getCode());
                //同步after数据
                log.info("新增:{}",after);
                if(OrderChildEnum.SYNC_STATUS_lIST.contains(after.getStatus()) && !Objects.equals(before.getStatus(),after.getStatus())){
                    orderChildChangeAfter(after);
                }
            }else if(Objects.equals(DtsOperationTypeEnum.UPDATE.getCode(),dataTransportDTO.getOperationType().getCode())){
                log.info("修改:{}",after);
                syncPerformanceProgress(before,after,DtsOperationTypeEnum.UPDATE.getCode());
                if(OrderChildEnum.SYNC_STATUS_lIST.contains(after.getStatus()) &&
                        (!Objects.equals(before.getStatus(),after.getStatus()) ||
                         !Objects.equals(before.getLoadNet(),after.getLoadNet())) ||
                         !Objects.equals(before.getUnloadNet(),after.getUnloadNet()) ||
                         !Objects.equals(before.getPoundStatus(),after.getPoundStatus())
                        ){
                    orderChildChangeAfter(after);
                }
                if(OrderChildEnum.DTS_LISTEN_CANCEL_lIST.contains(after.getStatus())){
                    //运单取消释放借款冻结金额
                    log.info("DTS运单取消释放借款冻结金额");
                    applicationEventPublisher.publishEvent(new OrderChildCancelEvent(this, after.getChildNo()));
                }
                afterLogicalProcessing(before,after);

            }else if(Objects.equals(DtsOperationTypeEnum.DELETE.getCode(),dataTransportDTO.getOperationType().getCode())){
                //数据删除
                log.info("删除:{}",before);

            }
        } catch (Exception e) {
            log.info("DTS消息同步失败, database:clx_performance.order_child, error:{}", e.getMessage());
        }
    }

    public void orderChildChangeAfter(OrderChild orderChild){
        FeignOrderVO orderInfoFeign = orderFeign.getOrderInfoFeign(orderChild.getOrderNo());
        if (orderInfoFeign == null) {
            return;
        }

        OrderChildMessage after = orderChildStruct.convertMessage(orderChild);


        //同步交易平台的运单
        if(Objects.equals(orderInfoFeign.getOrderSource(), SyncPlatformEnum.Source.TRADE_PLATFORM.getCode())){

            String truckModel = after.getTruckModel();
            if(StringUtils.isNotBlank(truckModel)){
                FeignDriverTruckModelVo dumpType = driverService.getDumpType(truckModel).orElseThrow(ResultCodeEnum.FAIL);
                after.setDumpType(dumpType.getDumpType());
            }
            buildOrderOtherInfo(after);

            //同步after数据
            Optional<OrderChildEnum.Status> option = OrderChildEnum.Status.getByCode(after.getStatus());
            String statusName = option.isPresent()?option.get().getName():"未知状态";
            log.info("同步运单数据，运单号:{},运单状态:{}",after.getChildNo(),statusName);
            //如果订单是取消操作，同步给交易平台统一 10000 的code
            if(OrderChildEnum.DTS_LISTEN_CANCEL_lIST.contains(after.getStatus())){
                after.setStatus(com.clx.open.sdk.enums.OrderChildEnum.Status.COMMON_CANCEL.getCode());
            }
            after.setLastFlag(ResultStatusEnum.NO.getCode());
            String data = JSON.toJSONString(after);
            OpenCallBackClient openCallBackClient = thirdAppConfig.getOpenCallBackClient(orderInfoFeign.getOrderSource().toString());
            Result<?> result = openCallBackClient.encryptPost(data,after.topic());
            log.info("运单信息同步，运单编号:{},响应结果:{}",after.getChildNo(),JSON.toJSONString(result));
            syncLastTruck(orderInfoFeign,after);
            return;
        }

        if (Objects.equals(orderInfoFeign.getOrderSource(), SyncPlatformEnum.Source.NEW_OWNER_CLIENT.getCode())) {
            if(Objects.equals(com.clx.open.sdk.enums.OrderChildEnum.Status.COMMON_CANCEL.getCode(),after.getStatus()) ||
                    (after.getStatus() >= OrderChildEnum.Status.ARRIVE_RECEIVE.getCode()  && after.getStatus() <= OrderChildEnum.Status.COMPLETE.getCode())){
                OrderChild child;
                if(Objects.equals(orderInfoFeign.getOrderStatus(), OrderEnum.Status.COMPLETED.getCode()) ||
                        Objects.equals(orderInfoFeign.getOrderStatus(), OrderEnum.Status.SUCCESS.getCode())) { //订单变成已完成 || 已完结
                    OrderEnum.Status byCode = OrderEnum.Status.getByCode(orderInfoFeign.getOrderStatus());
                    log.info("订单号:{},运单号：{},订单状态：{},开始查询最后一车运单===========" ,orderInfoFeign.getOrderNo(),after.getChildNo(),
                            Objects.nonNull(byCode)?byCode.getName():"未知状态");
                    child = lastTruckService.getOrderCompleteLastTruck(after.getOrderNo());
                }else{  // 订单除  已完成 || 已完结  外的其他状态
                    child = lastTruckService.getLastTruckChild(after.getOrderNo());
                }
                if (Objects.nonNull(child)) {
                    log.info("开始同步新货主客户端最后一车的运单，运单编号:{}", child.getChildNo());
                    OpenCallBackClient openCallBackClient = thirdAppConfig.getOpenCallBackClient(SyncPlatformEnum.Source.NEW_OWNER_CLIENT.getCode().toString());
                    OrderChildLastOneMessage message = new OrderChildLastOneMessage();
                    message.setChildNo(child.getChildNo());
                    Result<?> result = openCallBackClient.encryptPost(JSONUtil.parse(message).toString(), message.topic());
                    log.info("结束同步新货主客户端最后一车的运单，运单编号:{}，响应结果:{}", child.getChildNo(), JSONUtil.parse(result));
                }

            }
        }
    }
    //构建运单其它信息
    public void buildOrderOtherInfo(OrderChildMessage after){
        //查询挂车车牌号
        if(Objects.nonNull(after.getTruckId())){
            log.info("通过车辆id:{} 开始查找运单号:{},车牌号:{} 对应的车辆信息开始查询===",
                    after.getTruckId(),after.getChildNo(),after.getTruckNo());
            Result<TruckInfoFeignVo> result = truckFeign.getTruckInfo(after.getTruckId());
            if(!result.succeed()){
                log.warn("通过车辆id:{} 开始查找运单号:{},车牌号:{} 的车辆信息未查询到,响应结果:{}",
                        after.getTruckId(),after.getChildNo(),after.getTruckNo(),result);
            }else{
                log.warn("通过车辆id:{} 开始查找运单号:{},车牌号:{} 查询到对应的车辆信息,响应结果:{}",
                        after.getTruckId(),after.getChildNo(),after.getTruckNo(),result);
                after.setTruckNo2(result.getData().getTruckNo2());
            }
        }
        //查询收发货地对应的磅单图片信息，
        if(Objects.equals(after.getPoundStatus(), OrderChildPoundAuditEnum.Status.APPROVED.getCode())){
            List<OrderChildImage> orderChildImages = orderChildImageDao.listByField(OrderChildImage::getChildNo,
                    after.getChildNo());
            if(CollectionUtils.isNotEmpty(orderChildImages)){
                List<String> sendAddressPoundPicList = new ArrayList<>();
                List<String> receiveAddressPoundPicList = new ArrayList<>();
                orderChildImages.forEach(item->{
                    if(Objects.equals(item.getType(),OrderChildImage.Type.LOAD.getCode())){
                        sendAddressPoundPicList.add(item.getImage());
                    }
                    if(Objects.equals(item.getType(),OrderChildImage.Type.UNLOAD.getCode())){
                        receiveAddressPoundPicList.add(item.getImage());
                    }
                });
                after.setSendAddressPoundPicList(sendAddressPoundPicList);
                after.setReceiveAddressPoundPicList(receiveAddressPoundPicList);
            }
        }
    }

    public void syncLastTruck(FeignOrderVO orderInfoFeign,OrderChildMessage after){
        //当运单状态为到达目的地之后的状态时候，需要判断最后一车的逻辑
        if(Objects.equals(com.clx.open.sdk.enums.OrderChildEnum.Status.COMMON_CANCEL.getCode(),after.getStatus()) ||
                (after.getStatus() >= OrderChildEnum.Status.ARRIVE_RECEIVE.getCode()  && after.getStatus() <= OrderChildEnum.Status.COMPLETE.getCode())){
            OrderChild child;
            if(Objects.equals(orderInfoFeign.getOrderStatus(), OrderEnum.Status.COMPLETED.getCode()) ||
                    Objects.equals(orderInfoFeign.getOrderStatus(), OrderEnum.Status.SUCCESS.getCode())) { //订单变成已完成 || 已完结
                OrderEnum.Status byCode = OrderEnum.Status.getByCode(orderInfoFeign.getOrderStatus());
                log.info("订单号:{},运单号：{},订单状态：{},开始查询最后一车运单===========" ,orderInfoFeign.getOrderNo(),after.getChildNo(),
                        Objects.nonNull(byCode)?byCode.getName():"未知状态");
                child = lastTruckService.getOrderCompleteLastTruck(after.getOrderNo());
            }else{  // 订单除  已完成 || 已完结  外的其他状态
                child = lastTruckService.getLastTruckChild(after.getOrderNo());
            }
            if(Objects.nonNull(child)){
                lastTruckService.syncLastTruckChild(child);
            }

        }
    }

    /**
     * 第三方同步
     */
    public void thirdpartySync(OrderChildSyncMessage message){
        FeignOrderVO orderInfoFeign = orderFeign.getOrderInfoFeign(message.getOrderNo());
        if (orderInfoFeign == null) {
            return;
        }
        // 同步新货主客户端的运单
        if(!Objects.equals(orderInfoFeign.getOrderSource(), SyncPlatformEnum.Source.NEW_OWNER_CLIENT.getCode())){
            return;
        }

        try{
            OpenCallBackClient openCallBackClient = thirdAppConfig.getOpenCallBackClient(SyncPlatformEnum.Source.NEW_OWNER_CLIENT.getCode().toString());
            log.info("运单同步:{}", message.getId());
            Result<?> result = openCallBackClient.encryptPost(JSON.toJSONString(message), message.topic());
            if (result.succeed()) {
                log.info("运单同步成功:{}", message.getId());


            }else{
                log.info("运单同步失败:{}", message.getId());
            }

        }catch (Exception e){

        }

    }

    //同步履约进度表-----运单部分
    public void syncPerformanceProgress(OrderChild before,OrderChild after, Integer updateType){
        boolean isSend = false;
        if(Objects.equals(updateType,DtsOperationTypeEnum.INSERT.getCode())){
            isSend = true;
        }
        if(Objects.equals(updateType,DtsOperationTypeEnum.UPDATE.getCode()) &&
                (!Objects.equals(before.getStatus(),after.getStatus()) ||
                 !Objects.equals(before.getLoadNet(),after.getLoadNet())) ||
                 !Objects.equals(before.getUnloadNet(),after.getUnloadNet())
        ){
            isSend = true;
        }
        if(isSend){
            log.info("开始发送同步履约进度表消息,订单号:{},运单号:{}", after.getOrderNo(),after.getChildNo());
            Message body = MessageBuilder.withBody(JSON.toJSONString(new MqWrapper<>(after)).getBytes()).build();
            rabbitTemplate.send(SYNC_PERFORMANCE_PROGRESS_FOR_ORDER_CHILD_EXCHANGE,
                    SYNC_PERFORMANCE_PROGRESS_FOR_ORDER_CHILD_ROUTING_KEY, body);
            log.info("结束发送同步履约进度表消息,订单号:{},运单号:{}", after.getOrderNo(),after.getChildNo());
        }
    }

    /**
     * 后续逻辑处理
     * @param before
     * @param after
     */
    private void afterLogicalProcessing(OrderChild before,OrderChild after){
        BigDecimal beforeLoadNet = before.getLoadNet();//变化前装车净重
        BigDecimal afterLoadNet = after.getLoadNet();//变化后装车净重
        Integer beforeStatus = before.getStatus();//之前状态
        Integer afterStatus = after.getStatus();//之后状态
        String orderGoodsNo = after.getOrderGoodsNo();//货单号
        log.info("之前装车净重:{},之后装车净重:{},之前运单状态:{},之后运单状态:{},货单号:{}",
                beforeLoadNet,afterLoadNet,beforeStatus,afterStatus,orderGoodsNo);

        OrderGoods orderGoods = orderGoodsDao.getByOrderGoodsNo(orderGoodsNo)
                .orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);//货单详情查询

        BigDecimal loadNet;//定义实际装车吨数
        if(Objects.nonNull(afterLoadNet)){
            if(Objects.equals(after.getStatus(),OrderChildEnum.Status.LOAD.getCode())
                    && !Objects.equals(afterStatus,beforeStatus)){//第一次装车
                loadNet = afterLoadNet;
            }else if(OrderChildEnum.DTS_LISTEN_CANCEL_lIST.contains(after.getStatus())){//装车后取消
                //运单取消,货单装车吨数需要减掉
                loadNet = afterLoadNet.negate();
            }else if(!Objects.equals(beforeLoadNet,afterLoadNet)){//修改装车吨数
                loadNet = afterLoadNet.subtract(beforeLoadNet);
            }else{
                return;
            }
            //货单已经装车吨数
            BigDecimal alreadyLoadWeight = orderGoods.getAlreadyLoadWeight() == null? BigDecimal.ZERO:orderGoods.getAlreadyLoadWeight();
            alreadyLoadWeight = alreadyLoadWeight.add(loadNet);

            //更新货单已经装车吨数
            OrderGoods og = new OrderGoods();
            og.setId(orderGoods.getId());
            og.setAlreadyLoadWeight(alreadyLoadWeight);
            orderGoodsDao.updateEntityByKey(og);
        }





    }

}
