package com.engine.salary.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.cloudstore.eccom.pc.table.WeaTableColumn;
import com.engine.common.util.ServiceUtil;
import com.engine.core.impl.Service;
import com.engine.salary.constant.SalaryDefaultTenantConstant;
import com.engine.salary.constant.SalaryItemConstant;
import com.engine.salary.entity.datacollection.bo.VariableArchiveBO;
import com.engine.salary.entity.datacollection.bo.VariableArchiveExcelBO;
import com.engine.salary.entity.datacollection.dto.VariableArchiveListDTO;
import com.engine.salary.entity.datacollection.dto.VariableItemListDTO;
import com.engine.salary.entity.datacollection.param.VariableArchiveImportHandleParam;
import com.engine.salary.entity.datacollection.param.VariableArchiveQueryParam;
import com.engine.salary.entity.datacollection.param.VariableArchiveSaveParam;
import com.engine.salary.entity.datacollection.po.VariableArchiveItemPO;
import com.engine.salary.entity.datacollection.po.VariableArchivePO;
import com.engine.salary.entity.datacollection.po.VariableItemPO;
import com.engine.salary.entity.salaryarchive.dto.SalaryArchiveInitImportDTO;
import com.engine.salary.entity.taxagent.dto.TaxAgentManageRangeEmployeeDTO;
import com.engine.salary.entity.taxagent.po.TaxAgentPO;
import com.engine.salary.enums.datacollection.UseEmployeeTypeEnum;
import com.engine.salary.enums.salaryitem.SalaryDataTypeEnum;
import com.engine.salary.exception.SalaryRunTimeException;
import com.engine.salary.mapper.datacollection.VariableArchiveMapper;
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.IdGenerator;
import com.engine.salary.util.db.MapperProxyFactory;
import com.engine.salary.util.excel.*;
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.Maps;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
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.time.YearMonth;
import java.util.*;
import java.util.stream.Collectors;

import static com.engine.salary.util.excel.ExcelSupport.EXCEL_TYPE_XLSX;

/**
 * @author Harryxzy
 * @ClassName VariableArchiveServiceImpl
 * @date 2024/08/06 17:40
 * @description 浮动薪酬档案
 */
public class VariableArchiveServiceImpl extends Service implements VariableArchiveService {

    private VariableArchiveMapper getVariableArchiveMapper() {
        return MapperProxyFactory.getProxy(VariableArchiveMapper.class);
    }

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

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

    private VariableArchiveItemService getVariableArchiveItemService(User user) {
        return ServiceUtil.getService(VariableArchiveItemServiceImpl.class, user);
    }

    private VariableItemService getVariableItemService(User user) {
        return ServiceUtil.getService(VariableItemServiceImpl.class, user);
    }

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

    private int deleteByIds(List<Long> deleteIds) {
        if (CollectionUtils.isEmpty(deleteIds)) {
            return 0;
        }
        return getVariableArchiveMapper().deleteByIds(deleteIds);
    }

    /**
     * 浮动薪酬档案列表
     *
     * @param queryParam
     * @return
     */
    @Override
    public PageInfo<VariableArchiveListDTO> listPage(VariableArchiveQueryParam queryParam) {
        List<VariableArchiveListDTO> variableArchiveList = list(queryParam);
        return SalaryPageUtil.buildPage(queryParam.getCurrent(), queryParam.getPageSize(), variableArchiveList, VariableArchiveListDTO.class);
    }

    @Override
    public List<VariableArchiveListDTO> list(VariableArchiveQueryParam queryParam) {
        ValidUtil.doValidator(queryParam);
        Long employeeId = Long.valueOf(user.getUID());
        // 判断是否是“总管理员”
        Boolean isChief = getTaxAgentService(user).isChief(employeeId);
        // 是否开启分权
        Boolean openDevolution = getTaxAgentService(user).isOpenDevolution();
        if (BooleanUtils.isTrue(openDevolution) && !isChief) {
            Collection<TaxAgentPO> taxAgentPOS = getTaxAgentService(user).listAllTaxAgentsAsAdmin(employeeId);
            List<Long> taxAgentIds = taxAgentPOS.stream().map(TaxAgentPO::getId).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(taxAgentIds)) {
                // 无权限
                return Collections.emptyList();
            }
            if (CollectionUtils.isNotEmpty(queryParam.getTaxAgentIds())) {
                taxAgentIds = taxAgentIds.stream().filter(queryParam.getTaxAgentIds()::contains).collect(Collectors.toList());
            }
            queryParam.setTaxAgentIds(taxAgentIds);
        }

        // 浮动薪酬档案列表
        if (Objects.nonNull(queryParam.getSalaryMonth())) {
            queryParam.setSalaryMonthDate(SalaryDateUtil.dateStrToLocalYearMonth(queryParam.getSalaryMonth()));
        }
        //排序配置
        OrderRuleVO orderRule = getSalarySysConfService(user).orderRule();
        queryParam.setOrderRule(orderRule);
        return listDTO(queryParam);
    }

    public List<VariableArchiveListDTO> listDTO(VariableArchiveQueryParam queryParam) {
        List<VariableArchiveListDTO> list = getVariableArchiveMapper().list(queryParam);
        SalaryI18nUtil.i18nList(list);
        return list;
    }

    /**
     * 构建浮动薪资档案数据
     *
     * @param variableArchives
     * @return
     */
    @Override
    public List<Map<String, Object>> buildVariableArchiveData(List<VariableArchiveListDTO> variableArchives) {
        List<Long> variableArchiveIds = variableArchives.stream().map(VariableArchiveListDTO::getId).collect(Collectors.toList());
        // 获取浮动薪资档案所对应的浮动薪资项目数据
        List<VariableArchiveItemPO> variableArchiveItemList = getVariableArchiveItemService(user).listByVariableArchiveIds(variableArchiveIds);
        Map<Long, List<VariableArchiveItemPO>> variableArchiveItemMap = SalaryEntityUtil.group2Map(variableArchiveItemList, VariableArchiveItemPO::getVariableArchiveId);
        List<Map<String, Object>> variableArchiveItemData = variableArchives.stream().map(m -> {
            Map<String, Object> map = Maps.newHashMap();
            map.put("variableArchiveId", m.getId());
            List<VariableArchiveItemPO> variableArchiveItemValuelList = variableArchiveItemMap.getOrDefault(m.getId(), Collections.emptyList());
            variableArchiveItemValuelList.forEach(i -> {
                map.put(i.getVariableItemId() + SalaryItemConstant.VARIABLE_ITEM_DYNAMIC_SUFFIX, i.getItemValue());
            });
            return map;
        }).collect(Collectors.toList());


        // 组装数据
        List<Map<String, Object>> listMaps = new ArrayList<>();
        variableArchives.forEach(e -> {
            Map<String, Object> map = new LinkedHashMap<>();
            map.put("id", e.getId());
            map.put("taxAgentName", e.getTaxAgentName());
            map.put("taxAgentIds", e.getTaxAgentId());
            map.put("username", e.getUsername());
            map.put("salaryMonth", SalaryDateUtil.getFormatYearMonth(e.getSalaryMonth()));
            map.put("employeeId", e.getEmployeeId());
            map.put("subcompanyName", e.getSubcompanyName());
            map.put("departmentName", e.getDepartmentName());
            map.put("mobile", e.getMobile());
            map.put("workcode", e.getWorkcode());
            map.put("idNo", e.getIdNo());
            map.put("companystartdate", e.getCompanystartdate());
            map.put("dismissdate", e.getDismissdate());

            // 浮动薪资项目动态
            Optional<Map<String, Object>> optionalItem = variableArchiveItemData.stream().filter(f -> f.get("variableArchiveId").toString().equals(e.getId().toString())).findFirst();
            optionalItem.ifPresent(map::putAll);

            listMaps.add(map);
        });
        return listMaps;
    }

    /**
     * 创建浮动薪酬档案
     *
     * @param saveParam
     */
    @Override
    public void createData(VariableArchiveSaveParam saveParam) {
        ValidUtil.doValidator(saveParam);
        saveParam.setSalaryMonthDate(SalaryDateUtil.dateStrToLocalYearMonth(saveParam.getSalaryMonth()));

        List<VariableArchivePO> variableArchivePOList = getVariableArchiveMapper().listSome(VariableArchivePO.builder().salaryMonth(saveParam.getSalaryMonthDate()).taxAgentId(saveParam.getTaxAgentIds()).employeeId(saveParam.getEmployeeId()).build());
        if (CollectionUtils.isNotEmpty(variableArchivePOList)) {
           throw new SalaryRunTimeException("已存在浮动薪酬数据");
        }

        // 保存浮动薪资档案信息
        Date now = new Date();
        VariableArchivePO variableArchivePO = VariableArchivePO.builder()
                .id(IdGenerator.generate())
                .employeeId(saveParam.getEmployeeId())
                .taxAgentId(saveParam.getTaxAgentIds())
                .salaryMonth(saveParam.getSalaryMonthDate())
                .creator((long) user.getUID())
                .createTime(now)
                .updateTime(now)
                .deleteType(NumberUtils.INTEGER_ZERO)
                .tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY)
                .build();
        getVariableArchiveMapper().insertIgnoreNull(variableArchivePO);

        // 保存浮动薪资档案详细信息
        List<VariableArchiveItemPO> variableArchiveItemList = new ArrayList<>();
        if(CollectionUtil.isNotEmpty(saveParam.getItemValueList())){
            saveParam.getItemValueList().forEach(e -> {
                variableArchiveItemList.add(VariableArchiveItemPO.builder()
                        .id(IdGenerator.generate())
                        .employeeId(saveParam.getEmployeeId())
                        .variableArchiveId(variableArchivePO.getId())
                        .variableItemId(e.getVariableItemId())
                        .itemValue(e.getItemValue())
                        .creator((long) user.getUID())
                        .createTime(now)
                        .updateTime(now)
                        .deleteType(NumberUtils.INTEGER_ZERO)
                        .tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY)
                        .build());
            });
        }

        if (CollectionUtils.isNotEmpty(variableArchiveItemList)) {
            getVariableArchiveItemService(user).batchInsert(variableArchiveItemList);
        }
    }

    /**
     * 浮动薪资档案明细
     *
     * @param queryParam
     * @return
     */
    @Override
    public Map<String, Object> getDetail(VariableArchiveQueryParam queryParam) {
        if (queryParam.getId() == null) {
            return Collections.emptyMap();
        }

        List<VariableArchiveListDTO> variableArchiveList = listDTO(queryParam);

        // 获取所有浮动薪酬项目
        List<VariableItemPO> variableItems = getVariableItemService(user).listAll();

        //整合所有的显示列（固定列+薪资项目动态列）
        List<Map<String, Object>> listMaps = buildVariableArchiveData(variableArchiveList);
        Map<String, Object> resultMap = listMaps.get(0);

        //动态列组装
        List<WeaTableColumn> columns = VariableArchiveBO.buildVariableArchiveTable(variableItems);

        Map<String, Object> datas = new HashMap<>();
        datas.put("data", resultMap);
        datas.put("column", columns);
        return datas;
    }

    @Override
    public List<VariableItemListDTO> getCreateForm() {
        List<VariableItemPO> variableItemPOS = getVariableItemService(user).listAll();
        List<VariableItemListDTO> variableItemDTOList = variableItemPOS.stream()
                .map(po -> VariableItemListDTO.builder()
                        .id(po.getId())
                        .name(po.getName())
                        .dataType(SalaryDataTypeEnum.parseByValue(po.getDataType()).getValue())
                        .build())
                .collect(Collectors.toList());
        return variableItemDTOList;
    }

    @Override
    public XSSFWorkbook downloadTemplate(VariableArchiveQueryParam param) {
        // 名称
        String nameI18n = SalaryI18nUtil.getI18nLabel(0, "浮动薪酬导入模板");

        // 获取所有可被引用的薪资项目
        List<VariableItemPO> variableItems = getVariableItemService(user).listAll();
        List<Object> header = Lists.newArrayList();
        header.add(SalaryI18nUtil.getI18nLabel(0, "个税扣缴义务人"));
        header.add(SalaryI18nUtil.getI18nLabel(85429, "姓名"));
        header.add(SalaryI18nUtil.getI18nLabel(86185, "部门"));
        header.add(SalaryI18nUtil.getI18nLabel(86186, "手机号"));
        header.add(SalaryI18nUtil.getI18nLabel(1933, "工号"));
        header.add(SalaryI18nUtil.getI18nLabel(86186, "证件号码"));
        header.add(SalaryI18nUtil.getI18nLabel(86187, "入职日期"));
        for (VariableItemPO variableItem : variableItems) {
            header.add(variableItem.getName());
        }

        // 2.表头
        List<List<Object>> rows = new ArrayList<>();
        rows.add(header);
        // 获取档案信息
        List<VariableArchiveListDTO> variableArchiveList = list(param);

        if (param.isHasData()) {
            List<Map<String, Object>> listMaps = buildVariableArchiveData(variableArchiveList);
            // 组装数据
            listMaps.forEach(e -> {
                List<Object> row = new ArrayList<>();
                row.add(e.get("taxAgentName").toString());
                row.add(e.get("username").toString());
                row.add(Optional.ofNullable(e.get("departmentName")).orElse("").toString());
                row.add(e.get("mobile") == null ? "" : e.get("mobile").toString());
                row.add(Optional.ofNullable(e.get("workcode")).orElse("").toString());
                row.add(Util.null2String(e.get("idNo")));
                row.add(Util.null2String(e.get("companystartdate")));

                // 薪资项目数据
                for (VariableItemPO variableItem : variableItems) {
                    row.add(e.containsKey(variableItem.getId() + SalaryItemConstant.VARIABLE_ITEM_DYNAMIC_SUFFIX) ? (e.get(variableItem.getId() + SalaryItemConstant.VARIABLE_ITEM_DYNAMIC_SUFFIX) == null ? ""
                            : e.get(variableItem.getId() + SalaryItemConstant.VARIABLE_ITEM_DYNAMIC_SUFFIX).toString()) : "");
                }
                rows.add(row);
            });
        }


        // 4.注释
        List<ExcelComment> excelComments = Lists.newArrayList();

        return ExcelUtilPlus.genWorkbookV2(rows, nameI18n, excelComments);
    }

    @Override
    public ExcelPreviewDTO preview(VariableArchiveImportHandleParam importParam) {

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

        InputStream fileInputStream = null;
        try {
            fileInputStream = ImageFileManager.getInputStreamById(Integer.parseInt(imageId));
            return ExcelParseHelper.preview(fileInputStream, 0, EXCEL_TYPE_XLSX);
        } finally {
            IOUtils.closeQuietly(fileInputStream);
        }
    }

    @Override
    public Map<String, Object> importData(VariableArchiveImportHandleParam importParam) {
        // 初始化国际化标签
        VariableArchiveExcelBO.initI18n();
        // 校验参数
        checkImportParam(importParam);
        String imageId = importParam.getImageId();
        // 构建导入处理参数
        importParam = buildImportHandleParam(importParam);
        // 导入有重复
        List<String> allTodoVariableArchives = Lists.newArrayList();

        InputStream fileInputStream = null;
        try {
            fileInputStream = ImageFileManager.getInputStreamById(Integer.parseInt(imageId));
            Workbook workbook = ExcelSupport.parseFile(fileInputStream, EXCEL_TYPE_XLSX);
            Sheet sheet = workbook.getSheetAt(0);
            List<String> headers = ExcelSupport.getSheetHeader(sheet, 0);

            int total = 0;
            //excel数据
            List<Map<String, Object>> data = ExcelParseHelper.parse2Map(workbook, 0, 1);
            if (data != null) {
                total += data.size();
            }

            int index = 0;
            int successCount = 0;
            int errorCount = 0;
            // 用于（初始化导入）的相同employeeId时的处理
            List<SalaryArchiveInitImportDTO> initImportData = Lists.newArrayList();


            // 错误提示
            List<Map<String, String>> excelComments = new ArrayList<>();
            // 错误sheet数据
            List<Map<String, Object>> errorData = new ArrayList<>();

            Map<String, Object> map;
            for (int i = 0; i < data.size(); i++) {
                index += 1;
                map = data.get(i);
                map.put("index", i + 2);
                // 3.校验行内容
                boolean isError = VariableArchiveExcelBO.singleRowCheck(allTodoVariableArchives, map, headers, excelComments, errorCount, importParam, user);
                if (isError) {
                    errorCount += 1;
                    // 添加错误数据
                    errorData.add(map);
                } else {
                    successCount += 1;
                }
            }

            // 4.数据入库处理
            handleImportData(importParam);

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

            apidatas.put("successCount", successCount);
            apidatas.put("errorCount", errorCount);
            apidatas.put("errorNotice", excelComments);
            return apidatas;
        } finally {
            IOUtils.closeQuietly(fileInputStream);
        }
    }

    private void checkImportParam(VariableArchiveImportHandleParam importParam) {
        //excel文件id
        String imageId = Util.null2String(importParam.getImageId());
        //税款所属期
        String salaryMonthStr = Util.null2String(importParam.getSalaryMonth());
        if (StringUtils.isBlank(imageId)) {
            throw new SalaryRunTimeException("文件不存在");
        }
        if (StringUtils.isBlank(salaryMonthStr)) {
            throw new SalaryRunTimeException("薪资所属月为空");
        }
    }

    /**
     * 构建导入处理参数
     *
     * @param param
     * @return
     */
    private VariableArchiveImportHandleParam buildImportHandleParam(VariableArchiveImportHandleParam param) {
        // 获取所有可被引用的浮动薪资项目
        List<VariableItemPO> variableItems = getVariableItemService(user).listAll();
        Collection<Long> variableItemIds = variableItems.stream().map(VariableItemPO::getId).collect(Collectors.toList());
        List<VariableArchivePO> variableArchiveList = getVariableArchiveMapper().listSome(VariableArchivePO.builder().salaryMonth(SalaryDateUtil.dateStrToLocalYearMonth(param.getSalaryMonth())).build());

        List<Long> variableArchiveIds = variableArchiveList.stream().map(VariableArchivePO::getId).collect(Collectors.toList());
        Map<String, VariableArchivePO> variableArchivesMap = SalaryEntityUtil.convert2Map(variableArchiveList, k -> k.getTaxAgentId() + "-" + k.getEmployeeId());

        // 获取浮动薪资档案明细数据
        List<VariableArchiveItemPO> variableArchiveItemPOS = getVariableArchiveItemService(user).listByVariableArchiveIds(variableArchiveIds);
        Map<String, List<VariableArchiveItemPO>> variableArchiveItemMap = SalaryEntityUtil.group2Map(variableArchiveItemPOS, k -> k.getVariableArchiveId() + "-" + k.getVariableItemId());

        Collection<TaxAgentManageRangeEmployeeDTO> taxAgentList;
        taxAgentList = getTaxAgentService(user).listTaxAgentAndEmployeeTree((long) user.getUID());


        return VariableArchiveImportHandleParam.builder()
                .imageId(param.getImageId())
                .salaryMonth(param.getSalaryMonth())
                .salaryMonthDate(SalaryDateUtil.dateStrToLocalYearMonth(param.getSalaryMonth()))
                .currentEmployeeId((long) user.getUID())
                .tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY)
                //人员定位方式
                .empValidType(getSalaryEmployeeService(user).empValidType())
                // 获取租户下所有的人员
                .employees(getSalaryEmployeeService(user).listAll(UseEmployeeTypeEnum.ORG))
                // 浮动薪资项目
                .variableItems(variableItems)
                // 查询已有的浮动薪资档案基本数据
                .variableArchivesMap(variableArchivesMap)
                // 浮动薪资项目id
                .variableItemIds(variableItemIds)
                // 查询已生效的浮动薪资项目数据
                .effectiveItemListMap(variableArchiveItemMap)
                // 可以管理的义务人
                .taxAgentList(taxAgentList)
                // 当前时间
                .nowTime(new Date())
                // 当天
                .today(new Date())
                // 待保存浮动薪资档案
                .variableArchiveSaves(Lists.newArrayList())
                // 待保存浮动薪资档案-浮动薪资项目
                .variableArchiveItemSaves(Lists.newArrayList())
                // 待删除浮动薪资档案-浮动薪资项目
                .variableArchiveItemDelSalaryItemIds(Lists.newArrayList())
                .build();
    }


    private void handleImportData(VariableArchiveImportHandleParam importHandleParam) {
        List<VariableArchivePO> variableArchiveSaves = importHandleParam.getVariableArchiveSaves();
        List<VariableArchiveItemPO> variableArchiveItemSaves = importHandleParam.getVariableArchiveItemSaves();
        List<Long> variableArchiveItemDelSalaryItemIds = importHandleParam.getVariableArchiveItemDelSalaryItemIds();

        // 新增档案
        if (CollectionUtils.isNotEmpty(variableArchiveSaves)) {
            variableArchiveSaves.stream().forEach(getVariableArchiveMapper()::insertIgnoreNull);
        }
        //  薪资档案-薪资项目
        if (CollectionUtils.isNotEmpty(variableArchiveItemDelSalaryItemIds)) {
            getVariableArchiveItemService(user).deleteByIds(variableArchiveItemDelSalaryItemIds);
        }
        // 薪资档案-薪资项目
        if (CollectionUtils.isNotEmpty(variableArchiveItemSaves)) {
            getVariableArchiveItemService(user).batchInsert(variableArchiveItemSaves);
        }
    }

    @Override
    public XSSFWorkbook export(VariableArchiveQueryParam param) {
        // 名称
        String nameI18n = SalaryI18nUtil.getI18nLabel(0, "浮动薪酬");

        // 获取所有可被引用的薪资项目
        List<VariableItemPO> variableItems = getVariableItemService(user).listAll();
        List<WeaTableColumn> header = VariableArchiveBO.buildVariableArchiveTable(variableItems);
        Map<String, WeaTableColumn> columnMap = SalaryEntityUtil.convert2Map(header, WeaTableColumn::getColumn);

        List<WeaTableColumn> finalColumns = new ArrayList<>();
        param.getColumns().forEach(col -> {
            WeaTableColumn column = columnMap.get(col);
            if (column != null) {
                finalColumns.add(column);
            }
        });
        header = finalColumns;

        // 2.表头
        List<List<Object>> rows = new ArrayList<>();
        rows.add(header.stream().map(WeaTableColumn::getText).collect(Collectors.toList()));
        // 获取档案信息
        List<VariableArchiveListDTO> variableArchiveList = list(param);
        List<Map<String, Object>> listMaps = buildVariableArchiveData(variableArchiveList);
        // 组装数据
        List<WeaTableColumn> finalHeader = header;
        listMaps.forEach(e -> {
            List<Object> row = new ArrayList<>();
            for (WeaTableColumn column : finalHeader) {
                row.add(Util.null2String(e.get(column.getColumn())));
            }
            // row.add(e.get("salaryMonth").toString());
            // row.add(e.get("taxAgentName").toString());
            // row.add(e.get("username").toString());
            // row.add(Optional.ofNullable(e.get("departmentName")).orElse("").toString());
            // row.add(e.get("mobile") == null ? "" : e.get("mobile").toString());
            // row.add(Optional.ofNullable(e.get("workcode")).orElse("").toString());
            // row.add(Util.null2String(e.get("idNo")));
            // row.add(Util.null2String(e.get("companystartdate")));
            //
            // // 薪资项目数据
            // for (VariableItemPO variableItem : variableItems) {
            //     row.add(e.containsKey(variableItem.getId() + SalaryItemConstant.VARIABLE_ITEM_DYNAMIC_SUFFIX) ? (e.get(variableItem.getId() + SalaryItemConstant.VARIABLE_ITEM_DYNAMIC_SUFFIX) == null ? ""
            //             : e.get(variableItem.getId() + SalaryItemConstant.VARIABLE_ITEM_DYNAMIC_SUFFIX).toString()) : "");
            // }
            rows.add(row);
        });

        // 4.注释
        List<ExcelComment> excelComments = Lists.newArrayList();

        return ExcelUtilPlus.genWorkbookV2(rows, nameI18n, excelComments);
    }

    @Override
    public void deleteSelectVariableArchive(Collection<Long> deleteIds) {
        if (CollectionUtils.isEmpty(deleteIds)) {
            return;
        }
        List<VariableArchivePO> variableArchivePOList = getVariableArchiveMapper().listSome(VariableArchivePO.builder().ids(deleteIds).build());
        List<Long> archiveIds = variableArchivePOList.stream().map(VariableArchivePO::getId).collect(Collectors.toList());
        deleteByIds(archiveIds);
        // 删除明细
        getVariableArchiveItemService(user).deleteByArchiveIds(archiveIds);

    }

    @Override
    public List<Map<String, Object>> listBySalaryMonthAndEmployeeIds(YearMonth salaryMonth, List<Long> employeeIds, Long taxAgentId) {
        VariableArchiveQueryParam queryParam = VariableArchiveQueryParam.builder()
                .employeeIds(employeeIds)
                .salaryMonth(SalaryDateUtil.getFormatYearMonth(salaryMonth))
                .salaryMonthDate(SalaryDateUtil.toDate(salaryMonth, 1))
                .taxAgentIds(Collections.singletonList(taxAgentId))
                .build();
        List<VariableArchiveListDTO> variableArchiveListDTO = list(queryParam);
        return buildVariableArchiveData(variableArchiveListDTO);
    }

    @Override
    public void updateData(VariableArchiveSaveParam updateParam) {
        if (updateParam.getId() == null) {
            throw new SalaryRunTimeException("参数错误");
        }
        // 获取浮动薪酬档案
        VariableArchivePO variableArchivePO = getVariableArchiveMapper().getById(updateParam.getId());
        if (variableArchivePO == null) {
            throw new SalaryRunTimeException("浮动薪酬档案不存在或已被删除");
        }

        // 删除原有的浮动薪酬档案明细
        getVariableArchiveItemService(user).deleteByArchiveIds(Collections.singletonList(updateParam.getId()));

        // 保存浮动薪资档案详细信息
        List<VariableArchiveItemPO> variableArchiveItemList = new ArrayList<>();
        Date now = new Date();
        updateParam.getItemValueList().forEach(e -> {
            variableArchiveItemList.add(VariableArchiveItemPO.builder()
                    .id(IdGenerator.generate())
                    .employeeId(updateParam.getEmployeeId())
                    .variableArchiveId(variableArchivePO.getId())
                    .variableItemId(e.getVariableItemId())
                    .itemValue(e.getItemValue())
                    .creator(Long.valueOf(user.getUID()))
                    .createTime(now)
                    .updateTime(now)
                    .deleteType(NumberUtils.INTEGER_ZERO)
                    .tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY)
                    .build());
        });

        if (CollectionUtils.isNotEmpty(variableArchiveItemList)) {
            getVariableArchiveItemService(user).batchInsert(variableArchiveItemList);
        }
    }
}
