package com.xxfc.platform.vehicle.biz;



import cn.hutool.json.JSONUtil;
import com.github.wxiaoqi.security.common.biz.BaseBiz;
import com.github.wxiaoqi.security.common.exception.BaseException;
import com.github.wxiaoqi.security.common.msg.ObjectRestResponse;
import com.github.wxiaoqi.security.common.util.process.ResultCode;
import com.xxfc.platform.order.entity.BaseOrder;
import com.xxfc.platform.order.feign.OrderFeign;
import com.xxfc.platform.order.pojo.order.PulishReceiveBO;
import com.xxfc.platform.universal.dto.SendMsgDTO;
import com.xxfc.platform.universal.feign.MQSenderFeign;
import com.xxfc.platform.vehicle.entity.*;
import com.xxfc.platform.vehicle.mapper.VehiclePublishReceiveMapper;
import com.xxfc.platform.vehicle.pojo.dto.VehiclePublishReceiveDTO;
import com.xxfc.platform.vehicle.pojo.dto.VehicleReceiveRefundDTO;
import com.xxfc.platform.vehicle.pojo.vo.VehiclePublishReceiveVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import static com.github.wxiaoqi.security.common.config.rabbit.RabbitConstant.*;


@Service
@Slf4j
public class VehiclePublishReceiveBiz extends BaseBiz<VehiclePublishReceiveMapper, VehiclePublishReceive> {


    @Autowired
    VehicleBiz vehicleBiz;

    @Autowired
    VehiclePublishBiz vehiclePublishBiz;

    @Autowired
    VehiclePublishGoodsBiz publishGoodsBiz;

    @Autowired
    VehicleExtensionBiz vehicleExtensionBiz;

    @Autowired
    OrderFeign orderFeign;

    @Autowired
    MQSenderFeign mqSenderFeign;

    @Autowired
    VehicleUseTimeBiz vehicleUseTimeBiz;



    @Transactional(rollbackFor = Exception.class)
    public  BaseOrder  receive(VehiclePublishReceiveDTO publishReceiveDTO){
        Integer publishId = publishReceiveDTO.getPublishId() == null ? 0 : publishReceiveDTO.getPublishId();
        Integer receiveType = publishReceiveDTO.getType() == null ? 0 : publishReceiveDTO.getType();
        String receiveIdStr= publishReceiveDTO.getReceiveIds();
        if (publishId == 0 || receiveType == 0 || ( receiveType == 1 && CollectionUtils.isEmpty(publishReceiveDTO.getReceives()))){
            throw  new BaseException("参数不能为空", ResultCode.FAILED_CODE);
        }
        VehiclePublish vehiclePublish = vehiclePublishBiz.selectById(publishId);
        if (vehiclePublish == null ){
            throw  new BaseException("需求不存在或无效", ResultCode.FAILED_CODE);
        }
        Integer type = vehiclePublish.getType() == null ? 0 : vehiclePublish.getType();
        List<VehiclePublishReceive> receives = publishReceiveDTO.getReceives();
        setVehiclePublishReceive(receives,receiveIdStr);
        List<Integer> receiveIds = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(publishReceiveDTO.getReceives())){
            for (VehiclePublishReceive vehiclePublishReceive : receives){
                Integer id = vehiclePublishReceive.getId() == null ? 0 : vehiclePublishReceive.getId();
                if (id == 0){
                    String vehicleId = vehiclePublishReceive.getVehicleId();
                    Vehicle vehicle = vehicleBiz.selectById(vehicleId);
                    if (vehicle == null ){
                        throw  new BaseException("商品信息不存在", ResultCode.FAILED_CODE);
                    }
                    Integer publishGoodsId = vehiclePublishReceive.getPublishGoodsId() == null ? 0 : vehiclePublishReceive.getPublishGoodsId();
                    VehiclePublishGoods publishGoods = publishGoodsBiz.selectById(publishGoodsId);
                    if (publishGoods == null ){
                        throw  new BaseException("子需求不存在", ResultCode.FAILED_CODE);
                    }
                    String cover = publishGoods.getCover();
                    Integer brandId = publishGoods.getBrandId();
                    Integer categoryId = publishGoods.getCategoryId();
                    String extensionList = publishGoods.getExtensionList();
                    if (type == 1 ){
                        cover = vehicle.getCover();
                        brandId = vehicle.getBrandId();
                        categoryId = vehicle.getCategoryId();
                        extensionList = vehicleExtensionBiz.getExtensionIds(vehicleId);
                    }
                    vehiclePublishReceive.setReceiveCompanyId(publishReceiveDTO.getCompanyId());
                    vehiclePublishReceive.setName(vehicle.getName());
                    vehiclePublishReceive.setGoodsType(vehiclePublish.getGoodsType());
                    vehiclePublishReceive.setCover(cover);
                    vehiclePublishReceive.setBrandId(brandId);
                    vehiclePublishReceive.setCategoryId(categoryId);
                    vehiclePublishReceive.setExtensionList(extensionList);
                    insertSelective(vehiclePublishReceive);
                    id = vehiclePublishReceive.getId();
                }else {
                    VehiclePublishReceive  receive = selectById(id);
                    if (receive == null || !receive.getStatus().equals(VehiclePublishReceiveDTO.PAY)){
                        throw  new BaseException("接单无法确认--id==="+id, ResultCode.FAILED_CODE);
                    }
                }
                receiveIds.add(id);

            }
            publishReceiveDTO.setIds(receiveIds);
            BaseOrder baseOrder = addOrder(publishReceiveDTO);
            if (baseOrder == null)
                throw  new BaseException("下单失败",ResultCode.FAILED_CODE);
            publishReceiveDTO.setOrderNo(baseOrder.getNo());
            mapper.updReceiveById(publishReceiveDTO);
            return  baseOrder;
        }else {
            if (receiveType == 2){
                publishReceiveDTO.setStatus(VehiclePublishReceiveDTO.REFUSE);
                updOrderReceive(publishReceiveDTO);
            }
            return  null;
        }

    }

    public  void  setVehiclePublishReceive(List<VehiclePublishReceive> receives,String receiveIds){
        if (receives == null || receives.size() == 0){
            receives = new ArrayList<>();
            if(StringUtils.isNotBlank(receiveIds)){
                List<Integer> receiveIdList =Arrays.asList(receiveIds.split(",")).parallelStream().map(s -> Integer.valueOf(s)).collect(Collectors.toList());
                for (Integer id : receiveIdList){
                    VehiclePublishReceive vehiclePublishReceive  = new VehiclePublishReceive();
                    vehiclePublishReceive.setId(id);
                    receives.add(vehiclePublishReceive);
                }
            }
        }
    }


    public  List<VehiclePublishReceiveVo> getList(VehiclePublishReceiveDTO publishReceiveDTO){
        return  mapper.selectList(publishReceiveDTO);
    }


    public BaseOrder  addOrder(VehiclePublishReceiveDTO publishReceiveDTO){
        List<VehiclePublishReceiveVo> list = getList(publishReceiveDTO);
        if (list.size() == 0){
            throw  new BaseException("无处理的单", ResultCode.FAILED_CODE);
        }
        PulishReceiveBO pulishReceiveBO = new PulishReceiveBO();
        String receiveIds = publishReceiveDTO.getIds().stream().map(String::valueOf).collect(Collectors.joining(","));
        pulishReceiveBO.setReceiveIds(receiveIds);
        pulishReceiveBO.setRefuseReceiveIds(publishReceiveDTO.getRefuseReceiveIds());
        pulishReceiveBO.setReceiveVos(list);
        pulishReceiveBO.setType(publishReceiveDTO.getType());
        pulishReceiveBO.setCompanyId(publishReceiveDTO.getCompanyId());
        pulishReceiveBO.setPublishId(publishReceiveDTO.getPublishId());
        ObjectRestResponse<BaseOrder> restResponse = orderFeign.add(pulishReceiveBO);
        if (restResponse.getData() == null ){
            throw  new BaseException(restResponse.getMessage(),restResponse.getStatus());
        }
        return  restResponse.getData();
    }


    public  void  updOrderReceive(VehiclePublishReceiveDTO publishReceiveDTO){
        String receiveIds = publishReceiveDTO.getReceiveIds();
        Integer status = publishReceiveDTO.getStatus() == null ? 0 : publishReceiveDTO.getStatus();
        Integer type = publishReceiveDTO.getType() == null ? 0 : publishReceiveDTO.getType();
        Integer publishId = publishReceiveDTO.getPublishId() == null ? 0 : publishReceiveDTO.getPublishId();
        String publishOrderNo = publishReceiveDTO.getOrderNo();
        Integer number = 0;
        VehiclePublishReceive receive = new VehiclePublishReceive();
        if (type == 2){
            receive.setPublishOrderNo(publishOrderNo);
            receive.setAckTime(publishReceiveDTO.getNowTime());
        }
        if (StringUtils.isNotBlank(receiveIds)){
            List<Integer> receiveIdList =Arrays.asList(receiveIds.split(",")).parallelStream().map(s -> Integer.valueOf(s)).collect(Collectors.toList());
            receive.setStatus(status);
            number+=updReceive(receiveIdList,receive);
        }
        String refuseReceiveIds = publishReceiveDTO.getRefuseReceiveIds();
        Integer refuseNumber = 0;
        String orderNoStr = null;
        if (StringUtils.isNotBlank(refuseReceiveIds)){
            List<Integer> refuseReceiveIdList =Arrays.asList(refuseReceiveIds.split(",")).parallelStream().map(s -> Integer.valueOf(s)).collect(Collectors.toList());
            receive.setStatus(2);
            refuseNumber+=updReceive(refuseReceiveIdList,receive);
            if (status.equals( VehiclePublishReceiveDTO.REFUSE)){
                orderNoStr=mapper.getOrderNoStr(null,refuseReceiveIdList);
            }
        }
        if (type == 2){
            number+=refuseNumber;
            vehiclePublishBiz.updConfirmNumber(number,publishId);
            if (StringUtils.isBlank(orderNoStr)){
                orderNoStr=mapper.getOrderNoStr(publishOrderNo,null);
            }
            addVehicleUseTime(publishReceiveDTO);
            VehicleReceiveRefundDTO receiveRefundDTO = new VehicleReceiveRefundDTO();
            receiveRefundDTO.setOrderNoStr(orderNoStr);
            sendQueue(receiveRefundDTO);
        }else if (type == 1){
            if (status.equals( VehiclePublishReceiveDTO.PAY)){
                vehiclePublishBiz.updWaitConfirmNumber(number,publishId);
                addVehicleUseTime(publishReceiveDTO);
            }
        }
    }

    public  void  addVehicleUseTime(VehiclePublishReceiveDTO publishReceiveDTO){
        String receiveIds = publishReceiveDTO.getReceiveIds();
        String refuseReceiveIds = publishReceiveDTO.getRefuseReceiveIds();
        Integer receiveStatus = publishReceiveDTO.getStatus() == null ? 0 : publishReceiveDTO.getStatus();
        List<Integer> receiveIdList = new ArrayList<>();
        if (receiveStatus.equals(VehiclePublishReceiveDTO.PAY) && StringUtils.isNotBlank(receiveIds)){
            List<Integer>  receiveList =Arrays.asList(receiveIds.split(",")).parallelStream().map(s -> Integer.valueOf(s)).collect(Collectors.toList());
            receiveIdList.addAll(receiveList);
        }
        if (StringUtils.isNotBlank(refuseReceiveIds)){
            List<Integer>  refuseList =Arrays.asList(receiveIds.split(",")).parallelStream().map(s -> Integer.valueOf(s)).collect(Collectors.toList());
            receiveIdList.addAll(refuseList);
        }
        if (receiveIdList.size() == 0)
            return;
        for (Integer receiveId : receiveIdList){
            VehiclePublishReceive receive = selectById(receiveId);
            if (receive == null || !(receive.getStatus().equals(VehiclePublishReceiveDTO.PAY) || receive.getStatus().equals(VehiclePublishReceiveDTO.REFUSE)|| receive.getStatus().equals(VehiclePublishReceiveDTO.COLLECT)))
                continue;
            VehiclePublishGoods publishGoods = publishGoodsBiz.selectById(receive.getPublishGoodsId());
            if (publishGoods == null )
                continue;
            VehiclePublish vehiclePublish = vehiclePublishBiz.selectById(publishGoods.getPublishId());
            if (vehiclePublish == null )
                continue;
            Integer companyId = null;
            Long startTime = null;
            Long endTime = null;
            Integer status = 1;
            if (receive.getStatus().equals(VehiclePublishReceiveDTO.PAY)){
                companyId = receive.getReceiveCompanyId();
                startTime = System.currentTimeMillis();
                endTime =  vehiclePublish.getStartTime();
            }else if (receive.getStatus().equals(VehiclePublishReceiveDTO.COLLECT)){
                companyId = receive.getPublishCompanyId();
                startTime = vehiclePublish.getStartTime();
                endTime =  vehiclePublish.getEndTime();
            }else if (receive.getStatus().equals(VehiclePublishReceiveDTO.REFUSE)){
                status = 2;
            }
            VehicleUseTime vehicleUseTime = new VehicleUseTime();
            vehicleUseTime.setVehicleId(receive.getVehicleId());
            vehicleUseTime.setCompanyId(companyId);
            vehicleUseTime.setStartTime(startTime);
            vehicleUseTime.setEndTime(endTime);
            vehicleUseTime.setStatus(status);
            vehicleUseTime.setPublishId(vehiclePublish.getId());
            vehicleUseTimeBiz.addOrUpd(vehicleUseTime);
        }
    }

    public  Integer  updReceive(List<Integer> ids,VehiclePublishReceive receive){
        Integer num = 0;
        for (Integer id : ids){
            receive.setId(id);
            num+=updateSelectiveByIdRe(receive);
        }
        return num;
    }



    public  void  refundReceive(String orderNoStrList){
        if (StringUtils.isBlank(orderNoStrList))
            return;
        List<String> orderNoList =Arrays.asList(orderNoStrList.split(",")).parallelStream().map(s -> String.valueOf(s)).collect(Collectors.toList());
        for (String orderNo : orderNoList){
            VehiclePublishReceiveDTO publishReceiveDTO = new VehiclePublishReceiveDTO();
            publishReceiveDTO.setOrderNo(orderNo);
            List<VehiclePublishReceiveVo> listByOrderNo = getList(publishReceiveDTO);
            Long count = listByOrderNo.stream().filter(x -> x.getStatus().equals(VehiclePublishReceiveDTO.PAY)).count();
            if (count == null || count == 0){
               BigDecimal refundAmount = listByOrderNo.parallelStream().filter(oadTemp ->
                        (Integer.valueOf(VehiclePublishReceiveDTO.REFUSE).equals(oadTemp.getStatus()))
                       ).map(VehiclePublishReceiveVo::getReceiveAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
                if (refundAmount.compareTo(BigDecimal.ZERO) > 0){
                    log.info("-----操作接单退款-----orderNo==="+orderNo+"----refundAmount==="+refundAmount);

                }
            }

        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void  refundReceiveQueue(VehicleReceiveRefundDTO receiveRefundDTO){
        String orderNoStr = receiveRefundDTO.getOrderNoStr();
        if (StringUtils.isNotBlank(orderNoStr)){
            refundReceive(orderNoStr);
        }

    }



    public void sendQueue(VehicleReceiveRefundDTO receiveRefundDTO) {
        try {

            SendMsgDTO sendMsgDTO = new SendMsgDTO() {{
                setExchange(VEHICLE_TOPIC);
            }};
            sendMsgDTO.setJson(JSONUtil.toJsonStr(receiveRefundDTO));
            sendMsgDTO.setRoutKey(KEY_VEHICLE_RECEIVE);
            mqSenderFeign.postSendMessage(sendMsgDTO);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }









}
