package com.engine.salary.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import com.api.formmode.mybatis.util.SqlProxyHandle;
import com.engine.common.util.ServiceUtil;
import com.engine.core.impl.Service;
import com.engine.salary.config.SalaryElogConfig;
import com.engine.salary.constant.SalaryDefaultTenantConstant;
import com.engine.hrmelog.entity.dto.LoggerContext;
import com.engine.salary.entity.datacollection.DataCollectionEmployee;
import com.engine.salary.entity.salaryacct.bo.SalaryAcctEmployeeBO;
import com.engine.salary.entity.salaryacct.dto.SalaryAcctEmployeeCountDTO;
import com.engine.salary.entity.salaryacct.param.*;
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.salarysob.dto.SalarySobCycleDTO;
import com.engine.salary.entity.salarysob.po.SalarySobPO;
import com.engine.salary.enums.OperateTypeEnum;
import com.engine.salary.enums.salaryaccounting.SalaryAcctRecordStatusEnum;
import com.engine.salary.exception.SalaryRunTimeException;
import com.engine.salary.mapper.salaryacct.SalaryAcctEmployeeMapper;
import com.engine.salary.mapper.sys.SalarySysConfMapper;
import com.engine.salary.report.entity.param.SalaryStatisticsReportDataQueryParam;
import com.engine.salary.service.*;
import com.engine.salary.sys.entity.vo.OrderRuleVO;
import com.engine.salary.sys.service.SalarySysConfService;
import com.engine.salary.sys.service.impl.SalarySysConfServiceImpl;
import com.engine.salary.util.SalaryDateUtil;
import com.engine.salary.util.SalaryEntityUtil;
import com.engine.salary.util.SalaryI18nUtil;
import com.engine.salary.util.db.MapperProxyFactory;
import com.engine.salary.util.page.PageInfo;
import com.engine.salary.util.page.SalaryPageUtil;
import com.engine.salary.util.valid.ValidUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import weaver.hrm.User;

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

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

    private SalaryAcctEmployeeMapper getSalaryAcctEmployeeMapper() {
        return MapperProxyFactory.getProxy(SalaryAcctEmployeeMapper.class);
    }

    private SalaryAcctRecordService getSalaryAcctRecordService(User user) {
        return ServiceUtil.getService(SalaryAcctRecordServiceImpl.class, user);
    }

    private SalaryAcctResultService getSalaryAcctResultService(User user) {
        return ServiceUtil.getService(SalaryAcctResultServiceImpl.class, user);
    }

    private SalaryAcctReportServiceImpl getSalaryAcctReportService(User user) {
        return ServiceUtil.getService(SalaryAcctReportServiceImpl.class, user);
    }

//    private SalaryCheckResultDetailService salaryCheckResultDetailService;

//    private SalaryComparisonResultService salaryComparisonResultService;

    private SalarySobService getSalarySobService(User user) {
        return ServiceUtil.getService(SalarySobServiceImpl.class, user);
    }

    private SalaryEmployeeService getSalaryEmployeeService(User user) {
        return ServiceUtil.getService(SalaryEmployeeServiceImpl.class, user);
    }

    private SalaryArchiveService getSalaryArchiveService(User user) {
        return ServiceUtil.getService(SalaryArchiveServiceImpl.class, user);
    }

    private TaxAgentService getTaxAgentService(User user) {
        return ServiceUtil.getService(TaxAgentServiceImpl.class, user);
    }

    private SalarySysConfMapper getSalarySysConfMapper() {
        return SqlProxyHandle.getProxy(SalarySysConfMapper.class);
    }

    private SalarySysConfService getSalarySysConfService(User user) {
        return ServiceUtil.getService(SalarySysConfServiceImpl.class, user);
    }


    @Override
    public List<SalaryAcctEmployeeCountDTO> countBySalaryAcctRecordId(Collection<Long> salaryAcctRecordIds) {
        if (CollectionUtils.isEmpty(salaryAcctRecordIds)) {
            return Collections.emptyList();
        }
        return getSalaryAcctEmployeeMapper().countGroupBySalaryAcctRecordId(salaryAcctRecordIds);
    }

    @Override
    public SalaryAcctEmployeePO getById(Long id) {
        return getSalaryAcctEmployeeMapper().getById(id);
    }

    @Override
    public List<SalaryAcctEmployeePO> listByIds(Collection<Long> ids) {
        return getSalaryAcctEmployeeMapper().listSome(SalaryAcctEmployeePO.builder().ids(ids).build());
    }

    @Override
    public List<SalaryAcctEmployeePO> listBySalaryAcctRecordId(Long salaryAcctRecordId) {
        return getSalaryAcctEmployeeMapper().listSome(SalaryAcctEmployeePO.builder().salaryAcctRecordId(salaryAcctRecordId).build());
    }

    @Override
    public List<SalaryAcctEmployeePO> listBySalaryAcctRecordIds(Collection<Long> salaryAcctRecordIds) {
        return getSalaryAcctEmployeeMapper().listSome(SalaryAcctEmployeePO.builder().salaryAcctRecordIds(salaryAcctRecordIds).build());
    }

    @Override
    public List<SalaryAcctEmployeePO> listBySalaryAcctRecordIdAndTaxAgentId(Long salaryAcctRecordId, Long taxAgentId) {
        return getSalaryAcctEmployeeMapper().listSome(SalaryAcctEmployeePO.builder().salaryAcctRecordId(salaryAcctRecordId).taxAgentId(taxAgentId).build());
    }

    @Override
    public void addFromReduce(SalaryAcctEmployeeAddParam addParam) {
        ValidUtil.doValidator(addParam);
        // 查询薪资核算记录
        SalaryAcctRecordPO salaryAcctRecordPO = getSalaryAcctRecordService(user).getById(addParam.getSalaryAcctRecordId());
        if (Objects.isNull(salaryAcctRecordPO)) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(98747, "薪资核算记录不存在或已被删除"));
        }
        // 查询环比减少的薪资核算人员
        List<SalaryAcctEmployeePO> salaryAcctEmployeePOS = listByIds(addParam.getIds());
        if (CollectionUtils.isEmpty(salaryAcctEmployeePOS)) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(98830, "薪资核算人员不存在或已被删除"));
        }
        // 添加薪资核算人员
        Date now = new Date();
        List<SalaryAcctEmployeePO> newSalaryAcctEmployeePOS = salaryAcctEmployeePOS.stream().map(salaryAcctEmployeePO -> new SalaryAcctEmployeePO()
                .setSalaryAcctRecordId(salaryAcctRecordPO.getId()).setSalarySobId(salaryAcctRecordPO.getSalarySobId()).setSalaryMonth(salaryAcctRecordPO.getSalaryMonth()).setEmployeeId(salaryAcctEmployeePO.getEmployeeId()).setTaxAgentId(salaryAcctEmployeePO.getTaxAgentId()).setTenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY).setCreateTime(now).setUpdateTime(now).setCreator((long) user.getUID()).setDeleteType(0)).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(newSalaryAcctEmployeePOS)) {
            batchSave(newSalaryAcctEmployeePOS);
        }
    }

    @Override
    public List<SalaryAcctEmployeePO> listBySalaryAcctRecordIdAndIds(Long salaryAcctRecordId, Collection<Long> ids) {
        return getSalaryAcctEmployeeMapper().listSome(SalaryAcctEmployeePO.builder().salaryAcctRecordId(salaryAcctRecordId).ids(ids).build());
    }

    @Override
    public List<SalaryAcctEmployeePO> listBySalaryAcctRecordIdAndEmployeeIds(Long salaryAcctRecordId, Collection<Long> employeeIds) {
        if (CollectionUtils.isEmpty(employeeIds)) {
            return Collections.emptyList();
        }
        return getSalaryAcctEmployeeMapper().listSome(SalaryAcctEmployeePO.builder().salaryAcctRecordId(salaryAcctRecordId).employeeIds(employeeIds).build());
    }

    @Override
    public List<SalaryAcctEmployeePO> listBySalaryAcctRecordIdsAndEmployeeIds(Collection<Long> salaryAcctRecordIds, Collection<Long> employeeIds) {
        if (CollectionUtils.isEmpty(salaryAcctRecordIds) || CollectionUtils.isEmpty(employeeIds)) {
            return Collections.emptyList();
        }
        List<List<Long>> partition = Lists.partition((List<Long>) employeeIds, 500);
        List<SalaryAcctEmployeePO> list = new ArrayList<>();
        partition.forEach(l -> {
            list.addAll(getSalaryAcctEmployeeMapper().listSome(SalaryAcctEmployeePO.builder().salaryAcctRecordIds(salaryAcctRecordIds).employeeIds(l).build()));
        });

        return list;
    }

    @Override
    public List<SalaryAcctEmployeePO> listByRecordIdsAndEmpIdAndTaxAgentId(Collection<Long> salaryAcctRecordIds, Long employeeId, Long taxAgentId) {
        if (CollectionUtils.isEmpty(salaryAcctRecordIds)) {
            return Collections.emptyList();
        }
        return getSalaryAcctEmployeeMapper().listSome(SalaryAcctEmployeePO.builder().salaryAcctRecordIds(salaryAcctRecordIds).employeeId(employeeId).taxAgentId(taxAgentId).build());
    }

    @Override
    public PageInfo<SalaryAcctEmployeePO> listPageByParam(SalaryAcctEmployeeQueryParam queryParam) {
        ValidUtil.doValidator(queryParam);

        //排序配置
        OrderRuleVO orderRule = getSalarySysConfService(user).orderRule();
        queryParam.setOrderRule(orderRule);

        // 分页参数
        // 查询薪资核算人员
        List<SalaryAcctEmployeePO> salaryAcctEmployeePOS = getSalaryAcctEmployeeMapper().listPage(queryParam);
        return SalaryPageUtil.buildPage(queryParam.getCurrent(), queryParam.getPageSize(),
                salaryAcctEmployeePOS, SalaryAcctEmployeePO.class);
    }

    @Override
    public List<SalaryAcctEmployeePO> listByParam(SalaryAcctEmployeeQueryParam queryParam) {
        ValidUtil.doValidator(queryParam);
        //排序配置
        OrderRuleVO orderRule = getSalarySysConfService(user).orderRule();
        queryParam.setOrderRule(orderRule);
        return getSalaryAcctEmployeeMapper().list(queryParam);
    }

    @Override
    public PageInfo<SalaryAcctEmployeePO> listPageByResultQueryParam(SalaryAcctResultQueryParam queryParam) {
        ValidUtil.doValidator(queryParam);
        // 薪资核算人员的查询参数
        SalaryAcctEmployeeQueryParam salaryAcctEmployeeQueryParam = new SalaryAcctEmployeeQueryParam();
        BeanUtils.copyProperties(queryParam, salaryAcctEmployeeQueryParam);
        // 查询薪资核算人员（分页）
        // 如果需要筛选是否合并计税
        if (StringUtils.isNotEmpty(queryParam.getConsolidatedTaxation())) {
            return listPageByParam4ConsolidatedTax(salaryAcctEmployeeQueryParam);
        } else {
            return listPageByParam(salaryAcctEmployeeQueryParam);
        }
    }

    @Override
    public List<SalaryAcctEmployeePO> listByResultQueryParam(SalaryAcctResultQueryParam queryParam) {
        // 薪资核算人员的查询参数
        SalaryAcctEmployeeQueryParam salaryAcctEmployeeQueryParam = new SalaryAcctEmployeeQueryParam();
        BeanUtils.copyProperties(queryParam, salaryAcctEmployeeQueryParam);
        // 查询薪资核算人员
        List<SalaryAcctEmployeePO> salaryAcctEmployeePOS;
        // 如果需要筛选是否合并计税
        if (StringUtils.isNotEmpty(queryParam.getConsolidatedTaxation())) {
            salaryAcctEmployeePOS = listByParam4ConsolidatedTax(salaryAcctEmployeeQueryParam);
        } else {
            salaryAcctEmployeePOS = listByParam(salaryAcctEmployeeQueryParam);
        }
        return salaryAcctEmployeePOS;
    }


    @Override
    public PageInfo<SalaryAcctEmployeePO> listPageByParam4Reduce(SalaryAcctEmployeeQueryParam queryParam) {

        // 查询薪资核算人员
        List<SalaryAcctEmployeePO> salaryAcctEmployeePOS = listByParam4Reduce(queryParam);
        PageInfo<SalaryAcctEmployeePO> salaryAcctEmployeePOPageInfo = SalaryPageUtil.buildPage(queryParam.getCurrent(), queryParam.getPageSize(), SalaryAcctEmployeePO.class);
        // 分页参数
        salaryAcctEmployeePOPageInfo.setTotal(salaryAcctEmployeePOS.size());
        salaryAcctEmployeePOPageInfo.setList(SalaryPageUtil.subList(queryParam.getCurrent(), queryParam.getPageSize(), salaryAcctEmployeePOS));
        return salaryAcctEmployeePOPageInfo;
    }

    @Override
    public PageInfo<SalaryAcctEmployeePO> listPageByParam4Add(SalaryAcctEmployeeQueryParam queryParam) {
        // 查询薪资核算人员
        List<SalaryAcctEmployeePO> salaryAcctEmployeePOS = listByParam4Add(queryParam);
        PageInfo<SalaryAcctEmployeePO> salaryAcctEmployeePOPageInfo = SalaryPageUtil.buildPage(queryParam.getCurrent(), queryParam.getPageSize(), SalaryAcctEmployeePO.class);
        // 分页参数
        salaryAcctEmployeePOPageInfo.setTotal(salaryAcctEmployeePOS.size());
        salaryAcctEmployeePOPageInfo.setList(SalaryPageUtil.subList(queryParam.getCurrent(), queryParam.getPageSize(), salaryAcctEmployeePOS));
        return salaryAcctEmployeePOPageInfo;
    }


    @Override
    public List<SalaryAcctEmployeePO> listByParam4Reduce(SalaryAcctEmployeeQueryParam queryParam) {
        // 查询上个月的薪资核算记录（同一个薪资账套）
        List<SalaryAcctRecordPO> salaryAcctRecordPOS = getSalaryAcctRecordService(user).listById4LastSalaryMonth(queryParam.getSalaryAcctRecordId());
        if (CollectionUtils.isEmpty(salaryAcctRecordPOS)) {
            return Collections.emptyList();
        }
        Set<Long> lastMonthSalaryAcctRecordIds = SalaryEntityUtil.properties(salaryAcctRecordPOS, SalaryAcctRecordPO::getId);
        // 上个月的核算人员
        List<SalaryAcctEmployeePO> lastMonthSalaryAcctEmployeePOS = listBySalaryAcctRecordIds(lastMonthSalaryAcctRecordIds);
        Map<String, SalaryAcctEmployeePO> lastMonthSalaryAcctEmployeePOMap = SalaryEntityUtil.convert2Map(lastMonthSalaryAcctEmployeePOS, salaryAcctEmployeePO -> salaryAcctEmployeePO.getEmployeeId() + "-" + salaryAcctEmployeePO.getTaxAgentId());
        // 本月的核算人员
        List<SalaryAcctEmployeePO> salaryAcctEmployeePOS = listByParam(queryParam);
        Set<String> keySet = SalaryEntityUtil.properties(salaryAcctEmployeePOS, salaryAcctEmployeePO -> salaryAcctEmployeePO.getEmployeeId() + "-" + salaryAcctEmployeePO.getTaxAgentId());
        List<SalaryAcctEmployeePO> resultList = Lists.newArrayList();
        if (CollectionUtils.isNotEmpty(keySet)) {
            lastMonthSalaryAcctEmployeePOMap.forEach((k, v) -> {
                if (!keySet.contains(k)) {
                    resultList.add(v);
                }
            });
        }
        return resultList;
    }

    @Override
    public List<SalaryAcctEmployeePO> listByParam4Add(SalaryAcctEmployeeQueryParam queryParam) {
        // 查询上个月的薪资核算记录（同一个薪资账套）
        List<SalaryAcctRecordPO> salaryAcctRecordPOS = getSalaryAcctRecordService(user).listById4LastSalaryMonth(queryParam.getSalaryAcctRecordId());
        if (CollectionUtils.isEmpty(salaryAcctRecordPOS)) {
            return Collections.emptyList();
        }
        Set<Long> lastMonthSalaryAcctRecordIds = SalaryEntityUtil.properties(salaryAcctRecordPOS, SalaryAcctRecordPO::getId);
        // 上个月的核算人员
        List<SalaryAcctEmployeePO> lastMonthSalaryAcctEmployeePOS = listBySalaryAcctRecordIds(lastMonthSalaryAcctRecordIds);
        Map<String, SalaryAcctEmployeePO> lastMonthSalaryAcctEmployeePOMap = SalaryEntityUtil.convert2Map(lastMonthSalaryAcctEmployeePOS, salaryAcctEmployeePO -> salaryAcctEmployeePO.getEmployeeId() + "-" + salaryAcctEmployeePO.getTaxAgentId());
        // 本月的核算人员
        List<SalaryAcctEmployeePO> salaryAcctEmployeePOS = listByParam(queryParam);
//        Set<String> keySet = SalaryEntityUtil.properties(salaryAcctEmployeePOS, salaryAcctEmployeePO -> salaryAcctEmployeePO.getEmployeeId() + "-" + salaryAcctEmployeePO.getTaxAgentId());
        Map<String, SalaryAcctEmployeePO> thisMonthSalaryAcctEmployeePOMap = SalaryEntityUtil.convert2Map(salaryAcctEmployeePOS, salaryAcctEmployeePO -> salaryAcctEmployeePO.getEmployeeId() + "-" + salaryAcctEmployeePO.getTaxAgentId());
        List<SalaryAcctEmployeePO> resultList = Lists.newArrayList();
        thisMonthSalaryAcctEmployeePOMap.forEach((k, v) -> {
            if (!lastMonthSalaryAcctEmployeePOMap.containsKey(k)) {
                resultList.add(v);
            }
        });
        return resultList;
    }


    @Override
    public PageInfo<SalaryAcctEmployeePO> listPageByParam4ConsolidatedTax(SalaryAcctEmployeeQueryParam queryParam) {
        //排序配置
        OrderRuleVO orderRule = getSalarySysConfService(user).orderRule();
        queryParam.setOrderRule(orderRule);
        // 查询合并计税的其他薪资核算记录
        List<SalaryAcctRecordPO> otherSalaryAcctRecordPOS = getSalaryAcctRecordService(user).listById4OtherConsolidatedTax(queryParam.getSalaryAcctRecordId());
        if (CollectionUtils.isEmpty(otherSalaryAcctRecordPOS)) {
            return new PageInfo<>();
        }
        // 查询合并计税的薪资核算人员
        Set<Long> otherSalaryAcctRecordIds = SalaryEntityUtil.properties(otherSalaryAcctRecordPOS, SalaryAcctRecordPO::getId);
        // 分页参数
        List<SalaryAcctEmployeePO> salaryAcctEmployeePOS = new ArrayList<>();
        if (CollUtil.isNotEmpty(queryParam.getIds())) {
            List<SalaryAcctEmployeePO> list = new ArrayList<>();
            List<List<Long>> partition = Lists.partition(queryParam.getIds(), 500);
            partition.forEach(ids -> {
                queryParam.setIds(ids);
                list.addAll(getSalaryAcctEmployeeMapper().list4ConsolidatedTax(otherSalaryAcctRecordIds, queryParam));
            });
            salaryAcctEmployeePOS = list;
        } else {
            salaryAcctEmployeePOS = getSalaryAcctEmployeeMapper().listPage4ConsolidatedTax(otherSalaryAcctRecordIds, queryParam);
        }
        return SalaryPageUtil.buildPage(queryParam.getCurrent(), queryParam.getPageSize(),
                salaryAcctEmployeePOS, SalaryAcctEmployeePO.class);
    }

    @Override
    public List<SalaryAcctEmployeePO> listByParam4ConsolidatedTax(SalaryAcctEmployeeQueryParam queryParam) {
        //排序配置
        OrderRuleVO orderRule = getSalarySysConfService(user).orderRule();
        queryParam.setOrderRule(orderRule);
        // 查询合并计税的其他薪资核算记录
        List<SalaryAcctRecordPO> otherSalaryAcctRecordPOS = getSalaryAcctRecordService(user).listById4OtherConsolidatedTax(queryParam.getSalaryAcctRecordId());
        if (CollectionUtils.isEmpty(otherSalaryAcctRecordPOS)) {
            return Collections.emptyList();
        }
        // 查询合并计税的薪资核算人员
        Set<Long> otherSalaryAcctRecordIds = SalaryEntityUtil.properties(otherSalaryAcctRecordPOS, SalaryAcctRecordPO::getId);

        List<SalaryAcctEmployeePO> list = new ArrayList<>();
        if (CollUtil.isNotEmpty(queryParam.getIds())) {
            List<List<Long>> partition = Lists.partition(queryParam.getIds(), 500);
            partition.forEach(ids -> {
                queryParam.setIds(ids);
                list.addAll(getSalaryAcctEmployeeMapper().list4ConsolidatedTax(otherSalaryAcctRecordIds, queryParam));
            });
            return list;
        }

        return getSalaryAcctEmployeeMapper().list4ConsolidatedTax(otherSalaryAcctRecordIds, queryParam);
    }

    @Override
    public void save(SalaryAcctEmployeeSaveParam saveParam) {
        ValidUtil.doValidator(saveParam);

        // 查询薪资核算记录
        SalaryAcctRecordPO salaryAcctRecordPO = getSalaryAcctRecordService(user).getById(saveParam.getSalaryAcctRecordId());
        if (Objects.isNull(salaryAcctRecordPO)) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(98747, "薪资核算记录不存在或已被删除"));
        }
        // 查询薪资核算人员
        List<SalaryAcctEmployeePO> existSalaryAcctEmployeePOS = listBySalaryAcctRecordIdAndEmployeeIds(saveParam.getSalaryAcctRecordId(), saveParam.getEmployeeIds());
        if (CollectionUtils.isNotEmpty(existSalaryAcctEmployeePOS)) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(101581, "人员已存在，请勿重复添加"));
        }
        // 根据薪资账套查询薪资周期
        SalarySobCycleDTO salarySobCycleDTO = getSalarySobService(user).getSalarySobCycle(salaryAcctRecordPO.getSalarySobId(), SalaryDateUtil.localDate2YearMonth(salaryAcctRecordPO.getSalaryMonth()));
        //获取核算的扣缴义务人
        SalarySobPO salarySobPO = getSalarySobService(user).getById(salaryAcctRecordPO.getSalarySobId());
        if (Objects.isNull(salarySobPO)) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(98769, "薪资账套不存在或已被删除"));
        }
        Long taxAgentId = salarySobPO.getTaxAgentId();

        // 查询薪资档案
        List<SalaryArchiveDataDTO> salaryArchiveDataDTOS = getSalaryArchiveService(user).getSalaryArchiveTaxAgentData(salarySobCycleDTO.getSalaryCycle(), saveParam.getEmployeeIds(), taxAgentId);
        // 转换成薪资核算人员po
        List<SalaryAcctEmployeePO> salaryAcctEmployeePOS = SalaryAcctEmployeeBO.convert2EmployeePO(saveParam.getEmployeeIds(), salaryAcctRecordPO, salaryArchiveDataDTOS, (long) user.getUID());


        //过滤不是扣缴义务人下的人员
        salaryAcctEmployeePOS = salaryAcctEmployeePOS.stream().filter(ps -> Objects.equals(taxAgentId, ps.getTaxAgentId())).collect(Collectors.toList());
        // 保存薪资核算人员
        if (CollectionUtils.isEmpty(salaryAcctEmployeePOS)) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(98769, "个税扣缴义务人下无该人员档案信息或薪资缴纳日期不在薪资周期内"));
        }
        batchSave(salaryAcctEmployeePOS);


        // 记录日志
        String targetName = salarySobPO.getName() + ":" + SalaryDateUtil.localDate2YearMonth(salaryAcctRecordPO.getSalaryMonth());
        LoggerContext loggerContext = new LoggerContext<>();
        loggerContext.setUser(user);
        loggerContext.setTargetId("" + salaryAcctRecordPO.getId());
        loggerContext.setTargetName(targetName);
        loggerContext.setOperateType(OperateTypeEnum.ADD.getValue());
        loggerContext.setOperateTypeName(SalaryI18nUtil.getI18nLabel(0, "添加薪资核算人员"));
        loggerContext.setOperatedesc(SalaryI18nUtil.getI18nLabel(0, "添加薪资核算人员") + ":" + targetName);
        loggerContext.setNewValueList(salaryAcctEmployeePOS);
        SalaryElogConfig.salaryAcctRecordLoggerTemplate.write(loggerContext);
    }

    @Override
    public void batchSave(Collection<SalaryAcctEmployeePO> salaryAcctEmployeePOS) {
        if (CollectionUtils.isEmpty(salaryAcctEmployeePOS)) {
            return;
        }
        List<List<SalaryAcctEmployeePO>> partition = Lists.partition((List) salaryAcctEmployeePOS, 100);
        partition.forEach(getSalaryAcctEmployeeMapper()::batchInsert);
    }

    @Override
    public void deleteByIds(Collection<Long> ids) {
        // 删除薪资核算人员
        getSalaryAcctEmployeeMapper().deleteByIds(ids);
        // 删除薪资核算人员对应的薪资核算结果
        getSalaryAcctResultService(user).deleteBySalaryAcctEmployeeIds(ids);
        // 删除报表
        getSalaryAcctReportService(user).deleteBySalaryAcctEmpIds(ids);

        // 删除薪资核算人员对应的校验异常明细
//        salaryCheckResultDetailService.deleteBySalaryAcctEmployeeIds(ids);
        // 删除薪资核算人员对应的线下对比结果
//        salaryComparisonResultService.deleteBySalaryAcctRecordIds(ids);
    }

    @Override
    public void deleteByParam(SalaryAcctEmployeeDeleteParam deleteParam) {
        ValidUtil.doValidator(deleteParam);
        // 查询薪资核算记录
        SalaryAcctRecordPO salaryAcctRecordPO = getSalaryAcctRecordService(user).getById(deleteParam.getSalaryAcctRecordId());
        if (Objects.isNull(salaryAcctRecordPO)) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(98747, "薪资核算记录不存在或已被删除"));
        }
        // 回算不允许删除薪资核算人员
        if (Objects.equals(salaryAcctRecordPO.getBackCalcStatus(), 1)) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(0, "正常薪资已经发放，薪资回算时，不允许再删除薪资核算人员"));
        }
        // 只有未归档时才能删除薪资核算人员
        if (!Objects.equals(salaryAcctRecordPO.getStatus(), SalaryAcctRecordStatusEnum.NOT_ARCHIVED.getValue())) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(98830, "薪资核算已归档或已申报，不允许再删除薪资核算人员"));
        }
        // 查询薪资核算人员
        List<SalaryAcctEmployeePO> salaryAcctEmployeePOS = listBySalaryAcctRecordIdAndIds(deleteParam.getSalaryAcctRecordId(), deleteParam.getIds());
        if (CollectionUtils.isEmpty(salaryAcctEmployeePOS)) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(98830, "薪资核算人员不存在或已被删除"));
        }
        // 删除薪资核算人员
        Set<Long> ids = SalaryEntityUtil.properties(salaryAcctEmployeePOS, SalaryAcctEmployeePO::getId);
        deleteByIds(ids);

        // 查询薪资账套（记录日志用）
        SalarySobPO salarySobPO = getSalarySobService(user).getById(salaryAcctRecordPO.getSalarySobId());
        if (Objects.isNull(salarySobPO)) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(98769, "薪资账套不存在或已被删除"));
        }
        // 记录日志
        String targetName = salarySobPO.getName() + ":" + SalaryDateUtil.localDate2YearMonth(salaryAcctRecordPO.getSalaryMonth());
        LoggerContext loggerContext = new LoggerContext<>();
        loggerContext.setUser(user);
        loggerContext.setTargetId("" + salaryAcctRecordPO.getId());
        loggerContext.setTargetName(targetName);
        loggerContext.setOperateType(OperateTypeEnum.DELETE.getValue());
        loggerContext.setOperateTypeName(SalaryI18nUtil.getI18nLabel(0, "删除薪资核算人员"));
        loggerContext.setOperatedesc(SalaryI18nUtil.getI18nLabel(0, "删除薪资核算人员") + ":" + targetName);
        loggerContext.setOldValueList(salaryAcctEmployeePOS);
        SalaryElogConfig.salaryAcctRecordLoggerTemplate.write(loggerContext);
    }

    @Override
    public void deleteBySalaryAcctRecordIds(Collection<Long> salaryAcctRecordIds) {
        getSalaryAcctEmployeeMapper().deleteBySalaryAcctRecordIds(salaryAcctRecordIds);
    }

    @Override
    public void initBySalaryAcctRecord(SalaryAcctRecordPO salaryAcctRecordPO) {
        // 根据薪资账套查询人员
        List<DataCollectionEmployee> salaryEmployees = getSalaryEmployeeService(user).listBySalarySobId(salaryAcctRecordPO.getSalarySobId());
        if (CollectionUtils.isEmpty(salaryEmployees)) {
            return;
        }
        // 根据薪资账套查询薪资周期
        SalarySobCycleDTO salarySobCycleDTO = getSalarySobService(user).getSalarySobCycle(salaryAcctRecordPO.getSalarySobId(), SalaryDateUtil.localDate2YearMonth(salaryAcctRecordPO.getSalaryMonth()));

//        // 根据薪资账套的"核算人员范围"过滤入职日期大于薪资周期止的人员
//        salaryEmployees = salaryEmployees.stream().filter(salaryEmployee -> StringUtils.isBlank(salaryEmployee.getCompanystartdate()) || (SalaryDateUtil.stringToDate(salaryEmployee.getCompanystartdate()) != null && SalaryDateUtil.stringToDate(salaryEmployee.getCompanystartdate()).compareTo(salarySobCycleDTO.getSalaryCycle().getEndDate()) <= 0)).collect(Collectors.toList());
//
//
//        // 根据薪资账套的"核算人员范围"过滤离职日期小于薪资周期起的人员
//        salaryEmployees = salaryEmployees.stream().filter(salaryEmployee -> StringUtils.isBlank(salaryEmployee.getDismissdate()) || (SalaryDateUtil.stringToDate(salaryEmployee.getCompanystartdate()) != null && SalaryDateUtil.stringToDate(salaryEmployee.getDismissdate()).compareTo(salarySobCycleDTO.getSalaryCycle().getEndDate()) > 0)).collect(Collectors.toList());


        //查询账套对应的扣缴义务人
        SalarySobPO salarySobPO = getSalarySobService(user).getById(salaryAcctRecordPO.getSalarySobId());
        Long taxAgentId = salarySobPO.getTaxAgentId();
//        //过滤扣税扣缴义务人不包含的人员
//        Collection<Long> employeeIdsInTaxAgent = getTaxAgentService(user).listEmployeeIdsInTaxAgent(taxAgentId);
//        salaryEmployees = salaryEmployees.stream().filter(salaryEmployee -> employeeIdsInTaxAgent.contains(salaryEmployee.getEmployeeId())).collect(Collectors.toList());

        // 查询薪资档案，获取人员的个税扣缴义务人
        List<Long> employeeIds = SalaryEntityUtil.properties(salaryEmployees, DataCollectionEmployee::getEmployeeId, Collectors.toList());
        List<SalaryArchiveDataDTO> salaryArchiveDataDTOS = getSalaryArchiveService(user).getSalaryArchiveTaxAgentData(salarySobCycleDTO.getSalaryCycle(), employeeIds, taxAgentId);
        // 转换成薪资核算人员po
        List<SalaryAcctEmployeePO> salaryAcctEmployeePOS = SalaryAcctEmployeeBO.convert2Employee(salaryEmployees, salaryAcctRecordPO, salaryArchiveDataDTOS, (long) user.getUID());

        //过滤掉不属于当前账套扣缴义务人的人员
        salaryAcctEmployeePOS = salaryAcctEmployeePOS.stream().filter(po -> Objects.equals(taxAgentId, po.getTaxAgentId())).collect(Collectors.toList());

        // 保存薪资核算人员
        if (CollectionUtils.isNotEmpty(salaryAcctEmployeePOS)) {
            batchSave(salaryAcctEmployeePOS);
        }
    }

    @Override
    public void refresh(Long salaryAcctRecordId) {
        // 查询薪资核算人员
        List<SalaryAcctEmployeePO> salaryAcctEmployeePOS = listBySalaryAcctRecordId(salaryAcctRecordId);
        if (CollectionUtils.isEmpty(salaryAcctEmployeePOS)) {
            return;
        }
        List<Long> employeeIds = SalaryEntityUtil.properties(salaryAcctEmployeePOS, SalaryAcctEmployeePO::getEmployeeId, Collectors.toList());
        // 查询薪资核算记录
        SalaryAcctRecordPO salaryAcctRecordPO = getSalaryAcctRecordService(user).getById(salaryAcctRecordId);
        if (Objects.isNull(salaryAcctRecordPO)) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(98747, "薪资核算记录不存在或已被删除"));
        }
        //查询账套对应的扣缴义务人
        SalarySobPO salarySobPO = getSalarySobService(user).getById(salaryAcctRecordPO.getSalarySobId());
        //过滤掉不属于当前账套扣缴义务人的人员
        Long taxAgentId = salarySobPO.getTaxAgentId();

        // 查询薪资核算记录所用的帐套的薪资周期
        SalarySobCycleDTO salarySobCycleDTO = getSalarySobService(user).getSalarySobCycle(salaryAcctRecordPO.getSalarySobId(), SalaryDateUtil.localDate2YearMonth(salaryAcctRecordPO.getSalaryMonth()));
        // 查询薪资档案，获取人员的个税扣缴义务人
        List<SalaryArchiveDataDTO> salaryArchiveDataDTOS = getSalaryArchiveService(user).getSalaryArchiveTaxAgentData(salarySobCycleDTO.getSalaryCycle(), employeeIds, taxAgentId);
        // 转换成薪资核算人员po
        List<SalaryAcctEmployeePO> newSalaryAcctEmployeePOS = SalaryAcctEmployeeBO.convert2EmployeePO(employeeIds, salaryAcctRecordPO, salaryArchiveDataDTOS, (long) user.getUID());
        newSalaryAcctEmployeePOS = newSalaryAcctEmployeePOS.stream().filter(po -> Objects.equals(taxAgentId, po.getTaxAgentId())).collect(Collectors.toList());
        // 删除以前的薪资核算人员
        getSalaryAcctEmployeeMapper().deleteBySalaryAcctRecordIds(Collections.singleton(salaryAcctRecordId));
        // 插入新的薪资核算人员
        if (CollectionUtils.isNotEmpty(newSalaryAcctEmployeePOS)) {
            batchSave(newSalaryAcctEmployeePOS);
        }
    }


    @Override
    public List<SalaryAcctEmployeePO> listBySalaryStatisticsReportParam(SalaryStatisticsReportDataQueryParam param) {
        SalaryAcctEmployeePO lambdaQueryChainWrapper = SalaryAcctEmployeePO.builder().build();

        // 个税扣缴义务人
//        Collection<TaxAgentPO> taxAgentList = getTaxAgentService(user).listAllTaxAgents((long) user.getUID());
//        if (CollectionUtils.isNotEmpty(taxAgentList)) {
//            List<Long> taxAgentIds = taxAgentList.stream().map(TaxAgentPO::getId).collect(Collectors.toList());
//            // 有查询参数就取交集
//            if (CollectionUtils.isNotEmpty(param.getTaxAgent())) {
//                List<Long> finalTaxAgentIds = taxAgentIds;
//                taxAgentIds = param.getTaxAgent().stream().filter(finalTaxAgentIds::contains).collect(Collectors.toList());
//                lambdaQueryChainWrapper.setTaxAgentIds(CollectionUtils.isEmpty(taxAgentIds) ? Collections.singletonList(0L) : taxAgentIds);
//            } else {
//                lambdaQueryChainWrapper.setTaxAgentIds(taxAgentIds);
//            }
//        } else {
//            lambdaQueryChainWrapper.setTaxAgentIds(Collections.singletonList(0L));
//        }
        if (CollectionUtils.isNotEmpty(param.getTaxAgent())) {
            lambdaQueryChainWrapper.setTaxAgentIds(param.getTaxAgent());
        }

        if (CollectionUtils.isNotEmpty(param.getSalarySob())) {
            lambdaQueryChainWrapper.setSalarySobIds(param.getSalarySob());
        }

        // 薪资所属月
        Date startYearMonth = SalaryDateUtil.dateStrToLocalYearMonth(param.getSalaryStartMonth());
        Date endYearMonth = SalaryDateUtil.dateStrToLocalYearMonth(param.getSalaryEndMonth());
        if (Objects.nonNull(startYearMonth) && Objects.nonNull(endYearMonth)) {
            Set<Date> yearMonths = Sets.newHashSet();
            while (!startYearMonth.after(endYearMonth)) {
                yearMonths.add(startYearMonth);
                startYearMonth = DateUtil.offsetMonth(startYearMonth, 1);
            }
            lambdaQueryChainWrapper.setSalaryMonths(yearMonths);
        }

        // 收入所得项目
//        if (CollectionUtils.isNotEmpty(param.getIncomeCategory())) {
//            lambdaQueryChainWrapper.in(SalaryAcctEmployeePO::getIncomeCategory, param.getIncomeCategory().stream().map(Object::toString).collect(Collectors.toList()));
//        }

        //排除未归档数据
        List<SalaryAcctRecordPO> salaryAcctRecordPOS = getSalaryAcctRecordService(user).listAll();
        List<Long> salaryAcctRecordIds = salaryAcctRecordPOS.stream()
                .filter(po -> !Objects.equals(po.getStatus(), SalaryAcctRecordStatusEnum.NOT_ARCHIVED.getValue()))
                .map(SalaryAcctRecordPO::getId)
                .collect(Collectors.toList());

        List<SalaryAcctEmployeePO> list = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(salaryAcctRecordIds)) {
            //分片查询
            List<List<Long>> partition = Lists.partition(salaryAcctRecordIds, 500);
            List<SalaryAcctEmployeePO> empList = new ArrayList<>();
            partition.forEach(part -> {
                lambdaQueryChainWrapper.setSalaryAcctRecordIds(salaryAcctRecordIds);
                empList.addAll(getSalaryAcctEmployeeMapper().listSome(lambdaQueryChainWrapper));
            });
            list = empList;
        }

        if (CollectionUtils.isEmpty(list)) {
            return Lists.newArrayList();
        }
        List<Long> employeeIds = list.stream().map(SalaryAcctEmployeePO::getEmployeeId).collect(Collectors.toList());


        List<DataCollectionEmployee> employeeList = getSalaryEmployeeService(user).listByIds(employeeIds);
        // 获取分部信息
        List<Long> subCompanyIds = param.getSubCompany();
        if (CollectionUtils.isNotEmpty(subCompanyIds)) {
//            SubCompanyComInfo subCompanyComInfo = new SubCompanyComInfo();
//            List<String> allSubcompanyIds = new ArrayList<>();
//            for (Long subCompanyId : subCompanyIds) {
//                String organizationIds = Util.null2String(subCompanyId);
//                String allChildSubcompanyId = subCompanyComInfo.getAllChildSubcompanyId(subCompanyId.toString(), organizationIds);
//                allSubcompanyIds.addAll(Arrays.asList(allChildSubcompanyId.split(",")));
//            }
            employeeList = employeeList.stream().filter(emp -> subCompanyIds.contains(emp.getSubcompanyid())).collect(Collectors.toList());
        }

        // 部门过滤
        List<Long> depart = param.getDepart();
        if (CollectionUtils.isNotEmpty(depart)) {
//            List<String> allDepartIds = new ArrayList<>();
//            for (Long subDepartId : depart) {
//                String ids = Util.null2String(subDepartId);
//                try {
//                    String allDepartId = DepartmentComInfo.getAllChildDepartId(subDepartId.toString(), ids);
//                    allDepartIds.addAll(Arrays.asList(allDepartId.toString().split(",")));
//                } catch (Exception e) {
//                    log.error("获取子部门失败", e);
//                }
//            }
            employeeList = employeeList.stream().filter(emp -> depart.contains(emp.getDepartmentId())).collect(Collectors.toList());
        }
        // 职级过滤
//        if (CollectionUtils.isNotEmpty(param.getGrade())) {
//            Set<Long> employeeIdsByGradeFilter = new HashSet<>();
//            simpleEmployeeList.forEach(simpleEmployee -> {
//                if (simpleEmployee.getGrade() != null && param.getGrade().contains(simpleEmployee.getGrade().getId())) {
//                    employeeIdsByGradeFilter.add(simpleEmployee.getEmployeeId());
//                }
//            });
//            if (CollectionUtils.isEmpty(employeeIdsByGradeFilter)) {
//                return Lists.newArrayList();
//            }
//            list = list.stream().filter(po -> employeeIdsByGradeFilter.contains(po.getEmployeeId())).collect(Collectors.toList());
//        }
//        // 岗位过滤
//        if (CollectionUtils.isNotEmpty(param.getPosition())) {
//            Set<Long> employeeIdsByPostionFilter = new HashSet<>();
//            simpleEmployeeList.forEach(simpleEmployee -> {
//                if (simpleEmployee.getPosition() != null && param.getPosition().contains(simpleEmployee.getPosition().getId())) {
//                    employeeIdsByPostionFilter.add(simpleEmployee.getEmployeeId());
//                }
//            });
//            if (CollectionUtils.isEmpty(employeeIdsByPostionFilter)) {
//                return Lists.newArrayList();
//            }
//            list = list.stream().filter(po -> employeeIdsByPostionFilter.contains(po.getEmployeeId())).collect(Collectors.toList());
//        }
       // 人事状态过滤
       if (CollectionUtils.isNotEmpty(param.getStatus())) {
           Set<Long> employeeIdsByStatus = new HashSet<>();
           employeeList.forEach(simpleEmployee -> {
               if (simpleEmployee.getStatus() != null && param.getStatus().contains(simpleEmployee.getStatus())) {
                   employeeIdsByStatus.add(simpleEmployee.getEmployeeId());
               }
           });
           if (CollectionUtils.isEmpty(employeeIdsByStatus)) {
               return Lists.newArrayList();
           }
           list = list.stream().filter(po -> employeeIdsByStatus.contains(po.getEmployeeId())).collect(Collectors.toList());
       }
        // 入职日期
        if (CollectionUtils.isNotEmpty(param.getHiredate())) {
            Set<Long> employeeIdsByHiredate = new HashSet<>();
            employeeList.forEach(simpleEmployee -> {
                Date hiredate = SalaryDateUtil.stringToDate(simpleEmployee.getCompanystartdate());
                if (hiredate != null && !hiredate.before(param.getHiredate().get(0)) && !hiredate.after(param.getHiredate().get(1))) {
                    employeeIdsByHiredate.add(simpleEmployee.getEmployeeId());
                }
            });
            if (CollectionUtils.isEmpty(employeeIdsByHiredate)) {
                return Lists.newArrayList();
            }
            list = list.stream().filter(po -> employeeIdsByHiredate.contains(po.getEmployeeId())).collect(Collectors.toList());
        }
//        // 离职日期 todo
//        if (CollectionUtils.isNotEmpty(param.getLeavedate())) {
//            Set<Long> employeeIdsByLeavedate = new HashSet<>();
//            simpleEmployeeList.forEach(simpleEmployee -> {
//
//                if (simpleEmployee.get() != null && ) {
//                    employeeIdsByLeavedate.add(simpleEmployee.getEmployeeId());
//                }
//            });
//            if (CollectionUtils.isEmpty(employeeIdsByLeavedate)) {
//                return Lists.newArrayList();
//            }
//            list = list.stream().filter(po -> employeeIdsByLeavedate.contains(po.getEmployeeId())).collect(Collectors.toList());
//        }
        // 人员
        if (CollectionUtils.isNotEmpty(param.getEmployee())) {
            list = list.stream().filter(po -> param.getEmployee().contains(po.getEmployeeId())).collect(Collectors.toList());
        }

        Set<Long> empIds = SalaryEntityUtil.properties(employeeList, DataCollectionEmployee::getEmployeeId);
        list = list.stream().filter(po -> empIds.contains(po.getEmployeeId())).collect(Collectors.toList());

        return list;
    }

    @Override
    public List<SalaryAcctEmployeePO> listByTaxAgentAndSalaryMonth(List<Long> taxAgentIds, Set<Date> salaryMonths) {
        return getSalaryAcctEmployeeMapper().listSome(SalaryAcctEmployeePO.builder().taxAgentIds(taxAgentIds).salaryMonths(salaryMonths).build());
    }

}
