package com.engine.salary.entity.salaryacct.bo;

import com.engine.salary.constant.SalaryDefaultTenantConstant;
import com.engine.salary.entity.datacollection.DataCollectionEmployee;
import com.engine.salary.entity.salaryacct.dto.SalaryAccEmployeeListDTO;
import com.engine.salary.entity.salaryacct.po.SalaryAcctEmployeePO;
import com.engine.salary.entity.salaryacct.po.SalaryAcctRecordPO;
import com.engine.salary.entity.salaryarchive.dto.SalaryArchiveDataDTO;
import com.engine.salary.entity.salaryarchive.dto.SalaryArchiveTaxAgentDataDTO;
import com.engine.salary.entity.taxagent.po.TaxAgentPO;
import com.engine.salary.enums.UserStatusEnum;
import com.engine.salary.util.SalaryEntityUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;

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

/**
 * 薪资核算人员
 * <p>Copyright: Copyright (c) 2022</p>
 * <p>Company: 泛微软件</p>
 *
 * @author qiantao
 * @version 1.0
 **/
public class SalaryAcctEmployeeBO {

    /**
     * 将薪资核算人员po转换成薪资核算人员列表dto
     *
     * @param salaryAccountingEmployees
     * @param taxAgents
     * @param simpleEmployees
     * @return
     */
    public static List<SalaryAccEmployeeListDTO> convert2EmployeeListDTO(List<SalaryAcctEmployeePO> salaryAccountingEmployees,
                                                                         List<TaxAgentPO> taxAgents,
                                                                         List<DataCollectionEmployee> simpleEmployees) {
        if (CollectionUtils.isEmpty(salaryAccountingEmployees)) {
            return Collections.emptyList();
        }
        Map<Long, String> taxAgentNameMap = SalaryEntityUtil.convert2Map(taxAgents, TaxAgentPO::getId, TaxAgentPO::getName);
        Map<Long, DataCollectionEmployee> simpleEmployeeMap = SalaryEntityUtil.convert2Map(simpleEmployees, DataCollectionEmployee::getEmployeeId);
        return salaryAccountingEmployees.stream()
                .map(e -> {
                    DataCollectionEmployee simpleEmployee = simpleEmployeeMap.get(e.getEmployeeId());
                    if (simpleEmployee == null) {
                        return SalaryAccEmployeeListDTO.builder()
                                .id(e.getId())
                                .employeeId(e.getId())
                                .taxAgentId(e.getTaxAgentId())
                                .taxAgentName(taxAgentNameMap.getOrDefault(e.getTaxAgentId(), StringUtils.EMPTY))
                                .build();
                    }
                    return SalaryAccEmployeeListDTO.builder()
                            .id(e.getId())
                            .employeeId(simpleEmployee.getEmployeeId())
                            .employeeName(simpleEmployee.getUsername())
                            .taxAgentId(e.getTaxAgentId())
                            .taxAgentName(taxAgentNameMap.getOrDefault(e.getTaxAgentId(), StringUtils.EMPTY))
                            .departmentId(simpleEmployee.getDepartmentId())
                            .departmentName(simpleEmployee.getDepartmentName())
                            .status(UserStatusEnum.getDefaultLabelByValue(NumberUtils.toInt(simpleEmployee.getStatus())))
                            .mobile(simpleEmployee.getMobile())
                            .jobNum(simpleEmployee.getWorkcode())
                            .hireDate(simpleEmployee.getCompanystartdate())
                            .dismissDate(simpleEmployee.getDismissdate())
                            .build();
                }).collect(Collectors.toList());
    }

    /**
     * 转换成薪资核算人员的po
     *
     * @param employeeIds
     * @param salaryAcctRecord
     * @param salaryArchiveTaxAgentData
     * @param employeeId
     * @return
     */
    public static List<SalaryAcctEmployeePO> convert2EmployeePO(Collection<Long> employeeIds,
                                                                SalaryAcctRecordPO salaryAcctRecord,
                                                                List<SalaryArchiveDataDTO> salaryArchiveTaxAgentData,
                                                                Long employeeId) {
        if (CollectionUtils.isEmpty(employeeIds)) {
            return Collections.emptyList();
        }
        List<SalaryAcctEmployeePO> resultList = Lists.newArrayList();
        Map<Long, Set<List<SalaryArchiveTaxAgentDataDTO>>> empIdKeyTaxAgentMap = SalaryEntityUtil.group2Map(salaryArchiveTaxAgentData, SalaryArchiveDataDTO::getEmployeeId, SalaryArchiveDataDTO::getTaxAgents);
        Date now = new Date();
        for (Long id : employeeIds) {
            Set<Long> taxAgentIds = Sets.newHashSet();
            Set<List<SalaryArchiveTaxAgentDataDTO>> taxAgentSet = empIdKeyTaxAgentMap.getOrDefault(id, Collections.emptySet());
            for (List<SalaryArchiveTaxAgentDataDTO> taxAgents : taxAgentSet) {
                taxAgentIds.addAll(SalaryEntityUtil.properties(taxAgents, SalaryArchiveTaxAgentDataDTO::getTaxAgentId));
            }
            if (CollectionUtils.isEmpty(taxAgentIds)) {
                taxAgentIds.add(0L);
            }
            for (Long taxAgentId : taxAgentIds) {
                SalaryAcctEmployeePO salaryAcctEmployee = SalaryAcctEmployeePO.builder()
                        .salaryAcctRecordId(salaryAcctRecord.getId())
                        .salarySobId(salaryAcctRecord.getSalarySobId())
                        .salaryMonth(salaryAcctRecord.getSalaryMonth())
                        .employeeId(id)
                        .taxAgentId(taxAgentId)
                        .creator(employeeId)
                        .createTime(now)
                        .updateTime(now)
                        .deleteType(0)
                        .tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY)
                        .build();
                resultList.add(salaryAcctEmployee);
            }
        }
        return resultList;
    }

    public static List<SalaryAcctEmployeePO> convert2Employee(Collection<DataCollectionEmployee> employee,
                                                                SalaryAcctRecordPO salaryAcctRecord,
                                                                List<SalaryArchiveDataDTO> salaryArchiveTaxAgentData,
                                                                Long employeeId) {
        if (CollectionUtils.isEmpty(employee)) {
            return Collections.emptyList();
        }
        List<SalaryAcctEmployeePO> resultList = Lists.newArrayList();
        Map<Long, Set<List<SalaryArchiveTaxAgentDataDTO>>> empIdKeyTaxAgentMap = SalaryEntityUtil.group2Map(salaryArchiveTaxAgentData, SalaryArchiveDataDTO::getEmployeeId, SalaryArchiveDataDTO::getTaxAgents);
        Date now = new Date();
        for (DataCollectionEmployee emp : employee) {
            Set<Long> taxAgentIds = Sets.newHashSet();
            Set<List<SalaryArchiveTaxAgentDataDTO>> taxAgentSet = empIdKeyTaxAgentMap.getOrDefault(emp.getEmployeeId(), Collections.emptySet());
            for (List<SalaryArchiveTaxAgentDataDTO> taxAgents : taxAgentSet) {
                taxAgentIds.addAll(SalaryEntityUtil.properties(taxAgents, SalaryArchiveTaxAgentDataDTO::getTaxAgentId));
            }
            if (CollectionUtils.isEmpty(taxAgentIds)) {
                taxAgentIds.add(0L);
            }
            for (Long taxAgentId : taxAgentIds) {
                SalaryAcctEmployeePO salaryAcctEmployee = SalaryAcctEmployeePO.builder()
                        .salaryAcctRecordId(salaryAcctRecord.getId())
                        .salarySobId(salaryAcctRecord.getSalarySobId())
                        .salaryMonth(salaryAcctRecord.getSalaryMonth())
                        .employeeId(emp.getEmployeeId())
                        .employeeType(emp.isExtEmp() ? 1 : 0)
                        .taxAgentId(taxAgentId)
                        .creator(employeeId)
                        .createTime(now)
                        .updateTime(now)
                        .deleteType(0)
                        .tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY)
                        .build();
                resultList.add(salaryAcctEmployee);
            }
        }
        return resultList;
    }


    public static List<List<SalaryAcctEmployeePO>> partitionByEmployeeId(List<SalaryAcctEmployeePO> salaryAcctEmployees) {
        if (CollectionUtils.isEmpty(salaryAcctEmployees)) {
            return Collections.emptyList();
        }
        List<Long> employeeIdList = salaryAcctEmployees.stream()
                .map(SalaryAcctEmployeePO::getEmployeeId)
                .distinct()
                .collect(Collectors.toList());
        // 每个线程处理多少个人员（一个线程最多处理10个人员）
        int size = 100;
        List<List<Long>> partition = Lists.partition(employeeIdList, size);
        List<List<SalaryAcctEmployeePO>> resultList = new ArrayList<>();
        Map<Long, List<SalaryAcctEmployeePO>> salaryAcctEmployeeMap = SalaryEntityUtil.group2Map(salaryAcctEmployees, SalaryAcctEmployeePO::getEmployeeId);
        for (List<Long> employeeIds : partition) {
            List<SalaryAcctEmployeePO> temp = new ArrayList<>();
            for (Long employeeId : employeeIds) {
                temp.addAll(salaryAcctEmployeeMap.getOrDefault(employeeId, Collections.emptyList()));
            }
            resultList.add(temp);
        }
        return resultList;
    }
}
