package com.prolog.rdc.tms.app.service.business.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.codingapi.tx.annotation.TxTransaction;
import com.google.common.collect.Lists;
import com.prolog.common.util.ToolKits;
import com.prolog.framework.core.exception.BizException;
import com.prolog.framework.core.restriction.Criteria;
import com.prolog.framework.core.restriction.Order;
import com.prolog.framework.core.restriction.Restriction;
import com.prolog.framework.core.restriction.Restrictions;
import com.prolog.product.core.framework.entity.UserEntity;
import com.prolog.product.core.framework.util.PlgFxUsrUtils;
import com.prolog.rdc.tms.app.constant.DataDictionaryConstant;
import com.prolog.rdc.tms.app.constant.SeriaNnumberConstant;
import com.prolog.rdc.tms.app.constant.enums.EventFeedbackStatusEnum;
import com.prolog.rdc.tms.app.constant.enums.EventFeedbackTypeEnum;
import com.prolog.rdc.tms.app.constant.enums.EventTypeEnum;
import com.prolog.rdc.tms.app.dao.mapper.TmsLoadingBillDetailMapper;
import com.prolog.rdc.tms.app.dao.mapper.TmsShipbillEventFeedbackMapper;
import com.prolog.rdc.tms.app.dao.mapper.TmsShipbillHeaderMapper;
import com.prolog.rdc.tms.app.model.entity.TmsLoadingBillDetailModel;
import com.prolog.rdc.tms.app.model.entity.TmsShipbillEventFeedback;
import com.prolog.rdc.tms.app.model.entity.TmsShipbillHeaderModel;
import com.prolog.rdc.tms.app.model.vo.business.AddShipbillEventFeedbackVO;
import com.prolog.rdc.tms.app.model.vo.business.ShipbillNodeTrackingSaveVO;
import com.prolog.rdc.tms.app.model.vo.business.ShipbillOperateLogSaveVO;
import com.prolog.rdc.tms.app.proxy.MainDataProxy;
import com.prolog.rdc.tms.app.service.business.ShipbillEventFeedbackService;
import com.prolog.rdc.tms.app.service.business.ShipbillNodeTrackingService;
import com.prolog.rdc.tms.app.service.business.ShipbillOperateLogService;
import com.prolog.rdc.tms.model.vo.UpdateLatitudeAndLongitudeVO;
import com.prolog.rdc.tms.rmi.feign.MaindataFeign;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author hongbo.pan
 * @date 2022/11/1
 */
@Service
public class ShipbillEventFeedbackServiceImpl implements ShipbillEventFeedbackService {

    @Autowired
    private TmsShipbillEventFeedbackMapper tmsShipbillEventFeedbackMapper;

    @Autowired
    private MainDataProxy mainDataProxy;

    @Autowired
    private MaindataFeign maindataTmsResource;

    @Autowired
    private TmsShipbillHeaderMapper tmsShipbillHeaderMapper;

    @Autowired
    private ShipbillOperateLogService shipbillOperateLogService;

    @Autowired
    private ShipbillNodeTrackingService shipbillNodeTrackingService;

    @Autowired
    private TmsLoadingBillDetailMapper tmsLoadingBillDetailMapper;

    /**
     * 新增事件反馈
     * @param vo
     * @return
     */
    @Override
    public TmsShipbillEventFeedback add(AddShipbillEventFeedbackVO vo) {
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        String id = mainDataProxy.getCodeNumberByCode(SeriaNnumberConstant.TMS_SHIPBILL_EVENT_FEEDBACK_ID);
        TmsShipbillEventFeedback model = new TmsShipbillEventFeedback();
        model.setId(id);
        model.setType(vo.getType());
        model.setShipbillId(vo.getShipbillId());
        model.setShipbillNo(vo.getShipbillId());
        model.setMileage(vo.getMileage());
        model.setAddress(vo.getAddress());
        model.setLongitude(vo.getLongitude());
        model.setLatitude(vo.getLatitude());
        model.setEventType(vo.getEventType());
        model.setEventContent(vo.getEventContent());
        model.setEventPic(vo.getEventPic());
        model.setStatus(EventFeedbackStatusEnum.CHECKING.getCode());
        model.setEnterpriseId(user.getEnterpriseId());
        model.setEnterpriseName(user.getEnterpriseName());
        model.setCreateperson(user.getNickname());
        model.setCreatetime(new Date());
        model.setUpdateperson(user.getNickname());
        model.setUpdatetime(new Date());
        tmsShipbillEventFeedbackMapper.save(model);
        return model;
    }

    /**
     * 事件反馈
     * @param eventFeedbackId
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void eventFeedback(String eventFeedbackId) {
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        TmsShipbillEventFeedback tmsShipbillEventFeedback = tmsShipbillEventFeedbackMapper.findById(eventFeedbackId, TmsShipbillEventFeedback.class);
        tmsShipbillEventFeedback.setStatus(EventFeedbackStatusEnum.CHECKED.getCode());
        tmsShipbillEventFeedback.setUpdatetime(new Date());
        tmsShipbillEventFeedback.setUpdateperson(user.getNickname());
        tmsShipbillEventFeedbackMapper.update(tmsShipbillEventFeedback);
        String memo = generateMemo(tmsShipbillEventFeedback);
        List<TmsShipbillHeaderModel> tmsShipbillHeaderModelList = tmsShipbillHeaderMapper.findByIds(TmsShipbillHeaderModel.class, tmsShipbillEventFeedback.getShipbillId().split(","), null);
        List<Long> branchIdList = Lists.newArrayList();
        List<Long> shipperIdList = Lists.newArrayList();
        List<Long> consigneeIdList = Lists.newArrayList();
        tmsShipbillHeaderModelList.forEach(tmsShipbillHeaderModel -> {
            // 运单节点保存
            ShipbillNodeTrackingSaveVO shipbillNodeTrackingSaveVO = new ShipbillNodeTrackingSaveVO();
            shipbillNodeTrackingSaveVO.setNodeEvent(DataDictionaryConstant.SHIPBILL_EVENT_FEEDBACK + " " + memo);
            shipbillNodeTrackingSaveVO.setStatus(tmsShipbillHeaderModel.getStatus());
            shipbillNodeTrackingSaveVO.setShipbillId(tmsShipbillHeaderModel.getShipbillId());
            shipbillNodeTrackingSaveVO.setShipbillNo(tmsShipbillHeaderModel.getShipbillNo());
            shipbillNodeTrackingSaveVO.setPicUrl(tmsShipbillEventFeedback.getEventPic());
            shipbillNodeTrackingSaveVO.setNodeDate(new Date());
            shipbillNodeTrackingService.addShipbillNodeTrackingData(shipbillNodeTrackingSaveVO);
            // 运单日志保存
            ShipbillOperateLogSaveVO shipbillOperateLogSaveVO = new ShipbillOperateLogSaveVO();
            shipbillOperateLogSaveVO.setShipbillId(tmsShipbillHeaderModel.getShipbillId());
            shipbillOperateLogSaveVO.setShipbillNo(tmsShipbillHeaderModel.getShipbillId());
            shipbillOperateLogSaveVO.setOperateEvent(DataDictionaryConstant.SHIPBILL_EVENT_FEEDBACK + " " + memo);
            shipbillOperateLogSaveVO.setOldStatus(tmsShipbillHeaderModel.getStatus());
            shipbillOperateLogSaveVO.setNewStatus(tmsShipbillHeaderModel.getStatus());
            shipbillOperateLogService.addShipbillOperateLogData(shipbillOperateLogSaveVO);
            if (tmsShipbillEventFeedback.getEventType().contains(EventFeedbackTypeEnum.POSITION.getCode())) {
                Criteria criteriaDetail = Criteria.forClass(TmsLoadingBillDetailModel.class);
                Restriction r1 = Restrictions.eq("shipbillId", tmsShipbillHeaderModel.getShipbillId());
                Restriction r2 = Restrictions.eq(TmsLoadingBillDetailModel::getEnterpriseId, user.getEnterpriseId());
                criteriaDetail.setRestriction(Restrictions.and(r1, r2));
                criteriaDetail.setOrder(Order.newInstance().desc(new String[] { "createtime" }));
                List<TmsLoadingBillDetailModel> tmsLoadingBillDetails = tmsLoadingBillDetailMapper.findByCriteria(criteriaDetail);
                if (ToolKits.isEmpty(tmsLoadingBillDetails)) {
                    throw new BizException("装车单明细【" + tmsShipbillHeaderModel.getShipbillId() + "】查询失败");
                }
                TmsLoadingBillDetailModel tmsLoadingBillDetail = tmsLoadingBillDetails.get(0);
                if (EventTypeEnum.SHIP.getCode().equals(tmsShipbillEventFeedback.getType())) {
                    tmsShipbillHeaderModel.setShipperLatitude(tmsShipbillEventFeedback.getLatitude());
                    tmsShipbillHeaderModel.setShipperLongitude(tmsShipbillEventFeedback.getLongitude());
                    tmsLoadingBillDetail.setShipperLatitude(tmsShipbillEventFeedback.getLatitude());
                    tmsLoadingBillDetail.setShipperLongitude(tmsShipbillEventFeedback.getLongitude());
                    if (DataDictionaryConstant.SHIPPER_TYPE_KH.equals(tmsShipbillHeaderModel.getShipperType())) {
                        consigneeIdList.add(tmsShipbillHeaderModel.getShipperId());
                    } else if (DataDictionaryConstant.SHIPPER_TYPE_CK.equals(tmsShipbillHeaderModel.getShipperType())){
                        branchIdList.add(tmsShipbillHeaderModel.getShipperId());
                    } else if (DataDictionaryConstant.SHIPPER_TYPE_GYS.equals(tmsShipbillHeaderModel.getShipperType())){
                        shipperIdList.add(tmsShipbillHeaderModel.getShipperId());
                    }
                } else {
                    tmsShipbillHeaderModel.setConsigneeLatitude(tmsShipbillEventFeedback.getLatitude());
                    tmsShipbillHeaderModel.setConsigneeLongitude(tmsShipbillEventFeedback.getLongitude());
                    tmsLoadingBillDetail.setConsigneeLatitude(tmsShipbillEventFeedback.getLatitude());
                    tmsLoadingBillDetail.setConsigneeLongitude(tmsShipbillEventFeedback.getLongitude());
                    if (DataDictionaryConstant.CONSIGNEE_TYPE_KH.equals(tmsShipbillHeaderModel.getConsigneeType())) {
                        consigneeIdList.add(tmsShipbillHeaderModel.getConsigneeId());
                    } else if (DataDictionaryConstant.CONSIGNEE_TYPE_CK.equals(tmsShipbillHeaderModel.getConsigneeType())){
                        branchIdList.add(tmsShipbillHeaderModel.getConsigneeId());
                    } else if (DataDictionaryConstant.CONSIGNEE_TYPE_GYS.equals(tmsShipbillHeaderModel.getConsigneeType())){
                        shipperIdList.add(tmsShipbillHeaderModel.getConsigneeId());
                    }
                }
                tmsLoadingBillDetail.setUpdatetime(new Date());
                tmsLoadingBillDetail.setUpdateperson(user.getNickname());
                tmsLoadingBillDetailMapper.update(tmsLoadingBillDetail);
                tmsShipbillHeaderModel.setUpdatetime(new Date());
                tmsShipbillHeaderModel.setUpdateperson(user.getNickname());
                tmsShipbillHeaderMapper.update(tmsShipbillHeaderModel);
            }
        });
        UpdateLatitudeAndLongitudeVO updateLatitudeAndLongitudeVO = new UpdateLatitudeAndLongitudeVO();
        updateLatitudeAndLongitudeVO.setLongitude(tmsShipbillEventFeedback.getLongitude());
        updateLatitudeAndLongitudeVO.setLatitude(tmsShipbillEventFeedback.getLatitude());
        if (CollectionUtil.isNotEmpty(branchIdList)) {
            updateLatitudeAndLongitudeVO.setIdList(branchIdList);
            maindataTmsResource.updateBranchLatitudeAndLongitude(updateLatitudeAndLongitudeVO);
        }
        if (CollectionUtil.isNotEmpty(consigneeIdList)) {
            updateLatitudeAndLongitudeVO.setIdList(consigneeIdList);
            maindataTmsResource.updateConsigneeLatitudeAndLongitude(updateLatitudeAndLongitudeVO);
        }
        if (CollectionUtil.isNotEmpty(shipperIdList)) {
            updateLatitudeAndLongitudeVO.setIdList(shipperIdList);
            maindataTmsResource.updateShipperLatitudeAndLongitude(updateLatitudeAndLongitudeVO);
        }
    }

    /**
     * generateMemo
     * @param tmsShipbillEventFeedback
     * @return
     */
    private String generateMemo(TmsShipbillEventFeedback tmsShipbillEventFeedback) {
        String[] eventTypeArray = tmsShipbillEventFeedback.getEventType().split(",");
        return "事件内容:" + (StrUtil.isBlank(tmsShipbillEventFeedback.getEventContent()) ? "" : tmsShipbillEventFeedback.getEventContent()) + " " + Arrays.stream(eventTypeArray).map(eventType -> {
            if (EventFeedbackTypeEnum.MILEAGE.getCode().equals(eventType)) {
                return EventFeedbackTypeEnum.MILEAGE.getDesc() + ":" + (ObjectUtil.isNull(tmsShipbillEventFeedback.getMileage())  ? "" : tmsShipbillEventFeedback.getMileage());
            } else {
                return EventFeedbackTypeEnum.POSITION.getDesc() + ":经度=" + (ObjectUtil.isNull(tmsShipbillEventFeedback.getLongitude())  ? "" : tmsShipbillEventFeedback.getLongitude()) + "，纬度=" + (ObjectUtil.isNull(tmsShipbillEventFeedback.getLatitude())  ? "" : tmsShipbillEventFeedback.getLatitude());
            }
        }).collect(Collectors.joining(" "));
    }
}
