package com.engine.salary.report.wrapper;

import cn.hutool.crypto.SecureUtil;
import com.alibaba.fastjson.JSONArray;
import com.cloudstore.eccom.pc.table.WeaTable;
import com.cloudstore.eccom.pc.table.WeaTableColumn;
import com.cloudstore.eccom.result.WeaResultMsg;
import com.engine.common.util.ServiceUtil;
import com.engine.core.impl.Service;
import com.engine.hrmelog.entity.dto.LoggerContext;
import com.engine.salary.cache.SalaryCacheKey;
import com.engine.salary.component.WeaFormOption;
import com.engine.salary.component.WeaTableColumnGroup;
import com.engine.salary.config.SalaryElogConfig;
import com.engine.salary.entity.salaryitem.po.SalaryItemPO;
import com.engine.salary.enums.OperateTypeEnum;
import com.engine.salary.enums.salaryitem.SalaryDataTypeEnum;
import com.engine.salary.exception.SalaryRunTimeException;
import com.engine.salary.report.common.constant.SalaryConstant;
import com.engine.salary.report.entity.bo.SalaryStatisticsReportBO;
import com.engine.salary.report.entity.param.*;
import com.engine.salary.report.entity.po.SalaryStatisticsDimensionPO;
import com.engine.salary.report.entity.po.SalaryStatisticsItemPO;
import com.engine.salary.report.entity.po.SalaryStatisticsPushPO;
import com.engine.salary.report.entity.po.SalaryStatisticsReportPO;
import com.engine.salary.report.service.*;
import com.engine.salary.report.service.impl.*;
import com.engine.salary.service.*;
import com.engine.salary.service.impl.*;
import com.engine.salary.util.*;
import com.engine.salary.util.excel.ExcelUtilPlus;
import com.engine.salary.util.page.PageInfo;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import weaver.general.PageIdConst;
import weaver.hrm.User;
import weaver.wechat.util.Utils;

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


/**
 * 薪酬统计维度
 * <p>Copyright: Copyright (c) 2022</p>
 * <p>Company: 泛微软件</p>
 *
 * @author qiantao
 * @version 1.0
 **/
public class SalaryStatisticsReportWrapper extends Service {

    private static final String conditionId = "salaryStatisticsReportSearchCondition";

    private SalaryStatisticsReportService getSalaryStatisticsReportService(User user) {
        return ServiceUtil.getService(SalaryStatisticsReportServiceImpl.class, user);
    }

    private SalaryStatisticsItemService getSalaryStatisticsItemService(User user) {
        return ServiceUtil.getService(SalaryStatisticsItemServiceImpl.class, user);
    }

    private SalaryStatisticsDimensionService getSalaryStatisticsDimensionService(User user) {
        return ServiceUtil.getService(SalaryStatisticsDimensionServiceImpl.class, user);
    }

    private SubTableExportService getSubTableExportService(User user) {
        return ServiceUtil.getService(SubTableExportServiceImpl.class, user);
    }

    private SalaryAcctEmployeeService getSalaryAcctEmployeeService(User user) {
        return ServiceUtil.getService(SalaryAcctEmployeeServiceImpl.class, user);
    }

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

    private SalaryItemService getSalaryItemService(User user) {
        return ServiceUtil.getService(SalaryItemServiceImpl.class, user);
    }

    private SalaryCacheService getSalaryCacheService(User user) {
        return ServiceUtil.getService(SalaryCacheServiceImpl.class, user);
    }

    private SalaryStatisticsPushService getSalaryStatisticsPushService(User user) {
        return ServiceUtil.getService(SalaryStatisticsPushServiceImpl.class, user);
    }

    private SalaryStatisticsPushDetailService getSalaryStatisticsPushDetailService(User user) {
        return ServiceUtil.getService(SalaryStatisticsPushDetailServiceImpl.class, user);
    }

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


    /**
     * 报表列表
     *
     * @param queryParam
     * @return
     */
    public List<Map<String, Object>> list(SalaryStatisticsReportQueryParam queryParam) {
        Long uid = Long.valueOf(user.getUID());
        // 初始化
        getSalaryStatisticsDimensionService(user).init(uid);

        // 所有人能够看到自己创建的报表,薪酬总管理员能够查看所有报表
        List<SalaryStatisticsReportPO> reportList = getSalaryStatisticsReportService(user).listByCreator(uid);
        List<Long> reportIds = reportList.stream().map(SalaryStatisticsReportPO::getId).collect(Collectors.toList());
        // 获取所有没有撤回没有过期的报表ID（不包含过期失效的）
        List<SalaryStatisticsPushPO> pushList = getSalaryStatisticsPushService(user).getSuccessPushListByReceiver(uid);
        List<Long> sharedReportIds = pushList.stream().map(po -> Arrays.asList(StringUtils.split(po.getReportIds(), ",")))
                .flatMap(Collection::stream).distinct().map(Long::valueOf).collect(Collectors.toList());
        sharedReportIds = sharedReportIds.stream().filter(id -> !reportIds.contains(id)).collect(Collectors.toList());
        reportList.addAll(getSalaryStatisticsReportService(user).getByIds(sharedReportIds));

        if (StringUtils.isNotEmpty(queryParam.getReportName())) {
            reportList = reportList.stream().filter(rp -> rp.getReportName().contains(queryParam.getReportName())).collect(Collectors.toList());
        }
        List<SalaryStatisticsDimensionPO> salaryStatisticsDimensionList = this.getSalaryStatisticsDimensionService(user).listAll();
        Map<String, String> salaryStatisticsDimensionMap = SalaryEntityUtil.convert2Map(salaryStatisticsDimensionList, k -> k.getId().toString(), SalaryStatisticsDimensionPO::getDimName);
        List<Map<String, Object>> result = new ArrayList<>();
        List<Long> finalSharedReportIds = sharedReportIds;
        reportList.forEach(po -> {
            Map<String, Object> temp = new HashMap<>();
            temp.put("id", po.getId().toString());
            temp.put("reportName", po.getReportName());
            temp.put("timeType", po.getTimeType() == null ? 10 : po.getTimeType());
            temp.put("salaryStartMonth", SalaryDateUtil.getFormatYearMonth(po.getSalaryStartMonth()));
            temp.put("salaryEndMonth", SalaryDateUtil.getFormatYearMonth(po.getSalaryEndMonth()));
            List<String> dimNames = Arrays.stream(po.getDimension().split(",")).map(dim -> Optional.ofNullable(salaryStatisticsDimensionMap.get(dim)).orElse("")).collect(Collectors.toList());
            temp.put("dimension", StringUtils.join(dimNames, ","));
            temp.put("dimensionId", po.getDimension());
            temp.put("isShare", finalSharedReportIds.contains(po.getId()));
            result.add(temp);
        });
        return result;
    }

    /**
     * 获取薪酬统计报表表单
     *
     * @param id
     * @param
     * @return
     */
    public Map<String, Object> getFrom(Long id) {

        List<SalaryStatisticsDimensionPO> salaryStatisticsDimensions = getSalaryStatisticsDimensionService(user).listAll();

        List<WeaFormOption> statsDimOptions = salaryStatisticsDimensions.stream().map(sd -> new WeaFormOption(sd.getId().toString(), sd.getDimName())).collect(Collectors.toList());

        // 获取默认维度统计
        List<SalaryStatisticsDimensionPO> defaultSalaryStatisticsDimensions = getSalaryStatisticsDimensionService(user).listAllDefaultDimension();
        List<Long> defaultDimensionIds = defaultSalaryStatisticsDimensions.stream().map(SalaryStatisticsDimensionPO::getId).collect(Collectors.toList());
        // 获取有薪资统计报表引用的统计维度
        Set<String> haveUsedDimIds = new HashSet<>();
        List<SalaryStatisticsReportPO> salaryStatisticsReports = getSalaryStatisticsReportService(user).listAll();
        salaryStatisticsReports.stream().forEach(report -> Collections.addAll(haveUsedDimIds, report.getDimension().split(",")));
        statsDimOptions.stream().forEach(option -> {
            if (defaultDimensionIds.contains(Long.valueOf(option.getId()))) {
                // 默认维度不允许修改、删除
                option.setCanDelete(false);
                option.setCanEdit(false);
            } else if (haveUsedDimIds.contains(option.getId())) {
                // 被薪资统计报表引用的不能删除
                option.setCanEdit(true);
                option.setCanDelete(false);
            }
        });

        // 1.构建基础信息表单
        Map<String, Object> weaForm = new HashMap<>();
        weaForm.put("statsDimOptions", statsDimOptions);


        if (id != null) {
            SalaryStatisticsReportPO po = this.getSalaryStatisticsReportService(user).getById(id);
            if (po == null) {
                throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(161845, "薪酬统计报表不存在"));
            }
            Map<String, Object> dataMap = JsonUtil.parseMap(po, Object.class);
            dataMap.put("dimension", Arrays.asList(po.getDimension().split(",")));
            weaForm.put("data", dataMap);
        }

        return weaForm;
    }

    /**
     * 保存薪酬统计报表
     *
     * @param saveParam
     * @param
     * @return
     */
    public String save(SalaryStatisticsReportSaveParam saveParam) {
        return getSalaryStatisticsReportService(user).save(saveParam);
    }

    /**
     * 删除薪酬统计报表
     *
     * @param ids
     * @param
     * @return
     */
    public Map<String, Object> delete(Collection<Long> ids) {
        return getSalaryStatisticsReportService(user).delete(ids);
    }

    /**
     * 复制薪资账套
     *
     * @param id
     */
    public void duplicate(Long id) {
        if (id == null) {
            throw new SalaryRunTimeException("id为空");
        }
        getSalaryStatisticsReportService(user).duplicate(id);
    }

    /**
     * 获取统计条件
     *
     * @param id
     * @return
     */
    public Map<String, Object> getSearchCondition(Long id) {
        // 高级搜索实例
        Map<String, Object> map = new HashMap<>();

        if (id != null) {
            SalaryStatisticsReportPO po = getSalaryStatisticsReportService(user).getById(id);
            SalaryAssert.notNull(po, SalaryI18nUtil.getI18nLabel(152563, "报表不存在"));

            Map<String, Object> data = new HashMap<>();
            data.put("timeType", po.getTimeType() == null ? 10 : po.getTimeType());
            data.put("salaryStartMonth", SalaryDateUtil.getFormatYearMonth(po.getSalaryStartMonth()));
            data.put("salaryEndMonth", SalaryDateUtil.getFormatYearMonth(po.getSalaryEndMonth()));
            data.put("taxAgent", JSONArray.parseArray(po.getTaxAgentSetting()));
            data.put("salarySob", JSONArray.parseArray(po.getSalarySobSetting()));
            data.put("incomeCategory", JSONArray.parseArray(po.getIncomeCategorySetting()));
            data.put("subCompany", JSONArray.parseArray(po.getSubCompanySetting()));
            data.put("department", JSONArray.parseArray(po.getDepartSetting()));
            data.put("grade", JSONArray.parseArray(po.getGradeSetting()));
            data.put("position", JSONArray.parseArray(po.getPositionSetting()));
            data.put("status", JSONArray.parseArray(po.getStatusSetting()));
            data.put("employee", JSONArray.parseArray(po.getEmployeeSetting()));
            data.put("hiredate", JSONArray.parseArray(po.getHiredateSetting()));
//            data.put("leavedate", JSONArray.parseArray(po.getLeavedateSetting()));

            map.put("data", data);
        }

        return map;
    }


    public String saveSearchCondition(SalaryStatisticsSearchConditionSaveParam param) {
        return this.getSalaryStatisticsReportService(user).saveSearchCondition(param);
    }

    /**
     * 获取报表数据
     *
     * @param param
     * @return
     */
    public Map<String, Object> getData(SalaryStatisticsReportDataQueryParam param) {
        Long id = param.getId();
        if (id == null || param.getDimensionId() == null) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(84026, "参数错误"));
        }
        SalaryStatisticsDimensionPO dimension = getSalaryStatisticsDimensionService(user).getById(param.getDimensionId());
        if (dimension == null) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(161300, "统计维度不存在"));
        }
        // 查询报表配置
        SalaryStatisticsReportPO po = this.getSalaryStatisticsReportService(user).getById(id);
        if (po == null) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(161845, "薪酬统计报表不存在"));
        }
        if (param.isShare()) {
            // 是被分享的报表
            Long uid = Long.valueOf(user.getUID());
            // 校验查看权限，获取有效的分享记录
            List<SalaryStatisticsPushPO> pushList = getSalaryStatisticsPushService(user).shareReportValid(param.getId(), uid);
            List<Long> batchIds = pushList.stream().map(SalaryStatisticsPushPO::getId).collect(Collectors.toList());
            getSalaryStatisticsPushService(user).updateReportViewStatus(batchIds, uid);
//            salaryStatisticsPushService.sendViewedMsg(param.getBatchId(), param.getId(), employeeId, tenantKey);
            // 如果是被分享的报表，校验分享权限，通过后将user赋值为报表创建人
            User creator = new User();
            creator.setUid(po.getCreator().intValue());
            user = creator;
        } else {
            // 判断报表是否是登陆人创建的,或薪酬总管理员
            Boolean needAuth = getTaxAgentService(user).isNeedAuth((long) user.getUID());
            if (needAuth && NumberUtils.compare(po.getCreator().intValue(), user.getUID()) != 0) {
                throw new SalaryRunTimeException("无权限查看该报表！");
            }
        }

        // weaTable对象
        Map<String, Object> weaTable = new HashMap<>();

        // 查询自定义统计项目
        List<SalaryStatisticsItemPO> salaryStatisticsItemList = this.getSalaryStatisticsItemService(user).listByStatisticsReportId(po.getId());

        // 参数转换
        SalaryStatisticsReportBO.poToQueryParam(param, po);
        String paramMd5 = SecureUtil.md5(param + salaryStatisticsItemList.toString());

        //已缓存的报表id
        String salaryReportIds = Utils.null2String(getSalaryCacheService(user).get(SalaryCacheKey.SALARY_REPORT_IDS));
        String salaryReportConditions = "";
        if (StringUtils.isNotBlank(salaryReportIds) && salaryReportIds.contains(id + "")) {
            //报表中缓存的条件
            salaryReportConditions = Utils.null2String(getSalaryCacheService(user).get(SalaryCacheKey.SALARY_REPORT_CONDITIONS + id));
            if (StringUtils.isNotBlank(salaryReportConditions) && salaryReportConditions.contains(paramMd5)) {
                return getSalaryCacheService(user).get(SalaryCacheKey.SALARY_REPORT_DATA + id + "_" + paramMd5);
            }
        }


        // 列表data
        PageInfo<Map<String, Object>> page = this.getSalaryStatisticsReportService(user).buildReportRecords(dimension, param, salaryStatisticsItemList);

        // 组装合计
        Map<String, Object> countResultMap = SalaryStatisticsReportBO.buildTotal(page, salaryStatisticsItemList, (long) user.getUID());

        // 列表columns
        List<WeaTableColumnGroup> weaTableColumns = SalaryStatisticsReportBO.buildReportColumns(dimension, salaryStatisticsItemList);

        Map<String, Object> resultMap = Maps.newHashMap();
        resultMap.putAll(JsonUtil.parseMap(weaTable, Object.class));
        resultMap.put("columns", weaTableColumns);
        resultMap.put("pageInfo", page);
        resultMap.put("countResult", countResultMap);
        resultMap.put("reportId", id);


        //设置报表缓存
        getSalaryCacheService(user).set(SalaryCacheKey.SALARY_REPORT_IDS, salaryReportIds + "," + id);
        getSalaryCacheService(user).set(SalaryCacheKey.SALARY_REPORT_CONDITIONS + id, salaryReportConditions + "," + paramMd5);
        getSalaryCacheService(user).set(SalaryCacheKey.SALARY_REPORT_DATA + id + "_" + paramMd5, resultMap);


        return resultMap;
    }


    /**
     * 导出报表数据
     *
     * @param param
     * @return
     */
    public Map<String, Object> exportData(SalaryStatisticsReportDataQueryParam param) {
        if (param.getId() == null || param.getDimensionId() == null) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(84026, "参数错误"));
        }

        SalaryStatisticsReportPO po = this.getSalaryStatisticsReportService(user).getById(param.getId());
        if (po == null) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(161845, "薪酬统计报表不存在"));
        }
        SalaryStatisticsDimensionPO dimension = getSalaryStatisticsDimensionService(user).getById(param.getDimensionId());
        if (dimension == null) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(161300, "统计维度不存在"));
        }
        sharedReportCheck(param.isShare(), po);
        // 参数转换
        SalaryStatisticsReportBO.poToQueryParam(param, po);

        // 查询自定义统计项目
        List<SalaryStatisticsItemPO> salaryStatisticsItemList = this.getSalaryStatisticsItemService(user).listByStatisticsReportId(po.getId());
        // 列表data
        PageInfo<Map<String, Object>> page = this.getSalaryStatisticsReportService(user).buildReportRecords(dimension, param, salaryStatisticsItemList);
        // 组装合计
        Map<String, Object> countResultMap = SalaryStatisticsReportBO.buildTotal(page, salaryStatisticsItemList, (long) user.getUID());
        List<Map<String, Object>> list = page.getList();
        if (CollectionUtils.isNotEmpty(list) && MapUtils.isNotEmpty(countResultMap)) {
            list.add(countResultMap);
        }
        // 获取数据
        List<Map<String, String>> records = list.stream().map(m -> m.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue() + StringUtils.EMPTY))).collect(Collectors.toList());

        // 获取列头
        List<WeaTableColumnGroup> weaTableColumns = SalaryStatisticsReportBO.buildReportColumns(dimension, salaryStatisticsItemList);

        // 组装导出参数
//        ExportCommonParam exportParam = SalaryStatisticsReportBO.buildExportParam(dimension.getDimName(), weaTableColumns, records);
//        exportParam.setSheetName(SalaryI18nUtil.getI18nLabel(179263, "薪酬统计报表") + "-" + exportParam.getDimensionName());
//

        List rows = new ArrayList<>();
        rows.add(weaTableColumns);

        List<String> head = new ArrayList<>();
        weaTableColumns.forEach(weaTableColumn -> {
            String column = weaTableColumn.getColumn();
            if (CollectionUtils.isEmpty(weaTableColumn.getChildren())) {
                head.add(column);
            } else {
                weaTableColumn.getChildren().forEach(children -> {
                    head.add(children.getColumn());
                });
            }
        });

        for (Map<String, String> map : records) {
            List<Object> row = Lists.newArrayListWithExpectedSize(records.size());
            head.forEach(k -> {
                row.add(map.getOrDefault(k, StringUtils.EMPTY));
            });
            rows.add(row);
        }

        String sheetName = SalaryI18nUtil.getI18nLabel(179263, "薪酬统计报表") + "-" + dimension.getDimName();
        XSSFWorkbook book = ExcelUtilPlus.genWorkbookWithChildTitleColumn(rows, sheetName, true);

        Map<String, Object> map = new HashMap<>();
        map.put("workbook", book);
        map.put("fileName", sheetName);

        // 记录操作日志
        String name = SalaryI18nUtil.getI18nLabel(0, "导出");
        LoggerContext loggerContext = new LoggerContext<>();
        loggerContext.setTargetId(po.getId().toString());
        loggerContext.setTargetName(po.getReportName());
        loggerContext.setOperateType(OperateTypeEnum.EXCEL_EXPORT.getValue());
        loggerContext.setOperateTypeName(name);
        loggerContext.setOperatedesc(name + SalaryI18nUtil.getI18nLabel(0, "薪酬统计报表") + "-" + po.getReportName());
        loggerContext.setUser(user);
        SalaryElogConfig.salaryStatReportLoggerTemplate.write(loggerContext);

        return map;
    }

    /**
     * 获取报表透视数据
     *
     * @param param
     * @return
     */
    public Map<String, Object> getDataPerspective(SalaryStatisticsDataPerspectiveQueryParam param) {
        if (param.getId() == null || param.getDimensionId() == null) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(84026, "参数错误"));
        }
        SalaryStatisticsReportPO po = this.getSalaryStatisticsReportService(user).getById(param.getId());
        if (po == null) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(161845, "薪酬统计报表不存在"));
        }
        SalaryStatisticsDimensionPO dimension = getSalaryStatisticsDimensionService(user).getById(param.getDimensionId());
        if (dimension == null) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(161300, "统计维度不存在"));
        }
        // 校验报表权限，如果是被分享报表修改User
        sharedReportCheck(param.isShare(), po);
        // 查询自定义统计项目中所有薪资项目id
        List<SalaryStatisticsItemPO> salaryStatisticsItemPOS = getSalaryStatisticsItemService(user).listByStatisticsReportId(param.getId());
        List<Long> salaryItemIds = salaryStatisticsItemPOS.stream().filter(item -> StringUtils.isNotBlank(item.getItemValue())).map(p -> p.getItemValue().split(","))
                .flatMap(Arrays::stream).map(Long::valueOf).collect(Collectors.toList());

        PageInfo<Map<String, Object>> pageInfo = getSalaryStatisticsReportService(user).buildDataPerspectiveRecords(param, po, dimension, salaryStatisticsItemPOS);

        List<SalaryItemPO> itemList = getSalaryItemService(user).listByIds(salaryItemIds);
        // 列表columns
        List<WeaTableColumn> weaTableColumns = buildDataPerspectiveTableColumns(itemList, salaryItemIds);

        WeaTable table = new WeaTable();
        String pageId = "a4f85an7-9576-4125-adn9-7d06e7sy69f2";
        table.setPageID(pageId);
        table.setPageUID(pageId + user.getUID());
        table.setPagesize(PageIdConst.getPageSize(pageId, user.getUID()));
        table.setBackfields("");

        table.setColumns(weaTableColumns);

        WeaResultMsg result = new WeaResultMsg(false);
        result.putAll(table.makeDataResult());
        result.success();

        // 结果
        Map<String, Object> resultMap = Maps.newHashMap();
        resultMap.put("dataKey", result.getResultMap());
        resultMap.put("pageInfo", pageInfo);
        return resultMap;
    }

    /**
     * 获取报表透视数据
     *
     * @param param
     * @return
     */
    public Map<String, Object> exportDataPerspective(SalaryStatisticsDataPerspectiveQueryParam param) {
        if (param.getId() == null || param.getDimensionId() == null) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(84026, "参数错误"));
        }
        SalaryStatisticsReportPO po = this.getSalaryStatisticsReportService(user).getById(param.getId());
        if (po == null) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(161845, "薪酬统计报表不存在"));
        }
        SalaryStatisticsDimensionPO dimension = getSalaryStatisticsDimensionService(user).getById(param.getDimensionId());
        if (dimension == null) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(161300, "统计维度不存在"));
        }
        // 校验报表权限，如果是被分享报表修改User
        sharedReportCheck(param.isShare(), po);
        // 查询自定义统计项目中所有薪资项目id
        List<SalaryStatisticsItemPO> salaryStatisticsItemPOS = getSalaryStatisticsItemService(user).listByStatisticsReportId(param.getId());
        List<Long> salaryItemIds = salaryStatisticsItemPOS.stream().filter(item -> StringUtils.isNotBlank(item.getItemValue())).map(p -> p.getItemValue().split(","))
                .flatMap(Arrays::stream).map(Long::valueOf).collect(Collectors.toList());

        param.setCurrent(1);
        param.setPageSize(1000000000);
        PageInfo<Map<String, Object>> pageInfo = getSalaryStatisticsReportService(user).buildDataPerspectiveRecords(param, po, dimension, salaryStatisticsItemPOS);


        List<List<Object>> resultList = new ArrayList<>();

        List<SalaryItemPO> itemList = getSalaryItemService(user).listByIds(salaryItemIds);
        // 表格表头
        List<WeaTableColumn> weaTableColumns = buildDataPerspectiveTableColumns(itemList, salaryItemIds);
        List<Object> columns = new ArrayList<>();
        for (WeaTableColumn column : weaTableColumns) {
            columns.add(column.getText());
        }
        resultList.add(columns);

        List<Map<String, Object>> list = pageInfo.getList();
        for (Map<String, Object> resultMap : list) {
            List<Object> row = new ArrayList<>();
            for (WeaTableColumn column : weaTableColumns) {
                try {
                    if (StringUtils.isNotBlank(column.getOtherpara()) && column.getOtherpara().equals(SalaryDataTypeEnum.NUMBER.getValue())) {
                        // 数值
                        row.add(new BigDecimal(resultMap.get(column.getColumn()).toString()));
                    } else {
                        row.add(Utils.null2String(resultMap.get(column.getColumn())));
                    }
                } catch (Exception e) {
                    row.add(Utils.null2String(resultMap.get(column.getColumn())));
                }
            }
            resultList.add(row);
        }

        String sheetName = SalaryI18nUtil.getI18nLabel(179263, "薪酬统计报表明细") + "-" + dimension.getDimName();
        XSSFWorkbook book = ExcelUtilPlus.genWorkbookV2(resultList, sheetName);

        Map<String, Object> map = new HashMap<>();
        map.put("workbook", book);
        map.put("fileName", sheetName);
        return map;
    }

    /**
     * 权限校验
     *
     * @param isShared 是否是被分享的报表
     * @param po       报表po
     */
    private void sharedReportCheck(boolean isShared, SalaryStatisticsReportPO po) {
        if (isShared) {
            // 是被分享的报表
            Long uid = Long.valueOf(user.getUID());
            // 校验分享查看权限
            getSalaryStatisticsPushService(user).shareReportValid(po.getId(), uid);
            // 如果是被分享的报表，校验分享权限，通过后将user赋值为报表创建人
            User creator = new User();
            creator.setUid(po.getCreator().intValue());
            user = creator;
        } else {
            // 判断报表是否是登陆人创建的,或薪酬总管理员
            Boolean needAuth = getTaxAgentService(user).isNeedAuth((long) user.getUID());
            if (needAuth && NumberUtils.compare(po.getCreator().intValue(), user.getUID()) != 0) {
                throw new SalaryRunTimeException("无权限查看该报表！");
            }
        }
    }

    private List<WeaTableColumn> buildDataPerspectiveTableColumns(List<SalaryItemPO> salaryItems, List<Long> salaryItemIds) {
        Map<Long, SalaryItemPO> salaryItemMap = SalaryEntityUtil.convert2Map(salaryItems, SalaryItemPO::getId);
        // 表格表头
        List<WeaTableColumn> columns = new ArrayList<>();
        columns.add(new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(87614, "姓名"), "userName"));
        columns.add(new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(87614, "部门"), "departmentName"));
        columns.add(new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(87614, "薪资所属月"), "salaryMonth"));
        columns.add(new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(86184, "个税扣缴义务人"), "taxAgent"));
        columns.add(new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(86184, "账套"), "salarySob"));
//        columns.add(new WeaTableColumn("100px", SalaryI18nUtil.getI18nLabel(86184, "次数"), "acctTimes").setDisplay(WeaBoolAttr.FALSE));
        salaryItemIds.forEach(itemId -> {
            SalaryItemPO item = salaryItemMap.get(itemId);
            if (item != null) {
                WeaTableColumn weaTableColumn = new WeaTableColumn("100px", item.getName(), item.getId() + SalaryConstant.DYNAMIC_SUFFIX);
                weaTableColumn.setOtherpara(item.getDataType());
                columns.add(weaTableColumn);
            }
        });
        return columns;
    }
}
