package com.engine.salary.service.impl;

import com.api.browser.bean.SearchConditionGroup;
import com.api.browser.bean.SearchConditionItem;
import com.api.browser.util.ConditionFactory;
import com.api.browser.util.ConditionType;
import com.api.formmode.mybatis.util.SqlProxyHandle;
import com.engine.common.util.ServiceUtil;
import com.engine.core.impl.Service;
import com.engine.hrmelog.entity.dto.LoggerContext;
import com.engine.salary.biz.AddUpSituationBiz;
import com.engine.salary.config.SalaryElogConfig;
import com.engine.salary.encrypt.EncryptUtil;
import com.engine.salary.entity.datacollection.AddUpSituation;
import com.engine.salary.entity.datacollection.DataCollectionEmployee;
import com.engine.salary.entity.datacollection.dto.AddUpSituationDTO;
import com.engine.salary.entity.datacollection.dto.AddUpSituationRecordDTO;
import com.engine.salary.entity.datacollection.param.AddUpSituationDeleteParam;
import com.engine.salary.entity.datacollection.param.AddUpSituationImportParam;
import com.engine.salary.entity.datacollection.param.AddUpSituationParam;
import com.engine.salary.entity.datacollection.param.AddUpSituationQueryParam;
import com.engine.salary.entity.salaryacct.po.SalaryAcctEmployeePO;
import com.engine.salary.entity.taxagent.dto.TaxAgentManageRangeEmployeeDTO;
import com.engine.salary.entity.taxagent.po.TaxAgentPO;
import com.engine.salary.enums.OperateTypeEnum;
import com.engine.salary.enums.UserStatusEnum;
import com.engine.salary.exception.SalaryRunTimeException;
import com.engine.salary.mapper.datacollection.AddUpSituationMapper;
import com.engine.salary.mapper.sys.SalarySysConfMapper;
import com.engine.salary.service.AddUpDeductionService;
import com.engine.salary.service.AddUpSituationService;
import com.engine.salary.service.SalaryEmployeeService;
import com.engine.salary.service.TaxAgentService;
import com.engine.salary.sys.entity.po.SalarySysConfPO;
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.excel.ExcelComment;
import com.engine.salary.util.excel.ExcelParseHelper;
import com.engine.salary.util.excel.ExcelSupport;
import com.engine.salary.util.excel.ExcelUtil;
import com.engine.salary.util.page.PageInfo;
import com.engine.salary.util.page.SalaryPageUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.util.IOUtils;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import weaver.file.ImageFileManager;
import weaver.general.Util;
import weaver.hrm.User;

import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

import static com.engine.salary.constant.SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY;
import static com.engine.salary.util.excel.ExcelSupport.EXCEL_TYPE_XLSX;

public class AddUpSituationServiceImpl extends Service implements AddUpSituationService {
    private EncryptUtil encryptUtil = new EncryptUtil();

    private AddUpSituationMapper getAddUpSituationMapper() {
        return MapperProxyFactory.getProxy(AddUpSituationMapper.class);
    }

    private AddUpDeductionService getAddUpDeductionService(User user) {
        return ServiceUtil.getService(AddUpDeductionServiceImpl.class, user);
    }

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

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

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

    AddUpSituationBiz biz = new AddUpSituationBiz();

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

    @Override
    public Map<String, Object> getSearchCondition() {
        Map<String, Object> apidatas = new HashMap<String, Object>();
        ConditionFactory conditionFactory = new ConditionFactory(user);

        //条件组
        List<SearchConditionGroup> addGroups = new ArrayList<SearchConditionGroup>();

        List<SearchConditionItem> conditionItems = new ArrayList<SearchConditionItem>();

        //文本输入框
        SearchConditionItem username = conditionFactory.createCondition(ConditionType.INPUT, 25034, "username");
        username.setInputType("input");
        username.setColSpan(2);//定义一行显示条件数，默认值为2,当值为1时标识该条件单独占一行
        username.setFieldcol(16);    //条件输入框所占宽度，默认值18
        username.setLabelcol(8);
        username.setViewAttr(2);  //	 编辑权限  1：只读，2：可编辑， 3：必填   默认2
        username.setLabel("姓名"); //设置文本值  这个将覆盖多语言标签的值
        conditionItems.add(username);


        SearchConditionItem departmentName = conditionFactory.createCondition(ConditionType.BROWSER, 502227, "departmentIds", "57");
        departmentName.setInputType("browser");
        departmentName.setColSpan(2);
        departmentName.setFieldcol(16);
        departmentName.setLabelcol(8);
        departmentName.setViewAttr(2);
        departmentName.setIsQuickSearch(false);
        departmentName.setLabel("部门");
        conditionItems.add(departmentName);


        SearchConditionItem jobNum = conditionFactory.createCondition(ConditionType.INPUT, 25034, "jobNum");
        jobNum.setInputType("input");
        jobNum.setColSpan(2);
        jobNum.setFieldcol(16);
        jobNum.setLabelcol(8);
        jobNum.setViewAttr(2);
        jobNum.setLabel("工号");
        conditionItems.add(jobNum);


//        SearchConditionItem idNo = conditionFactory.createCondition(ConditionType.INPUT, 25034, "idNo");
//        idNo.setInputType("input");
//        idNo.setColSpan(2);
//        idNo.setFieldcol(16);
//        idNo.setLabelcol(8);
//        idNo.setViewAttr(2);
//        idNo.setLabel("证件号码");
//        conditionItems.add(idNo);
//
//        //日期范围选项
//        List<SearchConditionOption> dateOptions = new ArrayList<SearchConditionOption>();
//        dateOptions.add(new SearchConditionOption("6", SalaryI18nUtil.getI18nLabel(32530, user.getLanguage()), true));//指定日期范围(必须为6)
//        SearchConditionItem hiredate = conditionFactory.createCondition(ConditionType.RANGEPICKER, 18648, new String[]{"hiredate", "hiredate"});
//        hiredate.setInputType("rangepicker");
//        hiredate.setFormat("yyyy-MM-dd");
//        hiredate.setFieldcol(16);
//        hiredate.setLabelcol(8);
//        hiredate.setViewAttr(2);
//        hiredate.setLabel("入职日期");
//        hiredate.setOptions(dateOptions);
//        conditionItems.add(hiredate);
//
//
//        SearchConditionItem mobile = conditionFactory.createCondition(ConditionType.INPUT, 25034, "mobile");
//        mobile.setInputType("input");
//        mobile.setColSpan(2);
//        mobile.setFieldcol(16);
//        mobile.setLabelcol(8);
//        mobile.setViewAttr(2);
//        mobile.setLabel("手机号");
//        conditionItems.add(mobile);

        addGroups.add(new SearchConditionGroup("常用条件", true, conditionItems));

        apidatas.put("condition", addGroups);
        return apidatas;
    }


    @Override
    public AddUpSituation getById(Long id) {
        return getAddUpSituationMapper().getById(id);
    }


    @Override
    public PageInfo<AddUpSituationDTO> listPage(AddUpSituationQueryParam queryParam) {

        List<String> taxYearMonth = queryParam.getTaxYearMonth();
        if (CollectionUtils.isNotEmpty(taxYearMonth)) {
            queryParam.setTaxYearMonth(taxYearMonth.stream().map(e -> e + "-01 00:00:00").collect(Collectors.toList()));
            queryParam.setTaxYearMonthDate(taxYearMonth.stream().map(e -> e + "-01 00:00:00").map(SalaryDateUtil::dateStrToLocalTime).collect(Collectors.toList()));
        }
        //排序配置
        OrderRuleVO orderRule = getSalarySysConfService(user).orderRule();
        queryParam.setOrderRule(orderRule);

        long employeeId = user.getUID();

        Boolean needAuth = getTaxAgentService(user).isNeedAuth(employeeId);
        if (needAuth) {
            List<Long> taxAgentIdsAsAdmin = getTaxAgentService(user).listAllTaxAgentsAsAdmin(employeeId).stream().map(TaxAgentPO::getId).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(taxAgentIdsAsAdmin)) {
                return new PageInfo<>(AddUpSituationDTO.class);
            }
            queryParam.setTaxAgentIds(taxAgentIdsAsAdmin);
        }
        List<AddUpSituationDTO> list = getAddUpSituationMapper().list(queryParam);
        PageInfo<AddUpSituationDTO> page = SalaryPageUtil.buildPage(queryParam.getCurrent(), queryParam.getPageSize(), list, AddUpSituationDTO.class);
        encryptUtil.decryptList(page.getList(), AddUpSituationDTO.class);
        return page;

    }

    @Override
    public PageInfo<AddUpSituationRecordDTO> recordListPage(AddUpSituationQueryParam queryParam) {
        long employeeId = user.getUID();

        Boolean needAuth = getTaxAgentService(user).isNeedAuth(employeeId);
        if (needAuth) {
            List<Long> taxAgentIdsAsAdmin = getTaxAgentService(user).listAllTaxAgentsAsAdmin(employeeId).stream().map(TaxAgentPO::getId).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(taxAgentIdsAsAdmin)) {
                return new PageInfo<>(AddUpSituationRecordDTO.class);
            }
            queryParam.setTaxAgentIds(taxAgentIdsAsAdmin);
        }

        List<AddUpSituationRecordDTO> list = getAddUpSituationMapper().recordList(queryParam);

        PageInfo<AddUpSituationRecordDTO> page = SalaryPageUtil.buildPage(queryParam.getCurrent(), queryParam.getPageSize(),
                list, AddUpSituationRecordDTO.class);
        encryptUtil.decryptList(page.getList(), AddUpSituationRecordDTO.class);
        return page;
    }

    @Override
    public List<AddUpSituation> getAddUpSituationList(YearMonth taxYearMonth, List<Long> employeeIds) {
        if (taxYearMonth == null) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(100353, "参数有误：税款所属期必传"));
        }
        AddUpSituationBiz biz = new AddUpSituationBiz();
        return biz.listSome(AddUpSituation.builder().taxYearMonth(SalaryDateUtil.toDateStartOfMonth(taxYearMonth)).employeeIds(employeeIds).build());
    }

    @Override
    public boolean deleteAddUpSituationList(Date taxCycle, Long taxAgentId) {
        if (taxCycle == null) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(100353, "参数有误：税款所属期必传"));
        }


        AddUpSituationBiz biz = new AddUpSituationBiz();
        List<AddUpSituation> addUpSituations = biz.listSome(AddUpSituation.builder().taxAgentId(taxAgentId).taxYearMonth(taxCycle).build());
        Set<Long> addUpSituationIds = SalaryEntityUtil.properties(addUpSituations, AddUpSituation::getId);
        if (CollectionUtils.isNotEmpty(addUpSituationIds)) {
            getAddUpSituationMapper().deleteByIds(addUpSituationIds);
        }

        return Boolean.TRUE;
    }


    @Override
    public XSSFWorkbook export(AddUpSituationQueryParam queryParam) {
        // 获取操作按钮资源
        List<List<Object>> rowList = getExcelRowList(queryParam, true);

        // 记录日志
        String name = SalaryI18nUtil.getI18nLabel(0, "导出");
        LoggerContext<AddUpSituation> loggerContext = new LoggerContext<>();
        loggerContext.setTargetName(SalaryI18nUtil.getI18nLabel(0, "往期累计情况"));
        loggerContext.setOperateType(OperateTypeEnum.EXCEL_EXPORT.getValue());
        loggerContext.setOperateTypeName(name);
        loggerContext.setOperatedesc(SalaryI18nUtil.getI18nLabel(0, "往期累计情况") + "-" + name);
        loggerContext.setUser(user);
        SalaryElogConfig.addUpSituationLoggerTemplate.write(loggerContext);

        // 获取excel
        return ExcelUtil.genWorkbookV2(rowList, "累计情况");
    }


    /**
     * 获取excel数据行
     *
     * @return 导出数据行集合
     */
    private List<List<Object>> getExcelRowList(AddUpSituationQueryParam param, boolean hasData) {
        long employeeId = user.getUID();
        // excel标题
        final List<Object> title = Arrays.asList("姓名", "个税扣缴义务人", "部门", "手机号", "工号", "证件号码", "入职日期", "累计收入额", "累计减除费用",
                "累计社保个人合计", "累计公积金个人合计", "累计子女教育", "累计继续教育", "累计住房贷款利息", "累计住房租金", "累计赡养老人",
                "累计大病医疗", "累计企业（职业）年金及其他福利", "累计其他扣除", "累计免税收入", "累计准予扣除的捐赠额", "累计减免税额", "累计已预扣预缴税额", "累计婴幼儿照护", "累计个人养老金");


        List<List<Object>> rowList = new ArrayList<>();
        rowList.add(title);

        if (hasData) {
            //排序配置
            OrderRuleVO orderRule = getSalarySysConfService(user).orderRule();
            param.setOrderRule(orderRule);
            List<AddUpSituationDTO> list = biz.list(param);
            // 开启分权并且不是薪酬模块总管理员
            if (getTaxAgentService(user).isOpenDevolution() && !getTaxAgentService(user).isChief(employeeId)) {
                List<Long> taxAgentIdsAsAdmin = getTaxAgentService(user).listAllTaxAgentsAsAdmin(employeeId).stream().map(TaxAgentPO::getId).collect(Collectors.toList());
                list = list.stream().filter(f ->
                        taxAgentIdsAsAdmin.contains(f.getTaxAgentId())
                ).collect(Collectors.toList());
            }

            final List<List<Object>> dataRowList = Optional.ofNullable(list)
                    .map(List::stream)
                    .map(operatorStream -> operatorStream.map(dto -> {
                        List<Object> cellList = new ArrayList<>();
                        cellList.add(Util.null2String(dto.getUsername()));
                        cellList.add(Util.null2String(dto.getTaxAgentName()));
                        cellList.add(Util.null2String(dto.getDepartmentName()));
                        cellList.add(Util.null2String(dto.getMobile()));
                        cellList.add(Util.null2String(dto.getJobNum()));
                        cellList.add(Util.null2String(dto.getIdNo()));
                        cellList.add(Util.null2String(dto.getHiredate()));
                        cellList.add(Util.null2String(dto.getAddUpIncome()));
                        cellList.add(Util.null2String(dto.getAddUpSubtraction()));
                        cellList.add(Util.null2String(dto.getAddUpSocialSecurityTotal()));
                        cellList.add(Util.null2String(dto.getAddUpAccumulationFundTotal()));
                        cellList.add(Util.null2String(dto.getAddUpChildEducation()));
                        cellList.add(Util.null2String(dto.getAddUpContinuingEducation()));
                        cellList.add(Util.null2String(dto.getAddUpHousingLoanInterest()));
                        cellList.add(Util.null2String(dto.getAddUpHousingRent()));
                        cellList.add(Util.null2String(dto.getAddUpSupportElderly()));
                        cellList.add(Util.null2String(dto.getAddUpIllnessMedical()));
                        cellList.add(Util.null2String(dto.getAddUpEnterpriseAndOther()));
                        cellList.add(Util.null2String(dto.getAddUpOtherDeduction()));
                        cellList.add(Util.null2String(dto.getAddUpTaxExemptIncome()));
                        cellList.add(Util.null2String(dto.getAddUpAllowedDonation()));
                        cellList.add(Util.null2String(dto.getAddUpTaxSavings()));
                        cellList.add(Util.null2String(dto.getAddUpAdvanceTax()));
                        cellList.add(Util.null2String(dto.getAddUpInfantCare()));
                        cellList.add(Util.null2String(dto.getAddUpPrivatePension()));
                        return cellList;
                    }).collect(Collectors.toList()))
                    .orElse(Collections.emptyList());

            rowList.addAll(dataRowList);
        }
        return rowList;
    }


    /**
     * 导出详情
     *
     * @param param
     * @return
     */
    private List<List<String>> getExcelRowDetailList(AddUpSituationQueryParam param) {
        long employeeId = user.getUID();
        //excel标题
        List<String> title = Arrays.asList("姓名", "税款所属期", "个税扣缴义务人", "部门", "手机号", "工号", "累计收入额", "累计减除费用", "累计社保个人合计",
                "累计公积金个人合计", "累计子女教育", "累计继续教育", "累计住房贷款利息", "累计住房租金", "累计赡养老人", "累计大病医疗", "累计企业（职业）年金及其他福利",
                "累计其他扣除", "累计免税收入", "累计准予扣除的捐赠额", "累计减免税额", "累计已预扣预缴税额", "累计婴幼儿照护", "累计个人养老金");

        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM");
        //查询详细信息
        List<AddUpSituationRecordDTO> list = biz.recordList(param);

        // 开启了分权
        if (getTaxAgentService(user).isOpenDevolution() || !getTaxAgentService(user).isChief(employeeId)) {
            List<Long> taxAgentIdsAsAdmin = getTaxAgentService(user).listAllTaxAgentsAsAdmin(employeeId).stream().map(TaxAgentPO::getId).collect(Collectors.toList());
            list = list.stream().filter(f ->
                    // 作为管理员
                    taxAgentIdsAsAdmin.contains(f.getTaxAgentId())
            ).collect(Collectors.toList());
        }
        final List<List<String>> dataRowList = Optional.ofNullable(list)
                .map(List::stream)
                .map(operatorStream -> operatorStream.map(dto -> {
                    List<String> cellList = new ArrayList<>();
                    cellList.add(Util.null2String(dto.getUsername()));
                    cellList.add(Util.null2String(dto.getTaxYearMonth() == null ? "" : formatter.format(dto.getTaxYearMonth())));
                    cellList.add(Util.null2String(dto.getTaxAgentName()));
                    cellList.add(Util.null2String(dto.getDepartmentName()));
                    cellList.add(Util.null2String(dto.getMobile()));
                    cellList.add(Util.null2String(dto.getJobNum()));
                    cellList.add(Util.null2String(dto.getAddUpIncome()));
                    cellList.add(Util.null2String(dto.getAddUpSubtraction()));
                    cellList.add(Util.null2String(dto.getAddUpSocialSecurityTotal()));
                    cellList.add(Util.null2String(dto.getAddUpAccumulationFundTotal()));
                    cellList.add(Util.null2String(dto.getAddUpChildEducation()));
                    cellList.add(Util.null2String(dto.getAddUpContinuingEducation()));
                    cellList.add(Util.null2String(dto.getAddUpHousingLoanInterest()));
                    cellList.add(Util.null2String(dto.getAddUpHousingRent()));
                    cellList.add(Util.null2String(dto.getAddUpSupportElderly()));
                    cellList.add(Util.null2String(dto.getAddUpIllnessMedical()));
                    cellList.add(Util.null2String(dto.getAddUpEnterpriseAndOther()));
                    cellList.add(Util.null2String(dto.getAddUpOtherDeduction()));
                    cellList.add(Util.null2String(dto.getAddUpTaxExemptIncome()));
                    cellList.add(Util.null2String(dto.getAddUpAllowedDonation()));
                    cellList.add(Util.null2String(dto.getAddUpTaxSavings()));
                    cellList.add(Util.null2String(dto.getAddUpAdvanceTax()));
                    cellList.add(Util.null2String(dto.getAddUpInfantCare()));
                    cellList.add(Util.null2String(dto.getAddUpPrivatePension()));
                    return cellList;
                }).collect(Collectors.toList()))
                .orElse(Collections.emptyList());

        List<List<String>> rowList = new ArrayList<>();
        rowList.add(title);
        rowList.addAll(dataRowList);
        return rowList;
    }


    @Override
    public XSSFWorkbook exportDetail(AddUpSituationQueryParam queryParam) {
        AddUpSituationBiz biz = new AddUpSituationBiz();

        Long id = queryParam.getAccumulatedSituationId();
        if (id == null) {
            throw new SalaryRunTimeException("id不能为空");
        }

        AddUpSituation po = biz.getById(id);
        if (po == null) {
            throw new SalaryRunTimeException(String.format("累计情况不存在" + "[id:%s]", id));
        }

        List<DataCollectionEmployee> employeeList = getSalaryEmployeeService(user).getEmployeeByIds(Collections.singletonList(po.getEmployeeId()));
        if (CollectionUtils.isEmpty(employeeList)) {
            throw new SalaryRunTimeException("员工信息不存在");
        }

        //查询参数
        queryParam.setEmployeeId(po.getEmployeeId());
        //申报月份
        List<String> taxYearMonths = queryParam.getTaxYearMonth();
        if (CollectionUtils.isNotEmpty(taxYearMonths)) {
            queryParam.setTaxYearMonth(taxYearMonths.stream().map(e -> e + "-01 00:00:00").collect(Collectors.toList()));
            queryParam.setTaxYearMonthDate(taxYearMonths.stream().map(e -> e + "-01 00:00:00").map(SalaryDateUtil::dateStrToLocalTime).collect(Collectors.toList()));
        }

        //获取操作按钮资源
        List<List<String>> rowList = getExcelRowDetailList(queryParam);

        //获取excel
        return ExcelUtil.genWorkbook(rowList, "累计情况明细");

    }


    @Override
    public XSSFWorkbook downloadTemplate(AddUpSituationQueryParam queryParam) {
        String sheetName = SalaryI18nUtil.getI18nLabel(101605, "往期累计情况导入模板");
        // 获取操作按钮资源
        List<List<Object>> rowList = getExcelRowList(queryParam, queryParam.isHasData());
        // 4.注释
        List<ExcelComment> excelComments = Lists.newArrayList();
        excelComments.add(new ExcelComment(0, 0, 3, 2, SalaryI18nUtil.getI18nLabel(100344, "必填")));
        excelComments.add(new ExcelComment(1, 0, 4, 2, SalaryI18nUtil.getI18nLabel(100344, "必填")));
        excelComments.add(new ExcelComment(7, 0, 10, 2, SalaryI18nUtil.getI18nLabel(100344, "输入数字")));
        excelComments.add(new ExcelComment(8, 0, 11, 2, SalaryI18nUtil.getI18nLabel(100344, "输入数字")));
        excelComments.add(new ExcelComment(9, 0, 14, 2, SalaryI18nUtil.getI18nLabel(100344, "输入数字")));
        excelComments.add(new ExcelComment(10, 0, 15, 2, SalaryI18nUtil.getI18nLabel(100344, "输入数字")));
        excelComments.add(new ExcelComment(11, 0, 16, 2, SalaryI18nUtil.getI18nLabel(100344, "输入数字")));
        excelComments.add(new ExcelComment(12, 0, 17, 2, SalaryI18nUtil.getI18nLabel(100344, "输入数字")));
        excelComments.add(new ExcelComment(13, 0, 18, 2, SalaryI18nUtil.getI18nLabel(100344, "输入数字")));
        excelComments.add(new ExcelComment(14, 0, 19, 2, SalaryI18nUtil.getI18nLabel(100344, "输入数字")));
        excelComments.add(new ExcelComment(15, 0, 20, 2, SalaryI18nUtil.getI18nLabel(100344, "输入数字")));
        excelComments.add(new ExcelComment(16, 0, 21, 2, SalaryI18nUtil.getI18nLabel(100344, "输入数字")));
        excelComments.add(new ExcelComment(17, 0, 22, 2, SalaryI18nUtil.getI18nLabel(100344, "输入数字")));
        excelComments.add(new ExcelComment(18, 0, 23, 2, SalaryI18nUtil.getI18nLabel(100344, "输入数字")));
        excelComments.add(new ExcelComment(19, 0, 24, 2, SalaryI18nUtil.getI18nLabel(100344, "输入数字")));
        excelComments.add(new ExcelComment(20, 0, 25, 2, SalaryI18nUtil.getI18nLabel(100344, "输入数字")));
        excelComments.add(new ExcelComment(21, 0, 26, 2, SalaryI18nUtil.getI18nLabel(100344, "输入数字")));
        excelComments.add(new ExcelComment(22, 0, 27, 2, SalaryI18nUtil.getI18nLabel(100344, "输入数字")));
        excelComments.add(new ExcelComment(23, 0, 28, 2, SalaryI18nUtil.getI18nLabel(100344, "输入数字")));
        excelComments.add(new ExcelComment(24, 0, 29, 2, SalaryI18nUtil.getI18nLabel(100344, "输入数字")));

        return ExcelUtil.genWorkbookV2(rowList, sheetName, excelComments);
    }

    @Override
    public boolean deleteByTaxYearMonthAndTaxAgentIds(YearMonth taxYearMonth, Collection<Long> taxAgentIds) {
        if (taxYearMonth == null) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(100353, "参数有误：税款所属期必传"));
        }

        if (CollectionUtils.isEmpty(taxAgentIds)) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(100353, "参数有误：扣缴义务人为空"));
        }

        Date date = SalaryDateUtil.localDateToDate(taxYearMonth.atDay(1));

        getAddUpSituationMapper().deleteByTaxYearMonthAndTaxAgentIds(AddUpSituation.builder().taxYearMonth(date).taxAgentIds(taxAgentIds).build());

        return Boolean.TRUE;
    }

    @Override
    public Map<String, Object> preview(AddUpSituationImportParam importParam) {
        Map<String, Object> apidatas = new HashMap<String, Object>();

        //检验参数
        checkImportParam(importParam);

        //excel文件id
        String imageId = Util.null2String(importParam.getImageId());

        InputStream fileInputStream = null;
        try {
            fileInputStream = ImageFileManager.getInputStreamById(Integer.valueOf(imageId));
            Sheet sheet = ExcelSupport.parseFile(fileInputStream, 0, EXCEL_TYPE_XLSX);
            apidatas.put("headers", ExcelSupport.getSheetHeader(sheet, 0));
            apidatas.put("list", ExcelParseHelper.parse2List(sheet, 1, 0));
            return apidatas;
        } finally {
            IOUtils.closeQuietly(fileInputStream);
        }
    }


    @Override
    public Map<String, Object> importAddUpSituation(AddUpSituationImportParam importParam) {
        Boolean openDevolution = getTaxAgentService(user).isOpenDevolution();

        Map<String, Object> apidatas = new HashMap<String, Object>();
        AddUpSituationBiz biz = new AddUpSituationBiz();

        //查询对于人员信息导入筛选的全局配置
        SalarySysConfPO salarySysConfPO = getSalarySysConfMapper().getOneByCode("matchEmployeeMode");
        String confValue = (salarySysConfPO != null && salarySysConfPO.getConfValue() != null && !"".equals(salarySysConfPO.getConfValue())) ? salarySysConfPO.getConfValue() : "0";

        //检验参数
        checkImportParam(importParam);

        //excel文件id
        String imageId = Util.null2String(importParam.getImageId());
        //税款所属期
        String taxYearMonthStr = Util.null2String(importParam.getTaxYearMonth());

        Long currentEmployeeId = (long) user.getUID();

        // 获取所有个税扣缴义务人
        Collection<TaxAgentManageRangeEmployeeDTO> taxAgentList = getTaxAgentService(user).listTaxAgentAndEmployeeTree(currentEmployeeId);
        // 获取租户下所有的人员
        List<DataCollectionEmployee> employees = getSalaryEmployeeService(user).listEmployee();
        // 已经核算过的不可操作
        // 获取已经核算的数据(获取税款所属期下一个月的数据)
        YearMonth nextTaxYearMonth = SalaryDateUtil.String2YearMonth(taxYearMonthStr);
        String nextTaxYearMonthStr = taxYearMonthStr;
        if (!Objects.equals(nextTaxYearMonth.getMonthValue(), 12)) {
            nextTaxYearMonth = nextTaxYearMonth.plusMonths(1);
            nextTaxYearMonthStr = nextTaxYearMonth.format(SalaryDateUtil.MONTH_FORMATTER);
        }
        List<SalaryAcctEmployeePO> salaryAcctEmployees = getAddUpDeductionService(user).getAccountedEmployeeDataByTaxYearMonth(nextTaxYearMonthStr);

        //税款所属期
        Date taxYearMonth = SalaryDateUtil.localDateToDate(LocalDate.parse(taxYearMonthStr + "-01", SalaryDateUtil.DATE_FORMATTER));
        // 查询已有数据
        List<AddUpSituation> list = getAddUpSituationMapper().listSome(AddUpSituation.builder().taxYearMonth(taxYearMonth).build());


        InputStream fileInputStream = null;
        try {
            fileInputStream = ImageFileManager.getInputStreamById(Integer.parseInt(imageId));

            List<AddUpSituationDTO> excelDates = ExcelParseHelper.parse2Map(fileInputStream, AddUpSituationDTO.class, 0, 1, 25, "template.xlsx");

            int total = excelDates.size();
            int index = 0;
            int successCount = 0;
            int errorCount = 0;


            Date now = new Date();


            // 错误excel内容
            List<Map> errorData = new ArrayList<>();
            //合规数据
            List<AddUpSituation> eligibleData = new ArrayList<>();

            List<TaxAgentManageRangeEmployeeDTO.TaxAgentEmployee> taxAgentEmployees = Lists.newArrayList();
            for (int i = 0; i < excelDates.size(); i++) {
                //excel中的数据
                AddUpSituationDTO dto = excelDates.get(i);
                //待插入数据库对象
                AddUpSituation po = AddUpSituation.builder().tenantKey(DEFAULT_TENANT_KEY)
                        .createTime(now)
                        .updateTime(now)
                        .creator((long) user.getUID())
                        .year(Integer.valueOf(taxYearMonthStr.split("-")[0]))
                        .taxYearMonth(taxYearMonth)
                        .build();


                //异常点数量
                int errorSum = 0;

                //行号
                String rowIndex = String.format("第%s行", i + 2);

                //相同的姓名
                String userName = dto.getUsername();
                String deparmentName = dto.getDepartmentName();
                String mobile = dto.getMobile();
                String workcode = dto.getJobNum();
                String idNo = dto.getIdNo();

                //筛选导入人员信息可以在人力资源池中匹配到的人员信息
                List<DataCollectionEmployee> employeeSameIds = getSalaryEmployeeService(user).matchImportEmployee(confValue, employees, userName, deparmentName, mobile, workcode, idNo,null);

                //当人员信息导入筛选的全局配置为"0"时，姓名才是必填项
                if (StringUtils.isBlank(userName) && "0".equals(confValue)) {
                    //姓名 不能为空
                    //错误消息对象
                    Map<String, String> errorMessageMap = Maps.newHashMap();
                    errorMessageMap.put("message", rowIndex + "姓名不能为空");
                    errorData.add(errorMessageMap);
                    errorSum += 1;
                } else if (CollectionUtils.isEmpty(employeeSameIds)) {
                    Map<String, String> errorMessageMap = Maps.newHashMap();
                    errorMessageMap.put("message", rowIndex + "员工信息不存在");
                    errorData.add(errorMessageMap);
                    errorSum += 1;
                } else if (employeeSameIds.size() > 1) {
                    //存在离职和在职状态取在职状态
                    employeeSameIds = employeeSameIds.stream()
                            .filter(e -> UserStatusEnum.getNormalStatus().contains(e.getStatus()))
                            .collect(Collectors.toList());
                    if (employeeSameIds.size() != 1) {
                        Map<String, String> errorMessageMap = Maps.newHashMap();
                        errorMessageMap.put("message", rowIndex + "员工信息不存在或者存在多个员工");
                        errorData.add(errorMessageMap);
                        errorSum += 1;
                    } else {
                        Long employeeId = CollectionUtils.isNotEmpty(employeeSameIds) && employeeSameIds.size() == 1 ? employeeSameIds.get(0).getEmployeeId() : null;
                        po.setEmployeeId(employeeId);
                    }
                } else {
                    Long employeeId = CollectionUtils.isNotEmpty(employeeSameIds) && employeeSameIds.size() == 1 ? employeeSameIds.get(0).getEmployeeId() : null;
                    if (employeeId != null && employeeId > 0) {
                        po.setEmployeeId(employeeId);
                    } else {
                        //姓名错误，系统内不存在该姓名
                        Map<String, String> errorMessageMap = Maps.newHashMap();
                        errorMessageMap.put("message", rowIndex + "姓名错误，系统内不存在该姓名");
                        errorData.add(errorMessageMap);
                        errorSum += 1;
                    }
                }


                String taxAgentName = dto.getTaxAgentName();
                if (StringUtils.isBlank(taxAgentName)) {
                    //个税扣缴义务人不能为空
                    Map<String, String> errorMessageMap = Maps.newHashMap();
                    errorMessageMap.put("message", rowIndex + "个税扣缴义务人不能为空");
                    errorData.add(errorMessageMap);
                    errorSum += 1;
                } else {
                    Optional<TaxAgentManageRangeEmployeeDTO> optionalTemp = taxAgentList.stream().filter(m -> m.getTaxAgentName().equals(taxAgentName)).findFirst();
                    if (optionalTemp.isPresent()) {
                        po.setTaxAgentId(optionalTemp.get().getTaxAgentId());
                        taxAgentEmployees = optionalTemp.get().getEmployeeList();
                    } else {
                        //个税扣缴义务人不存在
                        Map<String, String> errorMessageMap = Maps.newHashMap();
                        errorMessageMap.put("message", rowIndex + "个税扣缴义务人不存在或不在权限范围内");
                        errorData.add(errorMessageMap);
                        errorSum += 1;
                    }
                }

                // fixme 分权判断，若员工离职后，不在扣缴义务人范围内，会有异常
//                if (openDevolution) {
//                    Optional<TaxAgentManageRangeEmployeeDTO.TaxAgentEmployee> optionalTaxAgentEmp = taxAgentEmployees.stream().filter(f -> f.getEmployeeId().equals(po.getEmployeeId())).findFirst();
//                    if (!optionalTaxAgentEmp.isPresent()) {
//                        Map<String, String> errorMessageMap = Maps.newHashMap();
//                        errorMessageMap.put("message", rowIndex + "该条数据不在个税扣缴义务人人员范围内，不可导入");
//                        errorData.add(errorMessageMap);
//                        errorSum += 1;
//                    }
//                }

                // 判断是否有核算过
                if (CollectionUtils.isNotEmpty(salaryAcctEmployees) && !Objects.equals(taxYearMonthStr.split("-")[1], "12")) {
                    Optional<SalaryAcctEmployeePO> optionalAcctEmp = salaryAcctEmployees.stream().filter(f -> f.getEmployeeId().equals(po.getEmployeeId()) && f.getTaxAgentId().equals(po.getTaxAgentId())).findFirst();
                    boolean isExist = list.stream().anyMatch(f -> f.getEmployeeId().equals(po.getEmployeeId()) && f.getTaxAgentId().equals(po.getTaxAgentId()));
                    if (optionalAcctEmp.isPresent() && isExist) {
                        Map<String, String> errorMessageMap = Maps.newHashMap();
                        errorMessageMap.put("message", rowIndex + "该年月这条数据已经核算过，不可导入");
                        errorData.add(errorMessageMap);
                        errorSum += 1;
                    }
                }


                //累计收入额
                String addUpIncome = dto.getAddUpIncome();
                po.setAddUpIncome(Util.null2String(addUpIncome));
                //累计减除费用
                String addUpSubtraction = dto.getAddUpSubtraction();
                po.setAddUpSubtraction(addUpSubtraction);
                //累计社保个人合计
                String addUpSocialSecurityTotal = dto.getAddUpSocialSecurityTotal();
                po.setAddUpSocialSecurityTotal(addUpSocialSecurityTotal);
                //累计公积金个人合计
                String addUpAccumulationFundTotal = dto.getAddUpAccumulationFundTotal();
                po.setAddUpAccumulationFundTotal(addUpAccumulationFundTotal);
                //累计子女教育
                String addUpChildEducation = dto.getAddUpChildEducation();
                po.setAddUpChildEducation(Util.null2String(addUpChildEducation));
                //累计继续教育
                String addUpContinuingEducation = dto.getAddUpContinuingEducation();
                po.setAddUpContinuingEducation(Util.null2String(addUpContinuingEducation));
                //累计住房贷款利息
                String addUpHousingLoanInterest = dto.getAddUpHousingLoanInterest();
                po.setAddUpHousingLoanInterest(Util.null2String(addUpHousingLoanInterest));
                //累计住房租金
                String addUpHousingRent = dto.getAddUpHousingRent();
                po.setAddUpHousingRent(Util.null2String(addUpHousingRent));
                //累计赡养老人
                String addUpSupportElderly = dto.getAddUpSupportElderly();
                po.setAddUpSupportElderly(Util.null2String(addUpSupportElderly));
                //累计企业（职业）年金及其他福利
                String addUpEnterpriseAndOther = dto.getAddUpEnterpriseAndOther();
                po.setAddUpEnterpriseAndOther(addUpEnterpriseAndOther);
                //累计其他扣除
                String addUpOtherDeduction = dto.getAddUpOtherDeduction();
                po.setAddUpOtherDeduction(addUpOtherDeduction);
                //累计免税收入
                String addUpTaxExemptIncome = dto.getAddUpTaxExemptIncome();
                po.setAddUpTaxExemptIncome(addUpTaxExemptIncome);
                //累计准予扣除的捐赠额
                String addUpAllowedDonation = dto.getAddUpAllowedDonation();
                po.setAddUpAllowedDonation(addUpAllowedDonation);
                //累计已预扣预缴税额
                String addUpAdvanceTax = dto.getAddUpAdvanceTax();
                po.setAddUpAdvanceTax(addUpAdvanceTax);

                po.setAddUpIllnessMedical(dto.getAddUpIllnessMedical());
                po.setAddUpTaxSavings(dto.getAddUpTaxSavings());
                po.setAddUpInfantCare(dto.getAddUpInfantCare());
                po.setAddUpPrivatePension(dto.getAddUpPrivatePension());

                if (errorSum == 0) {
                    successCount += 1;
                    // 合格数据
                    eligibleData.add(po);
                } else {
                    errorCount += 1;
                    // 添加错误数据
                }
            }

            //入库
            handleImportData(eligibleData);

            apidatas.put("successCount", successCount);
            apidatas.put("errorCount", errorCount);
            apidatas.put("errorData", errorData);

        } finally {
            IOUtils.closeQuietly(fileInputStream);
        }
        return apidatas;
    }

    public void handleImportData(List<AddUpSituation> pos) {
        if (CollectionUtils.isEmpty(pos)) {
            return;
        }
        AddUpSituationBiz biz = new AddUpSituationBiz();
        AddUpSituation po = pos.get(0);
        // 多条相同人的则以第一条为准，如果逆序排列（用于重复的则以最后一条为准）Collections.reverse(pos);
        // 去重（通过记录的唯一条件(申报月份，人员id，个税扣缴义务人id)拼接）
        List<AddUpSituation> finalPos = pos.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(f -> f.getEmployeeId() + "-" + f.getTaxAgentId()))), ArrayList::new));
        // 查询已有数据
        List<AddUpSituation> list = biz.listSome(AddUpSituation.builder().taxYearMonth(po.getTaxYearMonth()).build());
        // 待修改的 本地已存在则更新【交集】
        List<AddUpSituation> updateList = list.stream().map(m -> {
            Optional<AddUpSituation> optional = finalPos.stream().filter(p -> (p.getEmployeeId() + "-" + p.getTaxAgentId()).equals(m.getEmployeeId() + "-" + m.getTaxAgentId())).findFirst();
            AddUpSituation temp = null;
            if (optional.isPresent()) {
                temp = optional.get();
                // 换成本地库的id
                temp.setId(m.getId());
            }
            return temp;
        }).filter(Objects::nonNull).collect(Collectors.toList());
        // 待新增的 导入比本地多，则新增【差集(导入 - local)】
        List<AddUpSituation> saveList = finalPos.stream().map(m -> {
            Optional<AddUpSituation> optional = list.stream().filter(p -> (p.getEmployeeId() + "-" + p.getTaxAgentId()).equals(m.getEmployeeId() + "-" + m.getTaxAgentId())).findFirst();
            AddUpSituation temp = null;
            if (!optional.isPresent()) {
                temp = m;
            }
            return temp;
        }).filter(Objects::nonNull).collect(Collectors.toList());

        // 修改
        if (CollectionUtils.isNotEmpty(updateList)) {
            biz.batchUpdate(updateList);
        }
        // 保存
        if (CollectionUtils.isNotEmpty(saveList)) {
            batchSave(saveList);
        }

        // 记录操作日志
        // 根据月份、人员id查出保存的数据
        List<Long> empIds = saveList.stream().map(AddUpSituation::getEmployeeId).collect(Collectors.toList());
        List<AddUpSituation> insertList = biz.listSome(AddUpSituation.builder().taxYearMonth(po.getTaxYearMonth()).employeeIds(empIds).build());
        Map<String, AddUpSituation> insertMap = SalaryEntityUtil.convert2Map(insertList, p -> p.getTaxAgentId() + "-" + SalaryDateUtil.getFormatYearMonth(p.getTaxYearMonth()) + "-" + p.getEmployeeId());
        saveList.forEach(save -> {
            AddUpSituation addUpSituation = insertMap.get(save.getTaxAgentId() + "-" + SalaryDateUtil.getFormatYearMonth(save.getTaxYearMonth()) + "-" + save.getEmployeeId());
            if (addUpSituation != null) {
                updateList.add(addUpSituation);
            }
        });

        if (CollectionUtils.isNotEmpty(updateList)) {
            LoggerContext loggerContext = new LoggerContext();
            loggerContext.setUser(user);
            if (updateList.size() == 1) {
                loggerContext.setTargetId(updateList.get(0).getId().toString());
            }
            loggerContext.setTargetName(SalaryI18nUtil.getI18nLabel(0, "往期累计情况"));
            loggerContext.setOperateType(OperateTypeEnum.ADD.getValue());
            loggerContext.setOperateTypeName(SalaryI18nUtil.getI18nLabel(0, "导入"));
            loggerContext.setOperatedesc(SalaryI18nUtil.getI18nLabel(0, "导入往期累计情况"));
            loggerContext.setNewValueList(updateList);
            SalaryElogConfig.addUpSituationLoggerTemplate.write(loggerContext);
        }
    }


    private void checkImportParam(AddUpSituationImportParam importParam) {


        //excel文件id
        String imageId = Util.null2String(importParam.getImageId());
        //税款所属期
        String declareMonthStr = Util.null2String(importParam.getTaxYearMonth());


        if (StringUtils.isBlank(imageId)) {
            throw new SalaryRunTimeException("文件不存在");
        }
        if (StringUtils.isBlank(declareMonthStr)) {
            throw new SalaryRunTimeException("税款所属期为空");
        }
    }

    /**
     * @return void
     * @description 编辑数据
     * @author Harryxzy
     * @date 2022/10/27 21:32
     */
    @Override
    public void editAddUpSituation(AddUpSituationParam addUpSituationParam) {
        Long currentEmployeeId = (long) user.getUID();
        AddUpSituationBiz biz = new AddUpSituationBiz();
        //税款所属期
        String taxYearMonthStr = addUpSituationParam.getTaxYearMonth();
        // 获取所有个税扣缴义务人
        Collection<TaxAgentManageRangeEmployeeDTO> taxAgentList = getTaxAgentService(user).listTaxAgentAndEmployeeTree(currentEmployeeId);
        AddUpSituation byId = biz.getById(addUpSituationParam.getId());
        if (byId == null) {
            throw new SalaryRunTimeException("该数据不存在！");
        }
        Long taxAgentId = byId.getTaxAgentId();
        boolean canEdit = taxAgentList.stream().anyMatch(t -> Objects.equals(t.getTaxAgentId(), taxAgentId));
        if (!canEdit) {
            //没有编辑权限
            throw new SalaryRunTimeException("该个税扣缴义务人无权限编辑此数据！");
        }
        // 已经核算过的不可操作
        // 获取已经核算的数据(获取税款所属期下一个月的数据)
        YearMonth nextTaxYearMonth = SalaryDateUtil.String2YearMonth(taxYearMonthStr);
        String nextTaxYearMonthStr = taxYearMonthStr;
        if (!Objects.equals(nextTaxYearMonth.getMonthValue(), 12)) {
            nextTaxYearMonth = nextTaxYearMonth.plusMonths(1);
            nextTaxYearMonthStr = nextTaxYearMonth.format(SalaryDateUtil.MONTH_FORMATTER);
        }
        List<SalaryAcctEmployeePO> salaryAcctEmployees = getAddUpDeductionService(user).getAccountedEmployeeDataByTaxYearMonth(nextTaxYearMonthStr);

        // 判断是否有核算过
        if (CollectionUtils.isNotEmpty(salaryAcctEmployees) && !Objects.equals(taxYearMonthStr.split("-")[1], "12")) {
            Optional<SalaryAcctEmployeePO> optionalAcctEmp = salaryAcctEmployees.stream().filter(f -> f.getEmployeeId().equals(addUpSituationParam.getEmployeeId()) && f.getTaxAgentId().equals(addUpSituationParam.getTaxAgentId())).findFirst();
            if (optionalAcctEmp.isPresent()) {
                throw new SalaryRunTimeException("该年月这条数据已经核算过,不可进行编辑！");
            }
        }
        ArrayList<AddUpSituation> updateList = new ArrayList<>();
        AddUpSituation build = AddUpSituation.builder().id(addUpSituationParam.getId()).addUpIncome(addUpSituationParam.getAddUpIncome()).addUpSubtraction(addUpSituationParam.getAddUpSubtraction())
                .addUpSocialSecurityTotal(addUpSituationParam.getAddUpSocialSecurityTotal()).addUpAccumulationFundTotal(addUpSituationParam.getAddUpAccumulationFundTotal())
                .addUpChildEducation(addUpSituationParam.getAddUpChildEducation()).addUpContinuingEducation(addUpSituationParam.getAddUpContinuingEducation())
                .addUpHousingLoanInterest(addUpSituationParam.getAddUpHousingLoanInterest()).addUpHousingRent(addUpSituationParam.getAddUpHousingRent())
                .addUpSupportElderly(addUpSituationParam.getAddUpSupportElderly()).addUpIllnessMedical(addUpSituationParam.getAddUpIllnessMedical())
                .addUpEnterpriseAndOther(addUpSituationParam.getAddUpEnterpriseAndOther()).addUpOtherDeduction(addUpSituationParam.getAddUpOtherDeduction())
                .addUpTaxExemptIncome(addUpSituationParam.getAddUpTaxExemptIncome()).addUpAllowedDonation(addUpSituationParam.getAddUpAllowedDonation())
                .addUpTaxSavings(addUpSituationParam.getAddUpTaxSavings()).addUpAdvanceTax(addUpSituationParam.getAddUpAdvanceTax())
                .addUpInfantCare(addUpSituationParam.getAddUpInfantCare())
                .addUpPrivatePension(addUpSituationParam.getAddUpPrivatePension())
                .build();
        updateList.add(build);
        biz.batchUpdate(updateList);

        // 记录日志
        AddUpSituation newValue = biz.getById(build.getId());
        String name = SalaryI18nUtil.getI18nLabel(0, "编辑");
        LoggerContext<AddUpSituation> loggerContext = new LoggerContext<>();
        loggerContext.setTargetId(newValue.getId().toString());
        loggerContext.setTargetName(SalaryI18nUtil.getI18nLabel(0, "往期累计情况") + "-" + newValue.getId());
        loggerContext.setOperateType(OperateTypeEnum.UPDATE.getValue());
        loggerContext.setOperateTypeName(name);
        loggerContext.setOperatedesc(SalaryI18nUtil.getI18nLabel(0, "往期累计情况") + "-" + SalaryI18nUtil
                .getI18nLabel(0, "编辑"));
        loggerContext.setOldValues(byId);
        loggerContext.setNewValues(newValue);
        loggerContext.setUser(user);
        SalaryElogConfig.addUpSituationLoggerTemplate.write(loggerContext);
    }

    /**
     * @return void
     * @description 新建数据
     * @author Harryxzy
     * @date 2022/10/27 22:04
     */
    @Override
    public void createAddUpSituation(AddUpSituationParam addUpSituationParam) {
        Boolean openDevolution = getTaxAgentService(user).isOpenDevolution();
        AddUpSituationBiz biz = new AddUpSituationBiz();

        //查询对于人员信息导入筛选的全局配置
        //SalarySysConfPO salarySysConfPO = getSalarySysConfMapper().getOneByCode("matchEmployeeMode");
        //String confValue = (salarySysConfPO != null && salarySysConfPO.getConfValue() != null && !"".equals(salarySysConfPO.getConfValue())) ? salarySysConfPO.getConfValue() : "0";
        Long currentEmployeeId = (long) user.getUID();
        //税款所属期
        String taxYearMonthStr = Util.null2String(addUpSituationParam.getTaxYearMonth());
        // 获取所有个税扣缴义务人
        Collection<TaxAgentManageRangeEmployeeDTO> taxAgentList = getTaxAgentService(user).listTaxAgentAndEmployeeTree(currentEmployeeId);
        // 获取租户下所有的人员
        List<DataCollectionEmployee> employees = getSalaryEmployeeService(user).listEmployee();
        // 已经核算过的不可操作
        // 获取已经核算的数据
        List<SalaryAcctEmployeePO> salaryAcctEmployees = getAddUpDeductionService(user).getAccountedEmployeeData(taxYearMonthStr);
        //税款所属期
        Date taxYearMonth = SalaryDateUtil.localDateToDate(LocalDate.parse(taxYearMonthStr + "-01", SalaryDateUtil.DATE_FORMATTER));
        // 查询已有数据
        List<AddUpSituation> list = getAddUpSituationMapper().listSome(AddUpSituation.builder().taxYearMonth(taxYearMonth).build());
        Date now = new Date();
        //合规数据
        List<AddUpSituation> insertList = new ArrayList<>();

        List<TaxAgentManageRangeEmployeeDTO.TaxAgentEmployee> taxAgentEmployees = Lists.newArrayList();

        //待插入数据库对象
        AddUpSituation po = AddUpSituation.builder().tenantKey(DEFAULT_TENANT_KEY)
                .createTime(now)
                .updateTime(now)
                .creator((long) user.getUID())
                .year(Integer.valueOf(taxYearMonthStr.split("-")[0]))
                .taxYearMonth(taxYearMonth)
                .build();


        //筛选导入人员信息可以在人力资源池中匹配到的人员信息
        boolean employeeSameId = employees.stream().anyMatch(e -> Objects.equals(e.getEmployeeId(), addUpSituationParam.getEmployeeId()));
        if (!employeeSameId) {
            throw new SalaryRunTimeException("员工信息不存在");
        }
        po.setEmployeeId(addUpSituationParam.getEmployeeId());
        String taxAgentName = addUpSituationParam.getTaxAgentName();
        if (StringUtils.isBlank(taxAgentName)) {
            //个税扣缴义务人不能为空
            throw new SalaryRunTimeException("个税扣缴义务人不能为空");
        } else {
            Optional<TaxAgentManageRangeEmployeeDTO> optionalTemp = taxAgentList.stream().filter(m -> m.getTaxAgentName().equals(taxAgentName)).findFirst();
            if (optionalTemp.isPresent()) {
                po.setTaxAgentId(optionalTemp.get().getTaxAgentId());
                taxAgentEmployees = optionalTemp.get().getEmployeeList();
            } else {
                //个税扣缴义务人不存在
                throw new SalaryRunTimeException("个税扣缴义务人不存在或不在权限范围内");
            }
        }

        // fixme 分权判断，若员工离职后，不在扣缴义务人范围内，会有异常
//                if (openDevolution) {
//                    Optional<TaxAgentManageRangeEmployeeDTO.TaxAgentEmployee> optionalTaxAgentEmp = taxAgentEmployees.stream().filter(f -> f.getEmployeeId().equals(po.getEmployeeId())).findFirst();
//                    if (!optionalTaxAgentEmp.isPresent()) {
//                        Map<String, String> errorMessageMap = Maps.newHashMap();
//                        errorMessageMap.put("message", rowIndex + "该条数据不在个税扣缴义务人人员范围内，不可导入");
//                        errorData.add(errorMessageMap);
//                        errorSum += 1;
//                    }
//                }

        // 判断是否有核算过
        if (CollectionUtils.isNotEmpty(salaryAcctEmployees)) {
            Optional<SalaryAcctEmployeePO> optionalAcctEmp = salaryAcctEmployees.stream().filter(f -> f.getEmployeeId().equals(po.getEmployeeId()) && f.getTaxAgentId().equals(po.getTaxAgentId())).findFirst();
            boolean isExist = list.stream().anyMatch(f -> f.getEmployeeId().equals(po.getEmployeeId()) && f.getTaxAgentId().equals(po.getTaxAgentId()));
            if (optionalAcctEmp.isPresent() && isExist) {
                throw new SalaryRunTimeException("该年月这条数据已经核算过,不可导入");
            }
        }

        //累计收入额
        String addUpIncome = addUpSituationParam.getAddUpIncome();
        po.setAddUpIncome(Util.null2String(addUpIncome));
        //累计减除费用
        String addUpSubtraction = addUpSituationParam.getAddUpSubtraction();
        po.setAddUpSubtraction(addUpSubtraction);
        //累计社保个人合计
        String addUpSocialSecurityTotal = addUpSituationParam.getAddUpSocialSecurityTotal();
        po.setAddUpSocialSecurityTotal(addUpSocialSecurityTotal);
        //累计公积金个人合计
        String addUpAccumulationFundTotal = addUpSituationParam.getAddUpAccumulationFundTotal();
        po.setAddUpAccumulationFundTotal(addUpAccumulationFundTotal);
        //累计子女教育
        String addUpChildEducation = addUpSituationParam.getAddUpChildEducation();
        po.setAddUpChildEducation(Util.null2String(addUpChildEducation));
        //累计继续教育
        String addUpContinuingEducation = addUpSituationParam.getAddUpContinuingEducation();
        po.setAddUpContinuingEducation(Util.null2String(addUpContinuingEducation));
        //累计住房贷款利息
        String addUpHousingLoanInterest = addUpSituationParam.getAddUpHousingLoanInterest();
        po.setAddUpHousingLoanInterest(Util.null2String(addUpHousingLoanInterest));
        //累计住房租金
        String addUpHousingRent = addUpSituationParam.getAddUpHousingRent();
        po.setAddUpHousingRent(Util.null2String(addUpHousingRent));
        //累计赡养老人
        String addUpSupportElderly = addUpSituationParam.getAddUpSupportElderly();
        po.setAddUpSupportElderly(Util.null2String(addUpSupportElderly));
        //累计企业（职业）年金及其他福利
        String addUpEnterpriseAndOther = addUpSituationParam.getAddUpEnterpriseAndOther();
        po.setAddUpEnterpriseAndOther(addUpEnterpriseAndOther);
        //累计其他扣除
        String addUpOtherDeduction = addUpSituationParam.getAddUpOtherDeduction();
        po.setAddUpOtherDeduction(addUpOtherDeduction);
        //累计免税收入
        String addUpTaxExemptIncome = addUpSituationParam.getAddUpTaxExemptIncome();
        po.setAddUpTaxExemptIncome(addUpTaxExemptIncome);
        //累计准予扣除的捐赠额
        String addUpAllowedDonation = addUpSituationParam.getAddUpAllowedDonation();
        po.setAddUpAllowedDonation(addUpAllowedDonation);
        //累计已预扣预缴税额
        String addUpAdvanceTax = addUpSituationParam.getAddUpAdvanceTax();
        po.setAddUpAdvanceTax(addUpAdvanceTax);
        po.setAddUpIllnessMedical(addUpSituationParam.getAddUpIllnessMedical());
        po.setAddUpTaxSavings(addUpSituationParam.getAddUpTaxSavings());
        po.setAddUpInfantCare(addUpSituationParam.getAddUpInfantCare());
        po.setAddUpPrivatePension(addUpSituationParam.getAddUpPrivatePension());
        insertList.add(po);

        //入库
        handleImportData(insertList);
    }

    @Override
    public void deleteSelectAddUpSituation(AddUpSituationDeleteParam deleteParam) {
        long currentEmployeeId = user.getUID();
        // 获取所有个税扣缴义务人
        Collection<TaxAgentManageRangeEmployeeDTO> taxAgentList = getTaxAgentService(user).listTaxAgentAndEmployeeTree(currentEmployeeId);
        AddUpSituationBiz biz = new AddUpSituationBiz();
        String declareMonthStr = deleteParam.getTaxYearMonth();
        List<Long> deleteIds = deleteParam.getIds();
        // 已经核算过的不可操作
        // 获取已经核算的数据
        LocalDate salaryMonthDate = LocalDate.parse(declareMonthStr + "-01", SalaryDateUtil.DATE_FORMATTER);
        salaryMonthDate = salaryMonthDate.plusMonths(1);
        String format = salaryMonthDate.atStartOfDay().format(DateTimeFormatter.ofPattern("yyyy-MM"));
        List<SalaryAcctEmployeePO> salaryAcctEmployees = getAddUpDeductionService(user).getAccountedEmployeeData(format);
        // 判断是否有核算过
        List<AddUpSituation> deletePOList = new ArrayList<>();
        List<Long> deleteList = new ArrayList<>();
        for (int i = 0; i < deleteIds.size(); i++) {
            Long id = deleteIds.get(i);
            AddUpSituation byId = biz.getById(id);
            if (byId == null) {
                throw new SalaryRunTimeException("数据不存在或已被删除！");
            }
            // 判断是否在个税扣缴义务人范围内
            Optional<TaxAgentManageRangeEmployeeDTO> first = taxAgentList.stream().filter(m -> Objects.equals(m.getTaxAgentId(), byId.getTaxAgentId())).findFirst();
            if (!first.isPresent()) {
                throw new SalaryRunTimeException("个税扣缴义务人不存在或不在权限范围内");
            }
            // 判断用户是否存在
            if (CollectionUtils.isNotEmpty(salaryAcctEmployees)) {
                Optional<SalaryAcctEmployeePO> optionalAcctEmp = salaryAcctEmployees.stream().filter(f -> f.getEmployeeId().equals(byId.getEmployeeId()) && f.getTaxAgentId().equals(byId.getTaxAgentId())).findFirst();
                if (optionalAcctEmp.isPresent()) {
                    throw new SalaryRunTimeException("所选数据在该年月中已经核算过并归档,不可进行删除！");
                }
            }
            deleteList.add(byId.getId());
            deletePOList.add(byId);
        }
        biz.batchDeleteByIDS(deleteList);

        // 记录日志
        deletePOList.stream().forEach(po -> {
            LoggerContext loggerContext = new LoggerContext<>();
            loggerContext.setTargetId(po.getId().toString());
            loggerContext.setTargetName(SalaryI18nUtil.getI18nLabel(0, "往期累计情况") + "-" + po.getId());
            loggerContext.setOperateType(OperateTypeEnum.DELETE.getValue());
            loggerContext.setOperateTypeName(SalaryI18nUtil.getI18nLabel(0, "删除"));
            loggerContext.setOperatedesc(SalaryI18nUtil.getI18nLabel(0, "往期累计情况") + "-" + SalaryI18nUtil
                    .getI18nLabel(0, "删除"));
            loggerContext.setOldValues(po);
            loggerContext.setUser(user);
            SalaryElogConfig.addUpSituationLoggerTemplate.write(loggerContext);
        });
    }

    @Override
    public void deleteAllAddUpSituation(AddUpSituationDeleteParam deleteParam) {
        String declareMonthStr = deleteParam.getTaxYearMonth();
        long currentEmployeeId = user.getUID();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        // 获取所有个税扣缴义务人
        Collection<TaxAgentManageRangeEmployeeDTO> taxAgentList = getTaxAgentService(user).listTaxAgentAndEmployeeTree(currentEmployeeId);
        List<Long> taxAgentIds = taxAgentList.stream().map(TaxAgentManageRangeEmployeeDTO::getTaxAgentId).collect(Collectors.toList());
        AddUpSituationBiz biz = new AddUpSituationBiz();
        Date declareMonthDate = new Date();
        try {
            declareMonthDate = (sdf.parse(declareMonthStr + "-01"));
        } catch (Exception e) {
            throw new SalaryRunTimeException("日期异常");
        }
        AddUpSituation queryParam = null;

        if (deleteParam.getTaxAgentId() != null && !deleteParam.getTaxAgentId().isEmpty()) {
            // 设置了个税扣缴义务人
            Long taxAgentId = SalaryEntityUtil.string2Long(deleteParam.getTaxAgentId());
            boolean canDelete = taxAgentIds.stream().anyMatch(t -> Objects.equals(t, taxAgentId));
            if (!canDelete) {
                throw new SalaryRunTimeException("个税扣缴义务人不存在或不在权限范围内!");
            }
            ArrayList<Long> tai = new ArrayList<>();
            tai.add(taxAgentId);
            queryParam = AddUpSituation.builder().taxYearMonth(declareMonthDate).taxAgentIds(tai).build();
        } else {
            queryParam = AddUpSituation.builder().taxYearMonth(declareMonthDate).taxAgentIds(taxAgentIds).build();
        }

        // 获取所有想要删除的数据
        List<AddUpSituation> list = biz.listSome(queryParam);
        LocalDate salaryMonthDate = LocalDate.parse(declareMonthStr + "-01", SalaryDateUtil.DATE_FORMATTER);
        String format = salaryMonthDate.plusMonths(1).atStartOfDay().format(DateTimeFormatter.ofPattern("yyyy-MM"));
        // 获取已经核算的数据
        List<SalaryAcctEmployeePO> employees = getAddUpDeductionService(user).getAccountedEmployeeData(format);
        for (AddUpSituation item : list) {
            if (CollectionUtils.isNotEmpty(employees)) {
                Optional<SalaryAcctEmployeePO> optionalAcctEmp = employees.stream().filter(f -> f.getEmployeeId().equals(item.getEmployeeId()) && f.getTaxAgentId().equals(item.getTaxAgentId())).findFirst();
                if (optionalAcctEmp.isPresent()) {
                    throw new SalaryRunTimeException("有员工在该年月中已经完成核算并归档，不能进行一键清空！");
                }
            }
        }
        List<Long> deleteIds = list.stream().map(AddUpSituation::getId).collect(Collectors.toList());
        biz.batchDeleteByIDS(deleteIds);

        // 记录日志
        Collection<Long> finalTaxAgentIds = queryParam.getTaxAgentIds();
        List<String> taxAgentNames = taxAgentList.stream().filter(t -> finalTaxAgentIds.contains(t.getTaxAgentId()))
                .map(TaxAgentManageRangeEmployeeDTO::getTaxAgentName).collect(Collectors.toList());
        String name = declareMonthStr + " " + StringUtils.join(taxAgentNames, ",");
        LoggerContext<AddUpSituation> loggerContext = new LoggerContext<>();
        loggerContext.setTargetName(name);
        loggerContext.setOperateType(OperateTypeEnum.CLEAR.getValue());
        loggerContext.setOperateTypeName(SalaryI18nUtil.getI18nLabel(0, "一键清空"));
        loggerContext.setOperatedesc(SalaryI18nUtil.getI18nLabel(0, "往期累计情况") + "-" + SalaryI18nUtil
                .getI18nLabel(0, "一键清空：") + name);
        loggerContext.setUser(user);
        SalaryElogConfig.addUpSituationLoggerTemplate.write(loggerContext);
    }

    @Override
    public AddUpSituationRecordDTO getAddUpSituation(AddUpSituationParam addUpSituationParam) {
        long uid = user.getUID();
        // 获取所有个税扣缴义务人
        Collection<TaxAgentManageRangeEmployeeDTO> taxAgentList = getTaxAgentService(user).listTaxAgentAndEmployeeTree(uid);
        List<String> taxAgentNames = taxAgentList.stream().map(TaxAgentManageRangeEmployeeDTO::getTaxAgentName).collect(Collectors.toList());
        ArrayList<Long> ids = new ArrayList<>();
        ids.add(addUpSituationParam.getId());
        AddUpSituationQueryParam build = AddUpSituationQueryParam.builder().ids(ids).build();
        List<AddUpSituationRecordDTO> list = biz.recordList(build);
        if (list == null || list.size() == 0) {
            throw new SalaryRunTimeException("该数据不存在！");
        }
        String taxAgentName = list.get(0).getTaxAgentName();
        if (!taxAgentNames.contains(taxAgentName)) {
            throw new SalaryRunTimeException("您无权查看该数据!");
        }
        return list.get(0);
    }

    @Override
    public void batchSave(List<AddUpSituation> list) {
        if (CollectionUtils.isNotEmpty(list)) {
            encryptUtil.encryptList(list, AddUpSituation.class);
            List<List<AddUpSituation>> partition = Lists.partition(list, 50);
            partition.forEach(getAddUpSituationMapper()::insertData);
        }

    }
}
