package com.yeejoin.amos.boot.module.common.biz.service.impl;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

import com.yeejoin.amos.boot.biz.common.dao.mapper.DataDictionaryMapper;
import com.yeejoin.amos.boot.biz.common.entity.DataDictionary;
import com.yeejoin.amos.boot.module.common.api.dto.DutyCarDto;
import com.yeejoin.amos.boot.module.common.api.entity.*;
import com.yeejoin.amos.boot.module.common.api.mapper.DutyPersonShiftLogMapper;
import com.yeejoin.amos.boot.module.common.api.mapper.OrgUsrMapper;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.yeejoin.amos.boot.module.common.api.dto.DutyPersonShiftDto;
import com.yeejoin.amos.boot.module.common.api.mapper.DutyPersonShiftMapper;
import com.yeejoin.amos.boot.module.common.biz.enums.ActionStatus;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.typroject.tyboot.core.foundation.context.RequestContext;
import org.typroject.tyboot.core.foundation.utils.Bean;
import org.typroject.tyboot.core.restful.exception.instance.BadRequest;
import org.typroject.tyboot.core.restful.utils.ResponseModel;

import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yeejoin.amos.boot.biz.common.utils.DateUtils;
import com.yeejoin.amos.boot.module.common.api.dto.DutyPersonDto;
import com.yeejoin.amos.boot.module.common.api.feign.EquipFeignClient;
import com.yeejoin.amos.boot.module.common.api.service.IDutyPersonService;

/**
 * @author DELL
 */
@Service
public class DutyPersonServiceImpl extends DutyCommonServiceImpl implements IDutyPersonService{

    @Autowired
    EquipFeignClient equipFeign;
    @Autowired
    DutyPersonShiftMapper dutyPersonShiftMapper;
    @Autowired
    DutyPersonShiftLogMapper dutyPersonShiftLogMapper;

    @Autowired
    DataDictionaryMapper dataDictionaryMapper;

    @Autowired
    OrgUsrMapper orgUsrMapper;


    @Override
    public String getGroupCode(){
        return "dutyPerson";
    }

    @Override
    public DutyPersonDto save(DutyPersonDto dutyPersonDto) {
        // BUG 2807 更新人员车辆排版值班的保存逻辑 如果没有填写数据则保存空数据 。 同步修改 查询 导出相关逻辑 by kongfm 2021-09-14
        //1.保存行数据
        String groupCode = this.getGroupCode();
        String userId = dutyPersonDto.getUserId();
        List<DynamicFormInstance> instances = dynamicFormInstanceService
                .list(new LambdaQueryWrapper<DynamicFormInstance>().eq(DynamicFormInstance::getFieldCode, "userId")
                        .eq(DynamicFormInstance::getFieldValue, userId)
                        .eq(DynamicFormInstance::getGroupCode, this.getGroupCode()));
        Long instanceId = null;
        // 如果人员有区域id 则创建区域字段
        if(StringUtils.isNotEmpty(dutyPersonDto.getDutyAreaId())) {
            // 根据建筑id 查找建筑
            ResponseModel<Map<String, Object>> response = null;
            try {
                response = equipFeign.getFormInstanceById(Long.parseLong(dutyPersonDto.getDutyAreaId()));
            } catch (NumberFormatException e) {
                throw new BadRequest("值班区域id异常！");
            }
            Map<String, Object> result = response.getResult();
            dutyPersonDto.setDutyArea(result.get("name").toString());
        }

        Map<String, Object> map = Bean.BeantoMap(dutyPersonDto);

        if (!instances.isEmpty()) {
            // 0.定位instanceId，准备进行更新操作
            instanceId = instances.get(0).getInstanceId(); // 已经有了走更新方法
            //1.查询已有数据
            List<DynamicFormInstance> hasInstances = dynamicFormInstanceService.list(new LambdaQueryWrapper<DynamicFormInstance>().eq(DynamicFormInstance::getInstanceId, instanceId));
            //2.list 转 map
            Map<Object, DynamicFormInstance> instanceMap = Bean.listToMap(hasInstances, "fieldCode", DynamicFormInstance.class);
            //3.查询列数据，已列为主
            List<DynamicFormColumn> columns = dynamicFormColumnService.list(new LambdaQueryWrapper<DynamicFormColumn>().eq(DynamicFormColumn::getGroupCode, groupCode));
            //4.已列为主 填充动态表单数据
            List<DynamicFormInstance> entrys = new ArrayList<>();
            for (DynamicFormColumn column : columns) {
                DynamicFormInstance formInstance = instanceMap.get(column.getFieldCode());
                if (!ObjectUtils.isEmpty(formInstance)) {
                    //有的更新
                    formInstance.setFieldValue(map.get(column.getFieldCode()) != null ? map.get(column.getFieldCode()).toString() : "");
                } else {
                    //没有的新增
                    formInstance = new DynamicFormInstance();
                    buildFormInstanceData(instanceId, map, column, formInstance);
                }
                entrys.add(formInstance);
            }
            if(!entrys.isEmpty()){
                dynamicFormInstanceService.saveOrUpdateBatch(entrys);
            }

        } else {
            instanceId =  dynamicFormInstanceService.commonSave(groupCode,map);
        }
        // 如果当前保存没有保存调班记录 需要默认保存一个月的空数据

        if(dutyPersonDto.getDutyShift() != null && dutyPersonDto.getDutyShift().size() == 0) {
            Calendar startDate = Calendar.getInstance();
            startDate.setTime(DateUtils.longStr2Date(dutyPersonDto.getStartTime()));
            int dates = startDate.getActualMaximum(Calendar.DAY_OF_MONTH);
            startDate.set(Calendar.DAY_OF_MONTH, 1);
            List<DutyPersonShift> dutyShift = new ArrayList<>(dates);
            for (int i = 0 ; i < dates ; i ++) {
                DutyPersonShift temp = new DutyPersonShift();
                temp.setAppKey(RequestContext.getAppKey());
                temp.setDutyDate(startDate.getTime());
                temp.setIsDelete(false);
                temp.setInstanceId(instanceId);
                dutyShift.add(temp);
                startDate.add(Calendar.DAY_OF_YEAR,1);
            }
            dutyPersonShiftService.saveOrUpdateBatch(dutyShift);
        }
        //2.保存值班信息
        insertPersonShift(instanceId, dutyPersonDto,ActionStatus.METHOD_ADD.getCode());
        // 生成变更日志
        createDutyPersonShiftLog(dutyPersonDto, false, ActionStatus.METHOD_ADD.getCode());
        //3.返回保存后的数据
        return dutyPersonDto;
    }

    @Override
    public DutyPersonDto update(Long instanceId, DutyPersonDto dutyPersonDto) {
        String groupCode = this.getGroupCode();
        //1.查询已有数据
        List<DynamicFormInstance> instances = dynamicFormInstanceService.list(new LambdaQueryWrapper<DynamicFormInstance>().eq(DynamicFormInstance::getInstanceId, instanceId));
        //2.list 转 map
        Map<Object, DynamicFormInstance> instanceMap = Bean.listToMap(instances, "fieldCode", DynamicFormInstance.class);
        //3.查询列数据，已列为主
        List<DynamicFormColumn> columns = dynamicFormColumnService.list(new LambdaQueryWrapper<DynamicFormColumn>().eq(DynamicFormColumn::getGroupCode, groupCode));
        //页面数据转Map
        Map<String, Object> map = Bean.BeantoMap(dutyPersonDto);
        //4.已列为主 填充动态表单数据
        List<DynamicFormInstance> entrys = new ArrayList<>();
        for (DynamicFormColumn column : columns) {
            DynamicFormInstance formInstance = instanceMap.get(column.getFieldCode());
            if (!ObjectUtils.isEmpty(formInstance)) {
                //有的更新
                formInstance.setFieldValue(map.get(column.getFieldCode()) != null ? map.get(column.getFieldCode()).toString() : "");
            } else {
                //没有的新增
                formInstance = new DynamicFormInstance();
                buildFormInstanceData(instanceId, map, column, formInstance);
            }
            entrys.add(formInstance);
        }
        if(!entrys.isEmpty()){
            dynamicFormInstanceService.saveOrUpdateBatch(entrys);
        }
        //5.更新值班信息人日期数据
        insertPersonShift(instanceId, dutyPersonDto, ActionStatus.METHOD_UPDATE.getCode());
        // 生成变更日志
        createDutyPersonShiftLog(dutyPersonDto, false, ActionStatus.METHOD_UPDATE.getCode());
        return dutyPersonDto;
    }

    private void insertPersonShift(Long instanceId, DutyPersonDto dutyPersonDto,String type) {
        //此处代码针对页面操作 已有排班人员排班日期情况下 仍继续执行新增操作所造成的索引报错
        //拿到排班月份
        //获取本次排班数据
        List<DutyPersonShiftDto> dutyShiftList = dutyPersonDto.getDutyShift();
        this.dataCheck(dutyShiftList,instanceId,type);
        Set<DutyPersonShift> personShiftList = dutyShiftList.stream().map(dto -> {
            DutyPersonShift dutyPersonShift = new DutyPersonShift();
            dto.setInstanceId(instanceId);
            Bean.copyExistPropertis(dto, dutyPersonShift);
            dutyPersonShift.setAppKey(RequestContext.getAppKey());
            return dutyPersonShift;
        }).collect(Collectors.toSet());
        if (!personShiftList.isEmpty()) {
            dutyPersonShiftService.saveOrUpdateBatch(personShiftList);
        }
    }

    public void dataCheck(List<DutyPersonShiftDto> dutyShiftList,Long instanceId ,String type){
        try {
            //获取排班月份的最大及最小日期
            Date maxDate = DateUtils.maxDateOfMonth(dutyShiftList.get(0).getDutyDate());
            Date minDate = DateUtils.minDateOfMonth(dutyShiftList.get(0).getDutyDate());
            //拿到当前这个人指定月所有排班数据
            List<DutyPersonShiftDto> currentData = dutyPersonShiftMapper.queryDutyByPersonAndData(instanceId, minDate, maxDate);
            //对本次排班数据和历史排班数据的交集做主键赋值 执行更新 避免索引冲突
            dutyShiftList.forEach(e->{
                for (Iterator<DutyPersonShiftDto> iterator = currentData.listIterator();iterator.hasNext();){
                    DutyPersonShiftDto next = iterator.next();
                    if ( DateUtils.dateCompare(e.getDutyDate(),next.getDutyDate()) == 0){
                        e.setSequenceNbr(next.getSequenceNbr());
                        iterator.remove();
                    };
                }
            });
            //若修改时将原有值班改为请选择 需删除原有排班 否则无法置空原有数据
            if (currentData.size()>0 && ActionStatus.METHOD_UPDATE.getCode().equals(type) ){
                ArrayList<Long> ids = new ArrayList<>();
                currentData.stream().forEach(e->ids.add(e.getSequenceNbr()));
                dutyPersonShiftService.deleteBatchSeq(ids);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void buildFormInstanceData(Long instanceId, Map<String, Object> map, DynamicFormColumn column, DynamicFormInstance formInstance) {
        fillFormInstanceData(instanceId, map, column, formInstance, sequence.nextId());
    }


    @Override
    public List<DutyPersonDto> findByDutyAreaId(Long dutyAreaId) {
        Date now = new Date();
        Calendar c = Calendar.getInstance();
        c.setTime(now);
        c.set(Calendar.DAY_OF_MONTH, 1);
        c.set(Calendar.HOUR_OF_DAY,0);
        c.set(Calendar.MINUTE,0);
        c.set(Calendar.SECOND,0);
        String beginDate = DateUtils.date2LongStr(c.getTime());
        c.setTime(now);
        c.add(Calendar.MONTH, 1);
        c.set(Calendar.DAY_OF_MONTH, 1);
        c.add(Calendar.DATE, -1);
        c.set(Calendar.HOUR_OF_DAY,23);
        c.set(Calendar.MINUTE,59);
        c.set(Calendar.SECOND,59);
        String endDate = DateUtils.date2LongStr(c.getTime());
        List<DutyPersonDto> temp = new ArrayList<>();
        dutyPersonShiftService.list(new LambdaQueryWrapper<DutyPersonShift>()
                        .ge(beginDate != null, DutyPersonShift::getDutyDate, beginDate)
                        .le(endDate != null, DutyPersonShift::getDutyDate, endDate).groupBy(DutyPersonShift::getInstanceId))
                .stream().forEach(e -> {
                    //1.查询已有数据
                    List<DynamicFormInstance> instances = dynamicFormInstanceService.list(new LambdaQueryWrapper<DynamicFormInstance>().eq(DynamicFormInstance::getInstanceId, e.getInstanceId()).eq(DynamicFormInstance::getGroupCode,this.getGroupCode()));
                    if(instances.size() > 0) {
                        DutyPersonDto dto = new DutyPersonDto();
                        boolean add = false;
                        for(DynamicFormInstance t : instances) {
                            if("userId".equals(t.getFieldCode())) {
                                dto.setUserId(t.getFieldValue());
                            } else if("userName".equals(t.getFieldCode())) {
                                dto.setUserName(t.getFieldValue());
                            } else if("deptId".equals(t.getFieldCode())) {
                                dto.setDeptId(t.getFieldValue());
                            } else if("deptName".equals(t.getFieldCode())) {
                                dto.setDeptName(t.getFieldValue());
                            } else if("postType".equals(t.getFieldCode())) {
                                dto.setPostType(t.getFieldValue());
                            } else if("postTypeName".equals(t.getFieldCode())) {
                                dto.setPostTypeName(t.getFieldValue());
                            } else if("dutyArea".equals(t.getFieldCode())) {
                                dto.setDutyArea(t.getFieldValue());
                            } else if("dutyAreaId".equals(t.getFieldCode())) {
                                if(dutyAreaId.toString().equals(t.getFieldValue())) {
                                    add = true;
                                }
                                dto.setDutyAreaId(t.getFieldValue());
                            }
                        }
                        if(add) {
                            temp.add(dto);
                        }
                    }
                });
        return temp;
    }




public Object BuildScheduleDetails(String dutyDay, Long shiftId, String postType) {

		List<Map<String, Object>> list = dayDutyPersonList(dutyDay, shiftId, postType);
		list.stream().forEach(i->{
			List<Object> fieldsList= new ArrayList<Object>();
			List<Object>infoList= new ArrayList<Object>();
			LinkedHashMap<String, String> map = new LinkedHashMap<String, String>();
			map.put("name", "微型消防站");
			map.put("value",i.get("deptName").toString());
			map.put("id","1");
			fieldsList.add(map);
			map.clear();
			map.put("name", "微型消防站");
			map.put("value",i.get("deptName").toString());

		});



		return postType;
	}

    public static void main(String[] args) {
		String ssString="[{\"teamName\":\"发士大夫大师傅\",\"shiftId\":\"1437585222345547778\",\"carName\":\"特种消防车(46586458)\",\"postType\":\"\",\"dutyArea\":\"测试控制室\",\"dutyAreaId\":\"1382166994773610497\",\"postTypeName\":\"\",\"userName\":\"故障报修\",\"userId\":\"1428653787706347522\",\"dutyDate\":\"2021-10-12 00:00:00\",\"carId\":\"1432590747256770562\",\"shiftName\":\"晚班\",\"instanceId\":\"1447490875843239937\",\"teamId\":\"1404995716634050561\",\"groupCode\":\"dutyCar\"},{\"teamName\":\"发士大夫大师傅\",\"shiftId\":\"1432883228491972609\",\"carName\":\"特种消防车(46586458)\",\"postType\":\"\",\"dutyArea\":\"消防小室-shg\",\"dutyAreaId\":\"1382530839199387650\",\"postTypeName\":\"\",\"userName\":\"78678676\",\"userId\":\"1435886728803000322\",\"dutyDate\":\"2021-10-12 00:00:00\",\"carId\":\"1432590747256770562\",\"shiftName\":\"夜班\",\"instanceId\":\"1447490812534415361\",\"teamId\":\"1404995716634050561\",\"groupCode\":\"dutyCar\"},{\"teamName\":\"发士大夫大师傅\",\"shiftId\":\"1432883228491972609\",\"carName\":\"特种消防车(46586458)\",\"postType\":\"1\",\"dutyArea\":\"建构住-shg\",\"dutyAreaId\":\"1382157469081407490\",\"postTypeName\":\"指挥员\",\"userName\":\"张小四6\",\"userId\":\"1435072204550225922\",\"dutyDate\":\"2021-10-12 00:00:00\",\"carId\":\"1432590747256770562\",\"shiftName\":\"夜班\",\"instanceId\":\"1447490699435008001\",\"teamId\":\"1404995716634050561\",\"groupCode\":\"dutyCar\"}]\r\n"
				+ "";
	List<Map>	jjList= JSONArray.parseArray(ssString, Map.class);
	Map< String, String> map20 = new HashMap<String, String>();
	jjList.forEach(i->{
		List<Object> fieldsList= new ArrayList<Object>();
		List<Object>infoList= new ArrayList<Object>();
		Map<String, String> map = new HashMap<String, String>();
		map.put("name", "微型消防站");
		map.put("value",i.get("carName").toString());
		map.put("id","1");
		fieldsList.add(map);
		Map<String, String> map1 = new HashMap<String, String>();
		map1.put("name", "微型消防站");
		map1.put("value",i.get("teamName").toString());
		map1.put("id","2");
		fieldsList.add(map1);
	 if(!map20.containsKey(i.get("shiftName").toString())) {
		 map20.put(ssString, ssString);
	 }

		System.out.println("ssssssssss");
	});


	}

	@Override
    public   List<Map<String, Object>> queryByCompanyId(List<String> bizNames){
        return   dutyPersonShiftMapper.queryByCompanyId(bizNames);
    }

    @Override
    public   List<Map<String, Object>> queryByCompanyNew(String bizOrgName){
        return   dutyPersonShiftMapper.queryByCompanyNew(bizOrgName);
    }


    public Object getSchedulingDutyForSpecifyDate(String dutyDay, Long shiftId, String postType, String fieldCode) {
        List<Map<String, String>> dutyLogs = dutyPersonShiftLogMapper.selectSpecificDateLogForPerson(dutyDay);
        Map<String, List<Map<String, String>>> dutyLogGroups = dutyLogs.stream().collect(Collectors.groupingBy(v -> v.get("deptName")));
        List<Object> result = new ArrayList<>();

        // 获取排序规则: BizOrgName: 部门名称，OrgExpandAttr1: 排序字段
        List<OrgUsr> orgUserSortRules = orgUsrMapper.selectList(
                Wrappers.<OrgUsr>lambdaQuery()
                        .select(OrgUsr::getBizOrgName, OrgUsr::getOrgExpandAttr1)
                        .isNotNull(OrgUsr::getOrgExpandAttr1)
                        .ne(OrgUsr::getOrgExpandAttr1, "")
        ).stream().sorted(Comparator.comparing(v -> Integer.parseInt(v.getOrgExpandAttr1()))).collect(Collectors.toList());
        // orgUserSortRules中的BizOrgName对应dutyLogGroups的key， 按照OrgExpandAttr1排序, OrgExpandAttr1值越小越靠前，否则靠后。
        Map<String, List<Map<String, String>>> sortedDutyLogGroups = new LinkedHashMap<>();
        for (OrgUsr orgUsr : orgUserSortRules) {
            String bizOrgName = orgUsr.getBizOrgName();
            if (dutyLogGroups.containsKey(bizOrgName)) {
                sortedDutyLogGroups.put(bizOrgName, dutyLogGroups.get(bizOrgName));
            }
        }
        for (Map.Entry<String, List<Map<String, String>>> entry : dutyLogGroups.entrySet()) {
            String key = entry.getKey();
            if (!sortedDutyLogGroups.containsKey(key)) {
                sortedDutyLogGroups.put(key, entry.getValue());
            }
        }

        // 岗位排序规则 name: 岗位名称，sortNum: 排序字段
        List<DataDictionary> postSortRules = dataDictionaryMapper.selectList(
                Wrappers.<DataDictionary>lambdaQuery()
                        .select(DataDictionary::getName, DataDictionary::getSortNum)
                        .eq(DataDictionary::getType, "DUTY_POST_TYPE")
                        .eq(DataDictionary::getIsDelete, false)
        ).stream().sorted(Comparator.comparing(DataDictionary::getSortNum)).collect(Collectors.toList());

        // 组装数据
        for (Map.Entry<String, List<Map<String, String>>> entry : sortedDutyLogGroups.entrySet()) {
            List<Object> items = new ArrayList<>();
            String key = entry.getKey();
            List<Map<String, String>> value = entry.getValue();

            items.add(key);
            // postSortRules的name对应value的postTypeName，按照sortNum排序，sortNum值越小越靠前，否则靠后。
            Map<String, String> sortedValue = new LinkedHashMap<>();
            for (DataDictionary dataDictionary : postSortRules) {
                String name = dataDictionary.getName();
                for (Map<String, String> map : value) {
                    if (name.equals(map.get("postTypeName"))) {
                        sortedValue.put(name, map.getOrDefault("dutyUsers", ""));
                    }
                }
            }
            // 未匹配到的数据，按照原有顺序放到最后
            for (Map<String, String> map : value) {
                String postTypeName = map.get("postTypeName");
                if (!sortedValue.containsKey(postTypeName)) {
                    sortedValue.put(postTypeName, map.getOrDefault("dutyUsers", ""));
                }
            }
            for (Map.Entry<String, String> sortedEntry : sortedValue.entrySet()) {
                Map<String, String> itemN = new HashMap<String, String>() {{
                    this.put(sortedEntry.getKey(), sortedEntry.getValue());
                }};
                items.add(itemN);
            }
            result.add(items);
        }
        return result;
	}


    public Object getDutyPersonShiftLogData(String dutyDay, String fieldCode) {
        List<Map<String, Object>> equipmentList = dutyPersonShiftMapper.getNewEquipmentForSpecifyDate(dutyDay,
                this.getGroupCode(), "deptId", "deptName", "result.deptId");
        if (equipmentList == null || equipmentList.isEmpty() || equipmentList.get(0) == null) {
            return null;
        }
        List<Object> detailList = new ArrayList<>();
        for (Map<String, Object> map : equipmentList) {
            List<Object> resultList = new ArrayList<>();
            if(map.containsKey("deptName") && map.get("deptName") != null){
                resultList.add( map.get("deptName").toString());
            }
            String carId = map.get("deptId").toString();
            Map<String, Object> instanceMap = dutyPersonShiftMapper.getInstanceIdForSpecifyDateAndEquipment(dutyDay,
                    this.getGroupCode(), carId);
            if (instanceMap == null) {
                continue;
            }
            String instanceId = instanceMap.get("instanceIds").toString();
            if (StringUtils.isNotBlank(instanceId)) {
                String[] instanceIds = instanceId.split(",");

                // 获取当前装备ID下的排版数据
                List<Map<String, Object>> specifyDateList = dutyPersonShiftMapper
                        .getPositionStaffDutyForSpecifyDate(dutyDay, this.getGroupCode(), instanceIds,
                                null, fieldCode);
                if (specifyDateList == null || specifyDateList.isEmpty() || specifyDateList.get(0) == null) {
                    continue;
                }
                for (Map<String, Object> specify : specifyDateList) {
                    LinkedHashMap<String, Object> infoMap_2 = new LinkedHashMap<>();
                    if( specify.containsKey("postTypeName")&& specify.get("postTypeName")!=null && specify.containsKey("userName")&& specify.get("userName")!=null ) {
                        infoMap_2.put(specify.get("postTypeName").toString(),specify.get("userName").toString());
                        resultList.add(infoMap_2);
                    }
                }
            }
            detailList.add(resultList);
        }
        return detailList;
    }

    @Override
    public void writeHistoryDutyLog() {
        List<Map<String, Object>> list;
        try {
            list = this.list(null, "1980-01-01", "9999-12-12");
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
        for (Map<String, Object> map : list) {
            DutyPersonDto dutyPersonDto = (DutyPersonDto) Bean.mapToBean(map, DutyPersonDto.class);
            this.createDutyPersonShiftLog(dutyPersonDto, true, null);
        }
    }

    public Map<String, List<DutyPersonShiftLog>> getDownloadData(String beginDate, String endDate) throws ParseException {
        Map<String, List<DutyPersonShiftLog>> resultSortedMap = new LinkedHashMap<>();
        List<DutyPersonShiftLog> dutyCarLogs = dutyPersonShiftLogMapper.selectList(
                Wrappers.<DutyPersonShiftLog>lambdaQuery()
                        .ge(DutyPersonShiftLog::getDutyDate, beginDate)
                        .le(DutyPersonShiftLog::getDutyDate, endDate)
                        .eq(DutyPersonShiftLog::getGroupCode, "dutyPerson")
                        .eq(DutyPersonShiftLog::getIsDelete, false)
        );
        if (dutyCarLogs.isEmpty()) {
            return resultSortedMap;
        }
        List<Long> userIds = dutyCarLogs.stream().map(v -> Long.valueOf(v.getDutyUserId())).distinct().collect(Collectors.toList());
        // 获取人员姓名与人员部门的关系
        List<Map<String, String>> userDeptMapList = orgUsrMapper.selectUserDeptMap(userIds);
        // userDeptMapList 转为 Map， key: userName, value
        Map<String, String> userDeptMap = new HashMap<>();
        for (Map<String, String> map : userDeptMapList) {
            userDeptMap.put(map.get("userName"), map.get("deptName"));
        }
        Map<String, List<DutyPersonShiftLog>> unsortedMap = dutyCarLogs.stream().collect(Collectors.groupingBy(DutyPersonShiftLog::getDutyUser));
        // 先按照人员所属部门排序, 部门相同的情况下按照人员岗位排序即可
        // 获取人员部门排序规则: BizOrgName: 部门名称，OrgExpandAttr1: 排序字段
        List<OrgUsr> orgUserSortRules = orgUsrMapper.selectList(
                Wrappers.<OrgUsr>lambdaQuery()
                        .select(OrgUsr::getBizOrgName, OrgUsr::getOrgExpandAttr1)
                        .isNotNull(OrgUsr::getOrgExpandAttr1)
                        .ne(OrgUsr::getOrgExpandAttr1, "")
        ).stream().sorted(Comparator.comparing(v -> Integer.parseInt(v.getOrgExpandAttr1()))).collect(Collectors.toList());

        // 进行排序：按照人员部门排序 userDeptMap为人员与所属部门映射，orgUserSortRules为部门排序规则。orgUserSortRules中部门的顺序即为部门排序规则
        for (OrgUsr orgUsr : orgUserSortRules) {
            String bizOrgName = orgUsr.getBizOrgName();
            for (Map.Entry<String, List<DutyPersonShiftLog>> entry : unsortedMap.entrySet()) {
                String userName = entry.getKey();
                List<DutyPersonShiftLog> dutyPersonShiftLogs = entry.getValue();
                if (userDeptMap.containsKey(userName) && userDeptMap.get(userName).equals(bizOrgName)) {
                    resultSortedMap.put(userName, dutyPersonShiftLogs);
                }
            }
        }
        // 未匹配到的数据，按照原有顺序放到最后
        for (Map.Entry<String, List<DutyPersonShiftLog>> entry : unsortedMap.entrySet()) {
            String userName = entry.getKey();
            List<DutyPersonShiftLog> dutyPersonShiftLogs = entry.getValue();
            if (!resultSortedMap.containsKey(userName)) {
                resultSortedMap.put(userName, dutyPersonShiftLogs);
            }
        }

        return resultSortedMap;
    }

    @SuppressWarnings("Duplicates")
    public synchronized void createDutyPersonShiftLog(DutyPersonDto dutyPersonDto, boolean isInit, String actionCode) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        List<DutyPersonShiftDto> dutyPersonShift = dutyPersonDto.getDutyShift();
        final String groupCode = "dutyPerson";

        // 更新排班时处理
        if (!isInit && Objects.equals(actionCode, "update")) {
            TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
                @Override
                public void afterCommit() {
                    if (Objects.nonNull(dutyPersonShift) && !dutyPersonShift.isEmpty()) {
                        String month = dateFormat.format(dutyPersonShift.get(0).getDutyDate()).substring(0, 7);
                        String startDate = month + "-01";
                        String endDate = DateUtils.getLastDayOfMonth(month);
                        String today = dateFormat.format(new Date());
                        try {
                            startDate = isAfterToday(dateFormat.parse(startDate)) ? startDate : today;
                        } catch (ParseException e) {
                            throw new RuntimeException(e);
                        }
                        dutyPersonShiftLogMapper.delete(
                                Wrappers.<DutyPersonShiftLog>lambdaQuery()
                                        .eq(DutyPersonShiftLog::getGroupCode, groupCode)
                                        .eq(DutyPersonShiftLog::getDutyUserId, dutyPersonDto.getUserId())
                                        .ge(DutyPersonShiftLog::getDutyDate, startDate)
                                        .le(DutyPersonShiftLog::getDutyDate, endDate)
                                        .eq(DutyPersonShiftLog::getIsDelete, false)
                        );
                    }
                }
            });
        }

        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
            @Override
            public void afterCommit() {
                Set<String> dutyDates = dutyPersonShift.stream().map(v -> dateFormat.format(v.getDutyDate())).collect(Collectors.toSet());
                if (dutyDates.isEmpty()) {
                    return;
                }
                Map<Date, List<DutyPersonShiftLog>> dutyLogGroups = dutyPersonShiftLogMapper.selectList(
                        Wrappers.<DutyPersonShiftLog>lambdaQuery()
                                .in(DutyPersonShiftLog::getDutyDate, dutyDates)
                                .eq(DutyPersonShiftLog::getGroupCode, groupCode)
                                .eq(DutyPersonShiftLog::getDutyUserId, dutyPersonDto.getUserId())
                                .eq(DutyPersonShiftLog::getIsDelete, false)
                ).stream().collect(Collectors.groupingBy(DutyPersonShiftLog::getDutyDate));

                for (DutyPersonShiftDto dutyPersonShiftDto : dutyPersonShift) {
                    // 非初始化非历史数据禁止修改
                    if (!isAfterToday(dutyPersonShiftDto.getDutyDate()) && !isInit) {
                        continue;
                    }
                    List<DutyPersonShiftLog> dutyPersonShiftLogs = dutyLogGroups.get(dutyPersonShiftDto.getDutyDate());
                    DutyPersonShiftLog dutyPersonShiftLog = Objects.nonNull(dutyPersonShiftLogs) && !dutyPersonShiftLogs.isEmpty() ? dutyPersonShiftLogs.get(0) : null;

                    // 日志不存在：新建
                    if (Objects.isNull(dutyPersonShiftLog)) {
                        dutyPersonShiftLog = new DutyPersonShiftLog();
                        dutyPersonShiftLog.setInstanceId(dutyPersonShiftDto.getInstanceId());
                        dutyPersonShiftLog.setDutyDate(dutyPersonShiftDto.getDutyDate());
                        dutyPersonShiftLog.setGroupCode(groupCode);
                        dutyPersonShiftLog.setDeptName(dutyPersonDto.getDeptName());
                        dutyPersonShiftLog.setDutyUserId(dutyPersonDto.getUserId());
                        dutyPersonShiftLog.setDutyUser(dutyPersonDto.getUserName());
                        dutyPersonShiftLog.setPostTypeName(dutyPersonDto.getPostTypeName());
                        dutyPersonShiftLog.setDutyArea(dutyPersonDto.getDutyArea());
                        String shiftName = dutyPersonShiftDto.getShiftName();
                        if (StringUtils.isBlank(shiftName) && Objects.nonNull(dutyPersonShiftDto.getShiftId())) {
                            DutyShift dutyShift = dutyShiftService.getById(dutyPersonShiftDto.getShiftId());
                            dutyPersonShiftDto.setShiftName(dutyShift.getName());
                        }
                        dutyPersonShiftLog.setShiftName(dutyPersonShiftDto.getShiftName());
                        dutyPersonShiftLogMapper.insert(dutyPersonShiftLog);
                        continue;
                    }
                    if (isAfterToday(dutyPersonShiftDto.getDutyDate())) {
                        dutyPersonShiftLog.setInstanceId(dutyPersonShiftDto.getInstanceId());
                        dutyPersonShiftLog.setDeptName(dutyPersonDto.getDeptName());
                        dutyPersonShiftLog.setPostTypeName(dutyPersonDto.getPostTypeName());
                        dutyPersonShiftLog.setDutyArea(dutyPersonDto.getDutyArea());
                        String shiftName = dutyPersonShiftDto.getShiftName();
                        if (StringUtils.isBlank(shiftName) && Objects.nonNull(dutyPersonShiftDto.getShiftId())) {
                            DutyShift dutyShift = dutyShiftService.getById(dutyPersonShiftDto.getShiftId());
                            dutyPersonShiftDto.setShiftName(dutyShift.getName());
                        }
                        dutyPersonShiftLog.setShiftName(dutyPersonShiftDto.getShiftName());
                        dutyPersonShiftLogMapper.update(
                                dutyPersonShiftLog,
                                Wrappers.<DutyPersonShiftLog>lambdaUpdate()
                                        .eq(DutyPersonShiftLog::getDutyDate, dutyPersonShiftDto.getDutyDate())
                                        .eq(DutyPersonShiftLog::getGroupCode, groupCode)
                                        .eq(DutyPersonShiftLog::getDutyUserId, dutyPersonDto.getUserId())
                                        .eq(DutyPersonShiftLog::getIsDelete, false)
                        );
                    }
                }
            }
        });
    }
}
