package com.scm.contract.service.management;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.scm.contract.dao.management.TagDataDao;
import com.scm.contract.model.apply.DictionaryTagType;
import com.scm.contract.model.apply.LabelApplication;
import com.scm.contract.model.apply.LabelApplicationDetail;
import com.scm.contract.model.management.TagData;
import com.scm.contract.model.message.MessageCenter;
import com.scm.contract.model.purchase.TagPurchase;
import com.scm.contract.model.purchase.TagPurchaseDetail;
import com.scm.contract.service.apply.DictionaryTagTypeService;
import com.scm.contract.service.apply.LabelApplicationService;
import com.scm.contract.service.message.MessageCenterService;
import com.scm.contract.service.purchase.TagPurchaseService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author zuo
 * @date 2024/6/21 17:45
 */
@Service
public class TagDataService {

    @Autowired
    private TagDataDao tagDataDao;

    @Autowired
    private DictionaryTagTypeService tagTypeService;


    @Autowired
    private MessageCenterService messageCenterService;

    @Autowired
    private LabelApplicationService labelApplicationService;

    @Autowired
    private TagPurchaseService tagPurchaseService;

//    /**
//     * 获取每种标签的剩余可使用库存
//     * @return Map<String, Long> ,key为tagTypeId ，value为 该类型对应的剩余可使用库存
//     */
//    public Map<String, Long> getSurplusNumber() {
//        Map<String, Long> returnMap = new HashMap<>();
//        List<TagData> list = this.tagDataDao.list();
//        Map<String, Long> inMap = new HashMap<>();
//        Map<String, Long> outMap = new HashMap<>();
//
//        for (TagData tagData : list) {
//            String dataType = tagData.getDataType();
//            String status = tagData.getStatus();
//            String tagTypeId = tagData.getTagTypeId();
//            String key = status + "|" + tagTypeId;
//            Long number = tagData.getNumber();
//            if ("1".equals(dataType)) {
//                inMap.put(key, inMap.getOrDefault(key, 0L) + number);
//            } else {
//                outMap.put(key, outMap.getOrDefault(key, 0L) + number);
//            }
//        }
//        List<DictionaryTagType> tagTypes = tagTypeService.list();
//        for (DictionaryTagType tagType : tagTypes) {
//            String tagTypeId = tagType.getId();
//            String inKey = "1" + "|" + tagTypeId;
//            String outKey = "1" + "|" + tagTypeId;
//
//            Long inNumber = inMap.getOrDefault(inKey, 0L);
//            Long outNumber = outMap.getOrDefault(outKey, 0L);
//            returnMap.put(tagTypeId,inNumber - outNumber);
//        }
//        return returnMap;
//    }

    /**
     * 获取每种标签的剩余可使用库存
     *
     * @return Map<String, Long> ,key为tagTypeId ，value为 该类型对应的剩余可使用库存
     */
    public Map<String, Long> getSurplusNumber() {
        Map<String, Long> returnMap = new HashMap<>();
        List<TagData> list = this.tagDataDao.list();

        Map<String, Long> tagDataMap = new HashMap<>();
        for (TagData tagData : list) {
            String dataType = tagData.getDataType();
            String status = tagData.getStatus();
            String tagTypeId = tagData.getTagTypeId();
            String key = dataType + "|" + status + "|" + tagTypeId;
            Long number = tagData.getNumber();
            tagDataMap.put(key, number);
        }

        List<DictionaryTagType> tagTypes = tagTypeService.list();
        for (DictionaryTagType tagType : tagTypes) {
            String tagTypeId = tagType.getId();
            String inKey = "1|1|" + tagTypeId;
            String outKey1 = "2|1|" + tagTypeId;
            String outKey2 = "3|0|" + tagTypeId;
            String outKey3 = "3|1|" + tagTypeId;
            Long inNumber = tagDataMap.getOrDefault(inKey, 0L);
            Long outNumber1 = tagDataMap.getOrDefault(outKey1, 0L);
            Long outNumber2 = tagDataMap.getOrDefault(outKey2, 0L);
            Long outNumber3 = tagDataMap.getOrDefault(outKey3, 0L);
            returnMap.put(tagTypeId, inNumber - outNumber1 - outNumber2 - outNumber3);
        }
        return returnMap;
    }


    /**
     * 更新库存和修改告警状态 （修改该方法需加在修改数据之前，否则所有从表清除后无法查询旧数据）
     *
     * @param labelApplications 标签申领订单
     * @param tagPurchases      采购订单
     * @param tagDataList       直接添加和删除指定库存，只修改此项isNewAdd参数随便穿无作用
     * @param isNewAdd          是否新增（转换阶段均为新增），false为修改true为新增
     * @return
     */
    @Transactional
    public synchronized List<TagData> saveOrUpdateBash(List<LabelApplication> labelApplications,
                                                       List<TagPurchase> tagPurchases,
                                                       List<TagData> tagDataList, boolean isNewAdd) {
        List<TagData> tagDatas = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(labelApplications)) {
            Map<String, TagData> map = new HashMap<>();
            List<TagData> list = tagDataDao.list();
            for (TagData tagData : list) {
                String tagTypeId = tagData.getTagTypeId();
                String status = tagData.getStatus();
                String dataType = tagData.getDataType();
                if ("2".equals(dataType)) {
                    String key = tagTypeId + "|" + status;
                    map.put(key, tagData);
                }
            }
            List<String> ids = labelApplications.stream().map(LabelApplication::getId).distinct().collect(Collectors.toList());
            List<LabelApplication> labelApplicationList = labelApplicationService.getListByIds(ids);
            labelApplicationService.setName(labelApplicationList, true);
            if (isNewAdd) {
                for (LabelApplication labelApplication : labelApplicationList) {
                    String status = labelApplication.getTagApplyStateId();
                    List<LabelApplicationDetail> details = labelApplication.getDetails();
                    for (LabelApplicationDetail detail : details) {
                        if ("4".equals(status)) {
                            Integer isPrint = detail.getIsPrint();
                            if (0 == isPrint) {
                                String tagTypeId = detail.getTagTypeId();
                                Long number = detail.getNumber();
                                String key = tagTypeId + "|" + status;
                                if (!map.containsKey(key)) {
                                    TagData tagData = new TagData();
                                    tagData.setNumber(0L);
                                    tagData.setTagTypeId(tagTypeId);
                                    tagData.setStatus(status);
                                    tagData.setDataType("2");
                                    map.put(key, tagData);
                                }
                                TagData tagData = map.get(key);
                                tagData.setNumber(tagData.getNumber() + number);
                                tagDatas.add(tagData);
                            }
                        } else {
                            String tagTypeId = detail.getTagTypeId();
                            Long number = detail.getNumber();
                            String key = tagTypeId + "|" + status;
                            if (!map.containsKey(key)) {
                                TagData tagData = new TagData();
                                tagData.setNumber(0L);
                                tagData.setTagTypeId(tagTypeId);
                                tagData.setStatus(status);
                                tagData.setDataType("2");
                                map.put(key, tagData);
                            }
                            TagData tagData = map.get(key);
                            tagData.setNumber(tagData.getNumber() + number);
                            tagDatas.add(tagData);
                        }
                    }
                }
            } else {
                Map<String, LabelApplication> labelApplicationMap = new HashMap<>();
                for (LabelApplication labelApplication : labelApplicationList) {
                    labelApplicationMap.put(labelApplication.getId(), labelApplication);
                }
                for (LabelApplication labelApplication : labelApplications) {
                    /**
                     * 更新库存
                     */
                    List<LabelApplicationDetail> details = labelApplication.getDetails();
                    String id = labelApplication.getId();
                    String newStatus = labelApplication.getTagApplyStateId();

                    LabelApplication oldLabelApplication = labelApplicationMap.getOrDefault(id, new LabelApplication());
                    String oldStatus = oldLabelApplication.getTagApplyStateId();
                    List<LabelApplicationDetail> oldDetails = oldLabelApplication.getDetails();

                    Map<String, TagData> oldMap = new HashMap<>();
                    for (LabelApplicationDetail oldDetail : oldDetails) {
                        String tagTypeId = oldDetail.getTagTypeId();
                        Long number = oldDetail.getNumber();
                        String key = tagTypeId + "|" + oldStatus;
                        if (!oldMap.containsKey(key)) {
                            TagData tagData = new TagData();
                            tagData.setNumber(0L);
                            tagData.setStatus(oldStatus);
                            tagData.setDataType("2");
                            tagData.setTagTypeId(tagTypeId);
                            oldMap.put(key, tagData);
                        }
                        TagData tagData = oldMap.get(key);
                        tagData.setNumber(tagData.getNumber() + number);
                    }


                    Map<String, TagData> newMap = new HashMap<>();
                    for (LabelApplicationDetail detail : details) {
                        String tagTypeId = detail.getTagTypeId();
                        Long number = detail.getNumber();
                        String key = tagTypeId + "|" + newStatus;
                        if (!newMap.containsKey(key)) {
                            TagData tagData = new TagData();
                            tagData.setNumber(0L);
                            tagData.setStatus(newStatus);
                            tagData.setDataType("2");
                            tagData.setTagTypeId(tagTypeId);
                            newMap.put(key, tagData);
                        }
                        TagData tagData = newMap.get(key);
                        tagData.setNumber(tagData.getNumber() + number);
                    }

                    for (Map.Entry<String, TagData> entry : oldMap.entrySet()) {
                        TagData tagData = entry.getValue();
                        String key = entry.getKey();
                        String status = tagData.getStatus();
                        String tagTypeId = tagData.getTagTypeId();
                        Long numberOld = tagData.getNumber();
                        TagData remove = newMap.remove(key);
                        long numberNew = Objects.isNull(remove) ? 0 : remove.getNumber();

                        TagData tagData1 = map.get(key);
                        Long number = 0L;
                        if (!Objects.isNull(tagData1)) {
                            number = tagData1.getNumber();
                        }
                        tagData.setNumber(number + (numberNew - numberOld));
                        tagDatas.add(tagData);
                        //如果修改的是1阶段状态的值，还需要修改0阶段状态的值
                        if ("1".equals(status)){
                            String key0 = tagTypeId + "|0";
                            TagData tagData0 = map.get(key0);
                            Long number0 = 0L;
                            if (!Objects.isNull(tagData0)) {
                                number0 = tagData0.getNumber();
                            }
                            TagData tagData2 = new TagData();
                            tagData2.setDataType(tagData.getDataType());
                            tagData2.setStatus("0");
                            tagData2.setTagTypeId(tagData.getTagTypeId());
                            tagData2.setNumber(number0 + (numberNew - numberOld));
                            tagDatas.add(tagData2);
                        }
                    }

                    for (Map.Entry<String, TagData> entry : newMap.entrySet()) {
                        TagData tagData = entry.getValue();
                        String key = entry.getKey();
                        String status = tagData.getStatus();
                        String tagTypeId = tagData.getTagTypeId();
                        TagData tagData1 = map.get(key);
                        Long number = 0L;
                        if (!Objects.isNull(tagData1)) {
                            number = tagData1.getNumber();
                        }
                        tagData.setNumber(number + tagData.getNumber());
                        tagDatas.add(tagData);
                        //如果修改的是1阶段状态的值，还需要修改0阶段状态的值
                        if ("1".equals(status)){
                            String key0 = tagTypeId + "|0";
                            TagData tagData0 = map.get(key0);
                            Long number0 = 0L;
                            if (!Objects.isNull(tagData0)) {
                                number0 = tagData0.getNumber();
                            }
                            TagData tagData2 = new TagData();
                            tagData2.setDataType(tagData.getDataType());
                            tagData2.setStatus("0");
                            tagData2.setTagTypeId(tagData.getTagTypeId());
                            tagData2.setNumber(number0 + tagData.getNumber());
                            tagDatas.add(tagData2);
                        }
                    }
                }
            }
        }
        if (CollectionUtils.isNotEmpty(tagPurchases)) {
            /**
             * 获取已有库存
             */
            Map<String, TagData> map = new HashMap<>();
            List<TagData> list = tagDataDao.list();
            for (TagData tagData : list) {
                String tagTypeId = tagData.getTagTypeId();
                String status = tagData.getStatus();
                String dataType = tagData.getDataType();
                if ("1".equals(dataType)) {
                    String key = tagTypeId + "|" + status;
                    map.put(key, tagData);
                }

            }
            List<String> ids = tagPurchases.stream().map(TagPurchase::getId).distinct().collect(Collectors.toList());
            List<TagPurchase> tagPurchaseList = tagPurchaseService.getListByIds(ids);
            tagPurchaseService.setName(tagPurchaseList, true);
            if (isNewAdd) {
                for (TagPurchase tagPurchase : tagPurchaseList) {
                    String status = tagPurchase.getTagPurchaseStateId();
                    List<TagPurchaseDetail> details = tagPurchase.getDetails();
                    for (TagPurchaseDetail detail : details) {
                        String tagTypeId = detail.getTagTypeId();
                        Long number = detail.getNumber();
                        String key = tagTypeId + "|" + status;
                        if (!map.containsKey(key)) {
                            TagData tagData = new TagData();
                            tagData.setNumber(0L);
                            tagData.setTagTypeId(tagTypeId);
                            tagData.setStatus(status);
                            tagData.setDataType("1");
                            map.put(key, tagData);
                        }
                        TagData tagData = map.get(key);
                        tagData.setNumber(tagData.getNumber() + number);
                        tagDatas.add(tagData);
                    }
                }
            } else {
                Map<String, TagPurchase> tagPurchaseMap = new HashMap<>();
                for (TagPurchase tagPurchase : tagPurchaseList) {
                    tagPurchaseMap.put(tagPurchase.getId(), tagPurchase);
                }
                for (TagPurchase tagPurchase : tagPurchases) {
                    List<TagPurchaseDetail> details = tagPurchase.getDetails();
                    String newStatus = tagPurchase.getTagPurchaseStateId();
                    /**
                     * 更新库存
                     */
                    String id = tagPurchase.getId();
                    TagPurchase oldTagPurchase = tagPurchaseMap.getOrDefault(id, new TagPurchase());
                    String oldStatus = oldTagPurchase.getTagPurchaseStateId();
                    List<TagPurchaseDetail> oldDetails = oldTagPurchase.getDetails();

                    Map<String, TagData> oldMap = new HashMap<>();
                    for (TagPurchaseDetail oldDetail : oldDetails) {
                        String tagTypeId = oldDetail.getTagTypeId();
                        Long number = oldDetail.getNumber();
                        String key = tagTypeId + "|" + oldStatus;
                        if (!oldMap.containsKey(key)) {
                            TagData tagData = new TagData();
                            tagData.setNumber(0L);
                            tagData.setStatus(oldStatus);
                            tagData.setDataType("1");
                            tagData.setTagTypeId(tagTypeId);
                            oldMap.put(key, tagData);
                        }
                        TagData tagData = oldMap.get(key);
                        tagData.setNumber(tagData.getNumber() + number);
                    }


                    Map<String, TagData> newMap = new HashMap<>();
                    for (TagPurchaseDetail detail : details) {
                        String tagTypeId = detail.getTagTypeId();
                        Long number = detail.getNumber();
                        String key = tagTypeId + "|" + newStatus;
                        if (!newMap.containsKey(key)) {
                            TagData tagData = new TagData();
                            tagData.setNumber(0L);
                            tagData.setStatus(newStatus);
                            tagData.setDataType("1");
                            tagData.setTagTypeId(tagTypeId);
                            newMap.put(key, tagData);
                        }
                        TagData tagData = newMap.get(key);
                        tagData.setNumber(tagData.getNumber() + number);
                    }

                    for (Map.Entry<String, TagData> entry : oldMap.entrySet()) {
                        TagData tagData = entry.getValue();
                        String key = entry.getKey();
                        Long numberOld = tagData.getNumber();
                        TagData remove = newMap.remove(key);
                        long numberNew = Objects.isNull(remove) ? 0 : remove.getNumber();

                        TagData tagData1 = map.get(key);
                        Long number = 0L;
                        if (!Objects.isNull(tagData1)) {
                            number = tagData1.getNumber();
                        }
                        tagData.setNumber(number + (numberNew - numberOld));
                        tagDatas.add(tagData);
                    }
                    for (Map.Entry<String, TagData> entry : newMap.entrySet()) {
                        TagData tagData = entry.getValue();
                        String key = entry.getKey();
                        TagData tagData1 = map.get(key);
                        Long number = 0L;
                        if (!Objects.isNull(tagData1)) {
                            number = tagData1.getNumber();
                        }
                        tagData.setNumber(number + tagData.getNumber());
                        tagDatas.add(tagData);
                    }
                }
            }
        }
        if (CollectionUtils.isNotEmpty(tagDataList)) {
            List<TagData> tagDataListOld = tagDataDao.getListBy(tagDataList);
            if (CollectionUtils.isEmpty(tagDataListOld)){
                tagDatas.addAll(tagDataList);
            }else {
                Map<String, Long> map = new HashMap<>();
                for (TagData tagData : tagDataList) {
                    String dataType = tagData.getDataType();
                    String status = tagData.getStatus();
                    String tagTypeId = tagData.getTagTypeId();
                    String key = dataType + "|" + status + "|" + tagTypeId;
                    Long number = tagData.getNumber();
                    map.put(key, map.getOrDefault(key, 0L) + number);
                }
                for (TagData tagData : tagDataListOld) {
                    String dataType = tagData.getDataType();
                    String status = tagData.getStatus();
                    String tagTypeId = tagData.getTagTypeId();
                    String key = dataType + "|" + status + "|" + tagTypeId;
                    Long number = map.getOrDefault(key, 0L);
                    tagData.setNumber(tagData.getNumber() + number);
                    tagDatas.add(tagData);
                }
            }
        }
        if (CollectionUtils.isNotEmpty(tagDatas)) {
            tagDataDao.saveOrUpdateBash(tagDatas);
        }
        setAlarm();
        return tagDatas;
    }

    /**
     * 修改告警状态
     */
    @Transactional
    public synchronized void setAlarm() {
        List<MessageCenter> saveOrUpdateMessage = new ArrayList<>();

        //获取每重标签剩余可用库存数据Map
        Map<String, Long> surplusNumberMap = getSurplusNumber();

        //获取所有正在告警的标签
        MessageCenter messageCenter = new MessageCenter();
        messageCenter.setIsAlarm(true);
        List<MessageCenter> messages = messageCenterService.findList(messageCenter);
        Map<String, MessageCenter> messageMap = new HashMap<>();
        for (MessageCenter message : messages) {
            messageMap.put(message.getTagTypeId(), message);
        }

        List<DictionaryTagType> tagTypes = tagTypeService.list();
        for (DictionaryTagType tagType : tagTypes) {
            Long alarm = tagType.getAlarm();
            String tagTypeId = tagType.getId();
            String name = tagType.getName();
            Long surplusNumber = surplusNumberMap.getOrDefault(tagTypeId, 0L);

            MessageCenter message = messageMap.get(tagTypeId);
            if (Objects.isNull(message) && (surplusNumber) <= alarm) {
                //没告警需要加高精
                message = new MessageCenter();
                message.setId(IdWorker.getIdStr());
                message.setIsAlarm(true);
                message.setDataTime(new Date());
                message.setTagTypeId(tagTypeId);
                message.setContent("『库存告警』：" + name + "库存数已低于预设值。");
            } else if (!Objects.isNull(message) && (surplusNumber) > alarm) {
                //有告警需要删告警
                message.setIsAlarm(false);
            }
            if (!Objects.isNull(message)) {
                saveOrUpdateMessage.add(message);
            }
        }
        if (CollectionUtils.isNotEmpty(saveOrUpdateMessage)) {
            messageCenterService.saveOrUpdateBash(saveOrUpdateMessage);
        }
    }


    /**
     * 按照不同的标签类型，分别汇总显示总的采购数量，发放数量，锁定数量，作废数量，使用数量，和当前可用标签数量。
     *
     * @return
     */
    public List<Map<String, Object>> getTagSituation() {
        List<DictionaryTagType> tagTypes = tagTypeService.list();
        List<TagData> tagDataList = tagDataDao.list();
        Map<String, TagData> map = new HashMap<>();
        for (TagData tagData : tagDataList) {
            String dataType = tagData.getDataType();
            String tagTypeId = tagData.getTagTypeId();
            String status = tagData.getStatus();
            String key = dataType + "|" + status + "|" + tagTypeId;
            map.put(key, tagData);
        }
//        List<TagData> returnList = new ArrayList<>();
        List<Map<String, Object>> returnList = new ArrayList<>();
        for (DictionaryTagType tagType : tagTypes) {
            Map<String, Object> returnMap = new HashMap<>();
            returnList.add(returnMap);
            String tagTypeId = tagType.getId();
            String tagTypeName = tagType.getName();
            returnMap.put("tagTypeId", tagTypeId);
            returnMap.put("tagTypeName", tagTypeName);
            //总的采购数量
            String key = "1|1|" + tagTypeId;
            TagData buyTagData = map.get(key);
            if (Objects.isNull(buyTagData)) {
                buyTagData = new TagData();
                buyTagData.setDataType("1");
                buyTagData.setTagTypeId(tagTypeId);
                buyTagData.setNumber(0L);
            }
            buyTagData.setTagTypeName(tagTypeName);
            buyTagData.setStatus("总采购数量");
            returnMap.put("buyNumber", buyTagData.getNumber());

            //发放数量
            key = "2|6|" + tagTypeId;
            TagData sendTagData = map.get(key);
            if (Objects.isNull(sendTagData)) {
                sendTagData = new TagData();
                sendTagData.setDataType("2");
                sendTagData.setTagTypeId(tagTypeId);
                sendTagData.setNumber(0L);
            }
            sendTagData.setTagTypeName(tagTypeName);
            sendTagData.setStatus("发放数量");
            returnMap.put("sendNumber", sendTagData.getNumber());

            //锁定数量(生成订单数量-发放数量)
            key = "2|1|" + tagTypeId;
            TagData lockTagData = map.get(key);
            if (Objects.isNull(lockTagData)) {
                lockTagData = new TagData();
                lockTagData.setDataType("2");
                lockTagData.setTagTypeId(tagTypeId);
                lockTagData.setNumber(0L);
            }
            Long lockTagDataNumber = lockTagData.getNumber();
            Long sendTagDataNumber = sendTagData.getNumber();
            lockTagData.setNumber(lockTagDataNumber - sendTagDataNumber);
            lockTagData.setTagTypeName(tagTypeName);
            lockTagData.setStatus("锁定数量");
            returnMap.put("lockNumber", lockTagData.getNumber());

            //作废数量
            key = "3|0|" + tagTypeId;
            String key1 = "3|1|" + tagTypeId;
            TagData cancelTagData = map.get(key);
            TagData cancelTagData1 = map.get(key1);
            if (Objects.isNull(cancelTagData)) {
                cancelTagData = new TagData();
                cancelTagData.setDataType("3");
                cancelTagData.setTagTypeId(tagTypeId);
                cancelTagData.setNumber(0L);
            }
            cancelTagData.setTagTypeName(tagTypeName);
            cancelTagData.setStatus("作废数量");
            if (!Objects.isNull(cancelTagData1)){
                cancelTagData.setNumber(cancelTagData.getNumber() + cancelTagData1.getNumber());
            }
            returnMap.put("cancelNumber", cancelTagData.getNumber());

            //todo 使用数量(订单采购商已经使用的标签数量，目前没有该数据，需要去从别人API取),等有API后需要修改
            TagData useTagData = new TagData();
            useTagData.setStatus("使用数量");
            useTagData.setTagTypeId(tagTypeId);
            useTagData.setTagTypeName(tagTypeName);
            useTagData.setNumber(0L);
            returnMap.put("useNumber", useTagData.getNumber());

            //当前可用标签数量
            TagData availableTagData = new TagData();
            availableTagData.setStatus("可用标签数量");
            availableTagData.setTagTypeId(tagTypeId);
            availableTagData.setTagTypeName(tagTypeName);
            Long buyTagDataNumber = buyTagData.getNumber();
            Long cancelTagDataNumber = cancelTagData.getNumber();
            lockTagDataNumber = lockTagData.getNumber();
            sendTagDataNumber = sendTagData.getNumber();
            availableTagData.setNumber(buyTagDataNumber - sendTagDataNumber - lockTagDataNumber - cancelTagDataNumber);
            returnMap.put("availableNumber", availableTagData.getNumber());
        }
        return returnList;
    }
}
