package com.ningdatech.pmapi.ding.task;

import cn.hutool.core.collection.CollUtil;
import com.google.common.collect.Lists;
import com.ningdatech.basic.model.GenericResult;
import com.ningdatech.pmapi.organization.model.entity.DingEmployeeInfo;
import com.ningdatech.pmapi.organization.model.entity.DingOrganization;
import com.ningdatech.pmapi.organization.service.IDingEmployeeInfoService;
import com.ningdatech.pmapi.organization.service.IDingOrganizationService;
import com.ningdatech.zwdd.ZwddIntegrationProperties;
import com.ningdatech.zwdd.client.ZwddClient;
import com.ningdatech.zwdd.model.Page;
import com.ningdatech.zwdd.model.dto.EmployeeAccountIdDTO;
import com.ningdatech.zwdd.model.query.PageOrganizationEmployeePositionsQuery;
import com.ningdatech.zwdd.model.response.OrganizationEmployeePosition;
import com.ningdatech.zwdd.model.response.OrganizationEmployeePosition.GovEmployeePosition;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author liuxinxin
 * @date 2023/2/10 上午9:52
 */

@Component
public class EmployeeBatchGetTask {

    private final static Integer PAGE_SIZE = 20;

    private final static Integer GROUP_SIZE = 100;

    @Autowired
    private ZwddClient zwddClient;

    @Autowired
    private IDingOrganizationService iDingOrganizationService;

    @Autowired
    private IDingEmployeeInfoService iDingEmployeeInfoService;

    @Autowired
    private ZwddIntegrationProperties zwddIntegrationProperties;

    @Transactional(rollbackFor = Exception.class)
    public void batchGetEmployeeTask() {

        // 获取所有的组织列表用户获取组织下的 用户信息
        List<DingOrganization> dingOrganizationList = iDingOrganizationService.list();
        if (CollUtil.isNotEmpty(dingOrganizationList)) {
            for (DingOrganization dingOrganization : dingOrganizationList) {
                List<OrganizationEmployeePosition> allOrganizationEmployeePositionList = new ArrayList<>();
                String organizationCode = dingOrganization.getOrganizationCode();
                PageOrganizationEmployeePositionsQuery query = new PageOrganizationEmployeePositionsQuery();
                query.setEmployeeStatus("A");
                query.setOrganizationCode(organizationCode);
                query.setReturnTotalSize(true);
                query.setTenantId(zwddIntegrationProperties.getTenantId());
                int pageNo = 1;
                query.setPageNo(pageNo);
                query.setPageSize(PAGE_SIZE);

                // 查询组织下 用户信息
                GenericResult<Page<OrganizationEmployeePosition>> firstPageGenericResult = zwddClient.pageOrganizationEmployeePositions(query);
                Page<OrganizationEmployeePosition> data = firstPageGenericResult.getData();
                if (CollUtil.isNotEmpty(data.getData())) {
                    allOrganizationEmployeePositionList.addAll(data.getData());
                }
                Long totalSize = data.getTotalSize();
                if (totalSize > PAGE_SIZE) {
                    int restPageNo = totalSize % PAGE_SIZE > 0 ? 1 : 0;
                    int maxPageNo = (int) Math.ceil(totalSize / PAGE_SIZE) + restPageNo;
                    for (pageNo = 2; pageNo <= maxPageNo; pageNo++) {
                        query.setPageNo(maxPageNo);
                        GenericResult<Page<OrganizationEmployeePosition>> pageGenericResult = zwddClient.pageOrganizationEmployeePositions(query);
                        if (CollUtil.isNotEmpty(pageGenericResult.getData().getData())) {
                            allOrganizationEmployeePositionList.addAll(pageGenericResult.getData().getData());
                        }
                    }
                }

                // 批量查询 成员的accountId
                List<DingEmployeeInfo> dingEmployeeInfoSaveRecordList = new ArrayList<>();
                if (allOrganizationEmployeePositionList.size() <= GROUP_SIZE) {
                    assemblerAccountId(allOrganizationEmployeePositionList, dingEmployeeInfoSaveRecordList);
                } else {
                    List<List<OrganizationEmployeePosition>> split = Lists.partition(allOrganizationEmployeePositionList, GROUP_SIZE);
                    for (List<OrganizationEmployeePosition> segment : split) {
                        assemblerAccountId(segment, dingEmployeeInfoSaveRecordList);
                    }
                }
                // 批量保存用户信息
                saveBatch(dingEmployeeInfoSaveRecordList);
            }
        }
    }


    private void assemblerAccountId(List<OrganizationEmployeePosition> segment, List<DingEmployeeInfo> dingEmployeeInfoSaveRecordList) {
        List<String> employeeCodes = segment.stream().map(OrganizationEmployeePosition::getEmployeeCode).distinct().collect(Collectors.toList());
        GenericResult<List<EmployeeAccountIdDTO>> listGenericResult = zwddClient.listEmployeeAccountIds(employeeCodes);
        List<EmployeeAccountIdDTO> employeeAccountIdDTOList = listGenericResult.getData();
        Map<String, Long> employeeCodeAccountIdMap = employeeAccountIdDTOList.stream()
                .collect(Collectors.toMap(EmployeeAccountIdDTO::getEmployeeCode, EmployeeAccountIdDTO::getAccountId));

        List<DingEmployeeInfo> dingEmployeeInfos = buildDingEmployeeInfoRecordList(segment);

        dingEmployeeInfos = dingEmployeeInfos.stream().map(r -> {
            r.setAccountId(employeeCodeAccountIdMap.get(r.getEmployeeCode()));
            return r;
        }).collect(Collectors.toList());
        dingEmployeeInfoSaveRecordList.addAll(dingEmployeeInfos);
    }

    private List<DingEmployeeInfo> buildDingEmployeeInfoRecordList(List<OrganizationEmployeePosition> allOrganizationEmployeePositionList) {
        List<DingEmployeeInfo> saveRecordList = new ArrayList<>();
        for (OrganizationEmployeePosition organizationEmployeePosition : allOrganizationEmployeePositionList) {
            List<GovEmployeePosition> govEmployeePositions = organizationEmployeePosition.getGovEmployeePositions();
            if (CollUtil.isNotEmpty(govEmployeePositions)) {
                List<DingEmployeeInfo> segmentSaveRecordList = new ArrayList<>();
                for (GovEmployeePosition govEmployeePosition : govEmployeePositions) {
                    DingEmployeeInfo dingEmployeeInfo = new DingEmployeeInfo();
                    BeanUtils.copyProperties(organizationEmployeePosition, dingEmployeeInfo);
                    dingEmployeeInfo.setMainJob(govEmployeePosition.getMainJob());
                    dingEmployeeInfo.setEmpPosUnitCode(govEmployeePosition.getEmpPosUnitCode());
                    dingEmployeeInfo.setEmpPosEmployeeRoleCode(govEmployeePosition.getEmpPosEmployeeRoleCode());
                    dingEmployeeInfo.setEmpPosInnerInstitutionCode(govEmployeePosition.getEmpPosInnerInstitutionCode());
                    dingEmployeeInfo.setEmployeeCode(govEmployeePosition.getEmployeeCode());
                    dingEmployeeInfo.setJobAttributesCode(govEmployeePosition.getJobAttributesCode());
                    dingEmployeeInfo.setOrganizationCode(govEmployeePosition.getOrganizationCode());
                    dingEmployeeInfo.setEmpPosVirtualOrganizationCode(govEmployeePosition.getEmpPosVirtualOrganizationCode());
                    dingEmployeeInfo.setEmpStatus(govEmployeePosition.getStatus());
                    dingEmployeeInfo.setCreateOn(LocalDateTime.now());
                    dingEmployeeInfo.setUpdateOn(LocalDateTime.now());
                    dingEmployeeInfo.setCreateBy(-1L);
                    dingEmployeeInfo.setUpdateBy(-1L);
                    segmentSaveRecordList.add(dingEmployeeInfo);
                }
                saveRecordList.addAll(segmentSaveRecordList);
            } else {
                DingEmployeeInfo dingEmployeeInfo = new DingEmployeeInfo();
                BeanUtils.copyProperties(organizationEmployeePosition, dingEmployeeInfo);
                saveRecordList.add(dingEmployeeInfo);
            }
        }
        return saveRecordList;
    }

    private void saveBatch(List<DingEmployeeInfo> dingEmployeeInfoSaveRecordList) {
        if (dingEmployeeInfoSaveRecordList.size() <= GROUP_SIZE) {
            iDingEmployeeInfoService.saveBatch(dingEmployeeInfoSaveRecordList);
        } else {
            List<List<DingEmployeeInfo>> split = Lists.partition(dingEmployeeInfoSaveRecordList, GROUP_SIZE);
            for (List<DingEmployeeInfo> segment : split) {
                iDingEmployeeInfoService.saveBatch(segment);
            }
        }
    }
}
