package com.xxfc.platform.vehicle.biz;



import cn.hutool.json.JSONUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
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.github.wxiaoqi.security.common.vo.PageDataVO;
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.VehiclePublishFindDTO;
import com.xxfc.platform.vehicle.pojo.dto.VehiclePublishReceiveDTO;
import com.xxfc.platform.vehicle.pojo.dto.VehicleReceiveRefundDTO;
import com.xxfc.platform.vehicle.pojo.vo.ReceiveVo;
import com.xxfc.platform.vehicle.pojo.vo.VehicleExtensionVO;
import com.xxfc.platform.vehicle.pojo.vo.VehiclePublishReceiveVo;
import com.xxfc.platform.vehicle.pojo.vo.VehiclePublishVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
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;

    @Autowired
    VehicleBrandBiz brandBiz;

    @Autowired
    VehicleCategoryBiz categoryBiz;

    @Autowired
    BranchCompanyBiz branchCompanyBiz;



    @Transactional(rollbackFor = Exception.class)
    public  BaseOrder  receive(VehiclePublishReceiveDTO publishReceiveDTO){
        Integer receiveType = publishReceiveDTO.getType() == null ? 0 : publishReceiveDTO.getType();
        publishReceiveDTO = confirmOrder(publishReceiveDTO);
        List<VehiclePublishReceiveVo> receives = publishReceiveDTO.getReceiveVos();
        List<Integer> receiveIds = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(receives)){
            for (VehiclePublishReceive vehiclePublishReceive : receives){
                Integer id = vehiclePublishReceive.getId() == null ? 0 : vehiclePublishReceive.getId();
                if (id == 0){
                    insertSelective(vehiclePublishReceive);
                    id = vehiclePublishReceive.getId();
                }
                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  VehiclePublishReceiveDTO  confirmOrder(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.getReceiveVos()))){
            throw  new BaseException("参数不能为空", ResultCode.FAILED_CODE);
        }
        VehiclePublish vehiclePublish = vehiclePublishBiz.selectById(publishId);
        if (vehiclePublish == null ){
            throw  new BaseException("需求不存在或无效", ResultCode.FAILED_CODE);
        }
        publishReceiveDTO.setVehiclePublish(vehiclePublish);
        Integer type = vehiclePublish.getType() == null ? 0 : vehiclePublish.getType();
        setVehiclePublishReceive(publishReceiveDTO,receiveIdStr);
        List<VehiclePublishReceiveVo> receives = publishReceiveDTO.getReceiveVos();
        BigDecimal goodsAmount = BigDecimal.ZERO;
        BigDecimal payAmount = BigDecimal.ZERO;
        if (CollectionUtils.isNotEmpty(receives)){
            for (VehiclePublishReceiveVo 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);
                    }
                    goodsAmount = publishGoods.getReceiveAmount();
                    payAmount = payAmount.add(goodsAmount);
                    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);
                    vehiclePublishReceive.setReceiveUserId(publishReceiveDTO.getUserId());
                }else {
                    VehiclePublishReceive vehiclePublishReceive1  = selectById(id);
                    BeanUtils.copyProperties(vehiclePublishReceive1,vehiclePublishReceive);
                    if (vehiclePublishReceive == null || !vehiclePublishReceive.getStatus().equals(VehiclePublishReceiveDTO.PAY)){
                        throw  new BaseException("接单无法确认--id==="+id, ResultCode.FAILED_CODE);
                    }
                }
                VehicleBrand vehicleBrand = brandBiz.selectById(vehiclePublishReceive.getBrandId());
                if (vehicleBrand != null)
                    vehiclePublishReceive.setBrandName(vehicleBrand.getCnName());
                VehicleCategory vehicleCategory = categoryBiz.selectById(vehiclePublishReceive.getCategoryId());
                if (vehicleCategory != null )
                    vehiclePublishReceive.setCategoryName(vehicleCategory.getName());
                if (StringUtils.isNotBlank(vehiclePublishReceive.getExtensionList()))
                    vehiclePublishReceive.setExtensionVOS(vehicleExtensionBiz.getTreeByApply(Arrays.asList(vehiclePublishReceive.getExtensionList().split(",")).parallelStream().map(s -> Integer.valueOf(s)).collect(Collectors.toList())));
            }
        }
        publishReceiveDTO.setGoodsAmount(goodsAmount);
        publishReceiveDTO.setPayAmount(payAmount);
        return  publishReceiveDTO;
    }

    public  void   setVehiclePublishReceive(VehiclePublishReceiveDTO publishReceiveDTO,String receiveIds){
        if (CollectionUtils.isEmpty(publishReceiveDTO.getReceiveVos())){
            if(StringUtils.isNotBlank(receiveIds)){
                List<VehiclePublishReceiveVo>  receives = new ArrayList<>();
                List<Integer> receiveIdList =Arrays.asList(receiveIds.split(",")).parallelStream().map(s -> Integer.valueOf(s)).collect(Collectors.toList());
                for (Integer id : receiveIdList){
                    VehiclePublishReceiveVo vehiclePublishReceive  = new VehiclePublishReceiveVo();
                    vehiclePublishReceive.setId(id);
                    receives.add(vehiclePublishReceive);
                }
                publishReceiveDTO.setReceiveVos(receives);
            }

        }
    }


    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);
            publishGoodsBiz.updReceiveNumber(publishId);
            sendQueue(receiveRefundDTO);
        }else if (type == 1){
            if (status.equals( VehiclePublishReceiveDTO.PAY)){
                vehiclePublishBiz.updWaitConfirmNumber(number,publishId);
                addVehicleUseTime(publishReceiveDTO);
                publishGoodsBiz.updReceiveNumber(publishId);
            }
        }
    }

    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);
        }
    }


    public  List<VehiclePublishReceiveVo> getListByUserId(VehiclePublishFindDTO publishFindDTO){
        return  mapper.getListByUserId(publishFindDTO);
    }


    public  List<VehiclePublishReceiveVo> getListByIds(VehiclePublishReceiveDTO publishReceiveDTO){
        List<VehiclePublishReceiveVo> list = getList(publishReceiveDTO);
        if (CollectionUtils.isNotEmpty(list)){
            for (VehiclePublishReceiveVo publishReceiveVo : list){
                String extensionList = publishReceiveVo.getExtensionList();
                List<VehicleExtensionVO> extensionVOS = new ArrayList<>();
                if (StringUtils.isNotBlank(extensionList)){
                    extensionVOS=vehicleExtensionBiz.getTreeByApply(Arrays.asList(extensionList.split(",")).parallelStream().map(s -> Integer.valueOf(s)).collect(Collectors.toList()));
                }
                publishReceiveVo.setExtensionVOS(extensionVOS);
            }
        }
         return  list;
    }



    public  List<ReceiveVo> getListByReceive(VehiclePublishFindDTO publishFindDTO){
        return  mapper.selectListByReceive(publishFindDTO);
    }


    public PageDataVO<ReceiveVo> selectList(VehiclePublishFindDTO publishFindDTO) {
        Integer page = publishFindDTO.getPage() == null ? 1 : publishFindDTO.getPage();
        Integer limit = publishFindDTO.getLimit() == null ? 10 : publishFindDTO.getLimit();
        PageHelper.startPage(page, limit);
        PageInfo<ReceiveVo> pageInfo = new PageInfo<>(getListByReceive(publishFindDTO));
        PageDataVO<ReceiveVo> pageDataVO = PageDataVO.pageInfo(pageInfo);
        List<ReceiveVo> list = pageDataVO.getData();
        if (CollectionUtils.isNotEmpty(list)) {
            for (ReceiveVo receiveVo : list) {
                String statusStr = receiveVo.getStatusStr();
                if (StringUtils.isNotBlank(statusStr)) {
                    List<Integer> statusIds = Arrays.asList(statusStr.split(",")).parallelStream().map(s -> Integer.valueOf(s)).collect(Collectors.toList());
                    Long waitNumber = statusIds.stream().filter(x -> x == 1).count();
                    waitNumber = waitNumber == null ? 0L : waitNumber;
                    Long refusedNumber = statusIds.stream().filter(x -> x == 2).count();
                    refusedNumber = refusedNumber == null ? 0L : refusedNumber;
                    Long confirmNumber = statusIds.stream().filter(x -> x == 3).count();
                    confirmNumber = confirmNumber == null ? 0L : confirmNumber;
                    receiveVo.setWaitNumber(waitNumber);
                    receiveVo.setRefusedNumber(refusedNumber);
                    receiveVo.setConfirmNumber(confirmNumber);
                    Integer buttonState;
                    if (waitNumber > 0L) {
                        if (confirmNumber > 0L) {
                            buttonState = 2;
                        } else {
                            buttonState = 1;
                        }
                    } else {
                        if (confirmNumber > 0L){
                            buttonState = 3;
                            receiveVo.setPublishCompany(branchCompanyBiz.selectById(receiveVo.getPublishCompanyId()));
                        }else {
                            buttonState = 4;
                        }

                    }
                    receiveVo.setButtonState(buttonState);
                    receiveVo.setPublishGoodsVos(mapper.getListByNumber(receiveVo.getReceiveOrderNo()));
                }

            }
        }
        return pageDataVO;
    }


    public ReceiveVo getInfo(String orderNo){
        VehiclePublishFindDTO publishFindDTO = new VehiclePublishFindDTO();
        publishFindDTO.setOrderNo(publishFindDTO.getOrderNo());
        List<ReceiveVo> list = getListByReceive(publishFindDTO);
        if (CollectionUtils.isNotEmpty(list)){
            ReceiveVo receiveVo = list.get(0);
            String ids = receiveVo.getIds();
            if (StringUtils.isNotBlank(ids)){
                List<Integer> idList = Arrays.asList(ids.split(",")).parallelStream().map(s -> Integer.valueOf(s)).collect(Collectors.toList());
                VehiclePublishReceiveDTO receiveDTO = new VehiclePublishReceiveDTO();
                receiveDTO.setIds(idList);
                receiveVo.setPublishReceiveVos(getListByIds(receiveDTO));
            }
            return  receiveVo;
        }

        return  null;

    }




}
