
package com.hz.pm.api.ding.task;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.collect.Lists;
import com.ningdatech.basic.model.GenericResult;
import com.hz.pm.api.common.model.constant.BizConst;
import com.hz.pm.api.ding.model.DingOrgInfoTreeDTO;
import com.hz.pm.api.organization.model.entity.DingOrganization;
import com.hz.pm.api.organization.service.IDingOrganizationService;
import com.ningdatech.zwdd.client.ZwddClient;
import com.ningdatech.zwdd.model.dto.DingOrgInfoDTO;
import com.ningdatech.zwdd.model.dto.DingScopesV2DTO;
import com.ningdatech.zwdd.model.dto.PageSubOrganizationCodeDTO;
import lombok.extern.slf4j.Slf4j;
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.Objects;
import java.util.stream.Collectors;

/**
 * @author liuxinxin
 * @date 2023/2/7 上午10:15
 */

@Slf4j
@Component
public class OrganizationBatchGetTask {

    @Autowired
    private ZwddClient zwddClient;

    private static final Integer GROUP_SIZE = 100;

    @Autowired
    private IDingOrganizationService iDingOrganizationService;

    @Autowired
    private EmployeeBatchGetTask employeeBatchGetTask;

    /**
     * 获取浙政钉组织架构
     */
    @Transactional(rollbackFor = Exception.class)
//    @Scheduled(cron = "0 0 1 * * ?")
    public void batchGetOrganizationTask() {
//        List<DingOrganization> allList = iDingOrganizationService.list();
//        List<String> currentAllOrganizationCodeList = allList.stream().map(DingOrganization::getOrganizationCode).collect(Collectors.toList());
        // 全量删除
         iDingOrganizationService.remove(Wrappers.lambdaQuery(DingOrganization.class).isNotNull(DingOrganization::getId));
        // 获取顶级组织code
        GenericResult<DingScopesV2DTO> scopesV2Result = zwddClient.getScopesV2();
        DingScopesV2DTO scopesV2 = scopesV2Result.getData();

        if (Objects.nonNull(scopesV2)) {
            // 顶级组织code
            List<String> deptVisibleScopes = scopesV2.getDeptVisibleScopes();
            log.info("顶级组织code: size = " + deptVisibleScopes.size() + "列表：" + JSONObject.toJSONString(deptVisibleScopes));
            // 获取顶级节点信息
            GenericResult<List<DingOrgInfoDTO>> listGenericResult = zwddClient.listOrganizationsByCodes(deptVisibleScopes);
            log.info("listGenericResult: {}" + JSON.toJSONString(listGenericResult));
            List<DingOrgInfoDTO> dingOrgInfoDtos = listGenericResult.getData();
            for (String orgCode : deptVisibleScopes) {
//                if (currentAllOrganizationCodeList.contains(orgCode)) {
//                    log.info("已存在组织架构---{}", orgCode);
//                    continue;
//                }
                List<DingOrgInfoTreeDTO> treeDTOList = new ArrayList<>();

                DingOrgInfoTreeDTO childDingOrgInfoTreeDTO = new DingOrgInfoTreeDTO();
                //设置节点详情
                if (dingOrgInfoDtos != null && !dingOrgInfoDtos.isEmpty()) {
                    for (DingOrgInfoDTO orgInfo : dingOrgInfoDtos) {
                        if (orgInfo.getOrganizationCode().equals(orgCode)) {
                            childDingOrgInfoTreeDTO.setDingOrgInfoDTO(orgInfo);
                        }
                    }
                }
                childDingOrgInfoTreeDTO.setCode(orgCode);
                childDingOrgInfoTreeDTO.setChildCodes(new ArrayList<>());
                getDingOrgChild(childDingOrgInfoTreeDTO);
                treeDTOList.add(childDingOrgInfoTreeDTO);
                if (CollectionUtils.isNotEmpty(treeDTOList)) {
                    List<DingOrganization> saveRecordList = new ArrayList<>();
                    buildSaveRecordList(treeDTOList, saveRecordList);
                    // 批量保存
                    if (saveRecordList.size() <= GROUP_SIZE) {
                        iDingOrganizationService.saveBatch(saveRecordList);
                    } else {
                        List<List<DingOrganization>> split = Lists.partition(saveRecordList, GROUP_SIZE);
                        for (List<DingOrganization> segment : split) {
                            iDingOrganizationService.saveBatch(segment);
                        }
                    }
                }
                log.info("----拉取浙政钉组织结构结束---,顶级code：" + orgCode);
            }
        }
    }

    /**
     * 更新 其 子单位
     * @param orgCode
     */
    public void organizationGetSubs(String orgCode) {
        log.info("----拉取浙政钉组织子单位开始---,顶级code：" + orgCode);
        DingOrganization topOrg = iDingOrganizationService.getOne(Wrappers.lambdaQuery(DingOrganization.class)
                .eq(DingOrganization::getOrganizationCode, orgCode)
                .last(BizConst.LIMIT_1));
        // 顶级组织code
        GenericResult<PageSubOrganizationCodeDTO> subOrganizationResult = zwddClient.pageSubOrganizationCodes(1, 100, orgCode);
        log.info("subOrganizationResult: {}" + JSON.toJSONString(subOrganizationResult));
        PageSubOrganizationCodeDTO data = subOrganizationResult.getData();
        List<String> subOrganizationCodeList = data.getSubOrganizationCodeList();

        if(Objects.isNull(subOrganizationCodeList)){
            log.info("subOrganizationCodeList为null");
            return;
        }

        employeeBatchGetTask.batchGetEmployeeTaskByOrdCode(orgCode);

        for(String subOrganizationCode : subOrganizationCodeList){
            GenericResult<DingOrgInfoDTO> organizationByCode = zwddClient.getOrganizationByCode(subOrganizationCode);
            DingOrgInfoDTO dingOrgInfo = organizationByCode.getData();
            DingOrganization old = iDingOrganizationService.getOne(Wrappers.lambdaQuery(DingOrganization.class)
                    .eq(DingOrganization::getOrganizationCode, dingOrgInfo.getOrganizationCode())
                    .last(BizConst.LIMIT_1));
            if(Objects.nonNull(old)){
                log.info("该单位已经存在 :{}",old.getOrganizationName());
                organizationGetSubs(dingOrgInfo.getOrganizationCode());
//                employeeBatchGetTask.batchGetEmployeeTaskByOrdCode(dingOrgInfo.getOrganizationCode());
                continue;
            }

            DingOrganization organization = new DingOrganization();
            organization.setOrganizationCode(dingOrgInfo.getOrganizationCode());
            organization.setOrganizationName(dingOrgInfo.getOrganizationName());
            //和顶级单位一个区域
            organization.setDivisionCode(topOrg.getDivisionCode());
            organization.setParentCode(dingOrgInfo.getParentCode());
            organization.setTypeName(dingOrgInfo.getTypeName());
            organization.setAddress(dingOrgInfo.getAddress());
            organization.setBusinessStripCodes(dingOrgInfo.getBusinessStripCodes());
            organization.setDisplayOrder(dingOrgInfo.getDisplayOrder());
            organization.setGmtCreate(LocalDateTime.now());
            organization.setInstitutionLevelCode(dingOrgInfo.getInstitutionLevelCode());
            organization.setParentName(dingOrgInfo.getParentName());
            if(iDingOrganizationService.save(organization)){
                organizationGetSubs(organization.getOrganizationCode());
//                employeeBatchGetTask.batchGetEmployeeTaskByOrdCode(organization.getOrganizationCode());
            }
        }

        log.info("----拉取浙政钉组织子单位结束---,顶级code：" + orgCode);
    }

    /**
     * 查看下 当前的子单位信息
     * @param orgCode
     */
    public void organizationSubGetOrgs(String orgCode) {
        // 顶级组织code
        GenericResult<PageSubOrganizationCodeDTO> subOrganizationResult = zwddClient.pageSubOrganizationCodes(1, 100, orgCode);
        log.info("subOrganizationResult: {}" + JSON.toJSONString(subOrganizationResult));
        PageSubOrganizationCodeDTO data = subOrganizationResult.getData();
        List<String> subOrganizationCodeList = data.getSubOrganizationCodeList();

        if(Objects.isNull(subOrganizationCodeList)){
            log.info("subOrganizationCodeList为null");
            return;
        }

        for(String subOrganizationCode : subOrganizationCodeList){
            GenericResult<DingOrgInfoDTO> organizationByCode = zwddClient.getOrganizationByCode(subOrganizationCode);
            DingOrgInfoDTO dingOrgInfo = organizationByCode.getData();
            log.info("dingOrgInfo :{}",JSON.toJSONString(dingOrgInfo));
        }
    }

    private void buildSaveRecordList(List<DingOrgInfoTreeDTO> treeDTOList, List<DingOrganization> saveRecordList) {
        if (CollectionUtils.isEmpty(treeDTOList)) {
            return;
        }
        for (DingOrgInfoTreeDTO dingOrgInfoTreeDTO : treeDTOList) {
            DingOrganization saveRecord = new DingOrganization();
            DingOrgInfoDTO dingOrgInfoDTO = dingOrgInfoTreeDTO.getDingOrgInfoDTO();
            List<DingOrgInfoTreeDTO> childCodes = dingOrgInfoTreeDTO.getChildCodes();
            saveRecord.setDisplayOrder(dingOrgInfoDTO.getDisplayOrder());
//            saveRecord.setEnabled("1");
            saveRecord.setParentCode(dingOrgInfoDTO.getParentCode());
            saveRecord.setTypeCode(dingOrgInfoDTO.getTypeCode());
            saveRecord.setTypeName(dingOrgInfoDTO.getTypeName());
            saveRecord.setOrganizationCode(dingOrgInfoDTO.getOrganizationCode());
//            saveRecord.setSubCount((long) dingOrgInfoTreeDTO.getChildCodes().size());
            saveRecord.setOrganizationName(dingOrgInfoDTO.getOrganizationName());
            saveRecord.setDivisionCode(dingOrgInfoDTO.getDivisionCode());
            saveRecordList.add(saveRecord);
            if (CollectionUtils.isNotEmpty(childCodes)) {
                buildSaveRecordList(childCodes, saveRecordList);
            }
        }
    }

    private void getDingOrgChild(DingOrgInfoTreeDTO parentDingOrgInfoTreeDTO) {
        String parentOrgCode = parentDingOrgInfoTreeDTO.getCode();
        DingOrgInfoDTO orgInfoDTO = parentDingOrgInfoTreeDTO.getDingOrgInfoDTO();
        boolean leaf = orgInfoDTO.getLeaf();
        if (!leaf) {
            int currentPage = 1;
            int pageSize = 100;
            GenericResult<PageSubOrganizationCodeDTO> pageSubOrganizationCodeDTOGenericResult = zwddClient.pageSubOrganizationCodes(currentPage++, pageSize, parentOrgCode);
            PageSubOrganizationCodeDTO pageSubOrganizationCodeDTO = pageSubOrganizationCodeDTOGenericResult.getData();

            if (CollUtil.isNotEmpty(pageSubOrganizationCodeDTO.getSubOrganizationCodeList())) {
                List<String> subOrganizationCodeList = new ArrayList<>(pageSubOrganizationCodeDTO.getSubOrganizationCodeList());
                Long totalSize = pageSubOrganizationCodeDTO.getTotalSize();

                while (totalSize > (long) currentPage * pageSize) {
                    GenericResult<PageSubOrganizationCodeDTO> subPageSubOrganizationCodeDTOGenericResult = zwddClient
                            .pageSubOrganizationCodes(currentPage++, pageSize, parentOrgCode);
                    PageSubOrganizationCodeDTO subOrganizationCodeDTO = subPageSubOrganizationCodeDTOGenericResult.getData();
                    if (CollectionUtils.isNotEmpty(subOrganizationCodeDTO.getSubOrganizationCodeList())) {
                        subOrganizationCodeList.addAll(subOrganizationCodeDTO.getSubOrganizationCodeList());
                    }
                }

                if (CollectionUtils.isNotEmpty(subOrganizationCodeList)) {
                    GenericResult<List<DingOrgInfoDTO>> listGenericResult = zwddClient
                            .listOrganizationsByCodes(subOrganizationCodeList);
                    List<DingOrgInfoDTO> dingOrgInfoDtos = listGenericResult.getData();
                    List<DingOrgInfoTreeDTO> dingOrgInfoTreeDTOList = dingOrgInfoDtos.stream().map(r -> {
                        DingOrgInfoTreeDTO dingOrgInfoTreeDTO = new DingOrgInfoTreeDTO();
                        dingOrgInfoTreeDTO.setCode(r.getOrganizationCode());
                        dingOrgInfoTreeDTO.setDingOrgInfoDTO(r);
                        dingOrgInfoTreeDTO.setChildCodes(new ArrayList<>());
                        getDingOrgChild(dingOrgInfoTreeDTO);
                        return dingOrgInfoTreeDTO;
                    }).collect(Collectors.toList());
                    parentDingOrgInfoTreeDTO.setChildCodes(dingOrgInfoTreeDTOList);
                }
            }
        }
    }
}


