package cn.estsh.i3plus.ext.mes.apiservice.serviceimpl.busi.bu3;

import cn.estsh.i3plus.ext.mes.api.base.IProdOrgExtService;
import cn.estsh.i3plus.ext.mes.api.busi.bu3.ISxProdDataToMonthlyStatisticsDispatchService;
import cn.estsh.i3plus.ext.mes.pojo.bean.MesProdDataToStatisticsShiftProd;
import cn.estsh.i3plus.ext.mes.pojo.bean.MesShiftProdCenterRecord;
import cn.estsh.i3plus.ext.mes.pojo.model.bu3.SxProdDataToAutoStatisticsModel;
import cn.estsh.i3plus.ext.mes.pojo.repository.MesProdDataToStatisticsShiftProdRepository;
import cn.estsh.i3plus.ext.mes.pojo.util.MesExtConstWords;
import cn.estsh.i3plus.ext.mes.pojo.util.MesExtEnumUtil;
import cn.estsh.impp.framework.boot.exception.ImppBusiException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringJoiner;
import java.util.stream.Collectors;

@Slf4j
@Service
public class SxProdDataToMonthlyStatisticsShiftProdByMonthService implements ISxProdDataToMonthlyStatisticsDispatchService {

    @Autowired
    private SxProdDataToMonthlyStatisticsShiftProdService dispatchService;

    @Autowired
    private MesProdDataToStatisticsShiftProdRepository prodDataToStatisticsShiftProdRepository;

    @Autowired
    private IProdOrgExtService prodOrgExtService;

    @Override
    public String name() { return MesExtEnumUtil.JOB_STATISTICS_PROD_DATA_KEY.SHIFT_PROD_MONTH_KEY.name(); }

    @Override
    public String flag() { return MesExtEnumUtil.JOB_STATISTICS_PROD_DATA_KEY.SHIFT_PROD_MONTH_KEY.getFlag(); }

    @Override
    public SxProdDataToAutoStatisticsModel restock(SxProdDataToAutoStatisticsModel data) {
        return dispatchService.restock(data)
                .statisticsType(flag()).dataKey(MesExtEnumUtil.JOB_STATISTICS_PROD_DATA_KEY.SHIFT_PROD_MONTH_KEY.getValue());
    }

    @Override
    public SxProdDataToAutoStatisticsModel query(SxProdDataToAutoStatisticsModel data) {

        List<MesShiftProdCenterRecord> shiftProdCenterRecordList = dispatchService.queryShiftProdCenterRecordList(data);

        shiftProdCenterRecordList = removeUnValidData(shiftProdCenterRecordList);

        Map<String, List<MesShiftProdCenterRecord>> shiftProdMap = getDataMap(shiftProdCenterRecordList);

        Map<String, String> careerPersonnelCostMap = prodOrgExtService.getCareerPersonnelCostMap(data.getOrganizeCode());

        return CollectionUtils.isEmpty(shiftProdCenterRecordList) ? data.sourceCount(0).targetCount(0) :
                data.sourceCount(shiftProdCenterRecordList.size()).targetCount(shiftProdMap.size()).data(getDataMap(shiftProdMap, careerPersonnelCostMap));

    }

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = {ImppBusiException.class, Exception.class})
    public SxProdDataToAutoStatisticsModel exec(SxProdDataToAutoStatisticsModel data) {

        dispatchService.doTravel(data);

        if (null == data.getData()) return data;

        Map<String, Object> dataMap = (Map<String, Object>) data.getData();

        Map<String, List<MesShiftProdCenterRecord>> shiftProdMap = !dataMap.containsKey("shiftProdMap") ? null : (Map<String, List<MesShiftProdCenterRecord>>) dataMap.get("shiftProdMap");

        Map<String, String> careerPersonnelCostMap = !dataMap.containsKey("careerPersonnelCostMap") ? null : (Map<String, String>) dataMap.get("careerPersonnelCostMap");

        saveStatisticsData(data, shiftProdMap, careerPersonnelCostMap);

        return data;
    }

    private List<MesShiftProdCenterRecord> removeUnValidData(List<MesShiftProdCenterRecord> shiftProdCenterRecordList) {
        return CollectionUtils.isEmpty(shiftProdCenterRecordList) ? shiftProdCenterRecordList :
                shiftProdCenterRecordList.stream().filter(o -> (null != o &&
                        !StringUtils.isEmpty(o.getWorkCenterCode()) &&
                        !StringUtils.isEmpty(o.getShiftCode()) &&
                        !StringUtils.isEmpty(o.getProdCode()) &&
                        !StringUtils.isEmpty(o.getProdType()) &&
                        !StringUtils.isEmpty(o.getWorkerQty()) &&
                        !StringUtils.isEmpty(o.getStartTime()) &&
                        !StringUtils.isEmpty(o.getEndTime()) &&
                        !StringUtils.isEmpty(o.getProdCategory()) &&
                        !StringUtils.isEmpty(o.getCategoryCode()) &&
                        !StringUtils.isEmpty(o.getCareerCode()))).collect(Collectors.toList());
    }

    private Map<String, List<MesShiftProdCenterRecord>> getDataMap(List<MesShiftProdCenterRecord> shiftProdCenterRecordList) {
        return CollectionUtils.isEmpty(shiftProdCenterRecordList) ? null :
                shiftProdCenterRecordList.stream().filter(o -> null != o).collect(Collectors.groupingBy(o -> new StringJoiner(MesExtConstWords.AND)
                        .add(o.getWorkCenterCode()).add(o.getShiftCode()).add(o.getProdCode()).add(o.getProdType().toString()).add(o.getProdCategory().toString()).add(o.getCategoryCode()).add(o.getCareerCode()).toString()));
    }

    public Map<String, Object> getDataMap(Map<String, List<MesShiftProdCenterRecord>> shiftProdMap, Map<String, String> careerPersonnelCostMap) {
        Map<String, Object> dataMap = new HashMap<>();
        if (!CollectionUtils.isEmpty(shiftProdMap)) dataMap.put("shiftProdMap", shiftProdMap);
        if (!CollectionUtils.isEmpty(careerPersonnelCostMap)) dataMap.put("careerPersonnelCostMap", careerPersonnelCostMap);
        return dataMap;
    }

    private void saveStatisticsData(SxProdDataToAutoStatisticsModel data, Map<String, List<MesShiftProdCenterRecord>> shiftProdMap, Map<String, String> careerPersonnelCostMap) {
        for (Map.Entry<String, List<MesShiftProdCenterRecord>> entry : shiftProdMap.entrySet()) {
            List<MesShiftProdCenterRecord> itemList = entry.getValue();
            MesProdDataToStatisticsShiftProd statistics = dispatchService.packItemData(data, itemList);
            statistics.setWorkTime(data.getDate());
            statistics.setPersonnelCost((!CollectionUtils.isEmpty(careerPersonnelCostMap) && careerPersonnelCostMap.containsKey(statistics.getCareerCode())) ? careerPersonnelCostMap.get(statistics.getCareerCode()) : MesExtConstWords.ZERO_STR);
            prodDataToStatisticsShiftProdRepository.insert(statistics);
        }
    }

}
