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

import com.engine.salary.constant.SalaryDefaultTenantConstant;
import com.engine.salary.entity.salaryitem.po.SalaryItemPO;
import com.engine.salary.entity.salarysob.po.*;
import com.engine.salary.enums.sicategory.DeleteTypeEnum;
import com.engine.salary.util.SalaryEntityUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.engine.salary.util.db.IdGenerator;
import lombok.Data;
import lombok.experimental.Accessors;
import org.apache.commons.lang3.math.NumberUtils;

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

/**
 * 薪资账套薪资项目
 * <p>Copyright: Copyright (c) 2022</p>
 * <p>Company: 泛微软件</p>
 *
 * @author qiantao
 * @version 1.0
 **/
public class SalarySobItemBO {

    /**
     * 默认包含的员工信息字段转换成薪资账套员工信息字段po
     *
     * @param salarySobId         薪资账套id
     * @param defaultEmpFieldList 默认包含的员工信息字段
     * @param employeeId          当前登陆人员id
     * @return
     */
    public static List<SalarySobEmpFieldPO> convert2EmpFieldPO(Long salarySobId, List<SalarySobDefaultEmpFieldPO> defaultEmpFieldList, Long employeeId) {
        Date now = new Date();
        return defaultEmpFieldList.stream()
                .map(field -> new SalarySobEmpFieldPO()
                        .setSalarySobId(salarySobId)
                        .setFieldCode(field.getFieldCode())
                        .setSortedIndex(field.getSortedIndex())
                        .setCanDelete(field.getCanDelete())
                        .setCreator(employeeId)
                        .setCreateTime(now)
                        .setUpdateTime(now)
                        .setDeleteType(0)
                        .setTenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY))
                .collect(Collectors.toList());
    }

    /**
     * 转换成薪资账套的薪资项目副本po
     *
     * @param salarySobId
     * @param salarySobDefaultItemGroupPOS
     * @param salarySobDefaultItemPOS
     * @param defaultSalaryItemPOS
     * @param employeeId
     * @param tenantKey
     * @return
     */
    public static Result initSalarySobItem(Long salarySobId,
                                           List<SalarySobDefaultItemGroupPO> salarySobDefaultItemGroupPOS,
                                           List<SalarySobDefaultItemPO> salarySobDefaultItemPOS,
                                           List<SalaryItemPO> defaultSalaryItemPOS,
                                           Long employeeId, String tenantKey) {
        Date now = new Date();
        // 需要保存的隐藏项目
        List<SalarySobItemHidePO> needInsertItemHides = new ArrayList<>();
        // 处理薪资账套默认的薪资项目分类
        Map<Long, Long> salarySobItemGroupIdMap = Maps.newHashMapWithExpectedSize(salarySobDefaultItemGroupPOS.size());
        List<SalarySobItemGroupPO> salarySobItemGroups = Lists.newArrayListWithExpectedSize(salarySobDefaultItemGroupPOS.size());
        for (SalarySobDefaultItemGroupPO salarySobDefaultItemGroupPO : salarySobDefaultItemGroupPOS) {
            long salarySobItemGroupId = IdGenerator.generate();
            salarySobItemGroups.add(SalarySobItemGroupPO.builder()
                    .id(salarySobItemGroupId)
                    .name(salarySobDefaultItemGroupPO.getName())
                    .salarySobId(salarySobId)
                    .sortedIndex(salarySobDefaultItemGroupPO.getSortedIndex())
                    .description(salarySobDefaultItemGroupPO.getDescription())
                    .creator(employeeId)
                    .createTime(now)
                    .updateTime(now)
                    .tenantKey(tenantKey)
                    .deleteType(NumberUtils.INTEGER_ZERO)
                    .build());
            salarySobItemGroupIdMap.put(salarySobDefaultItemGroupPO.getId(), salarySobItemGroupId);

            // 保存薪资项目分类隐藏信息
            needInsertItemHides.add(SalarySobItemHidePO.builder()
                    .id(IdGenerator.generate())
                    .salarySobId(salarySobId)
                    .salaryItemId(salarySobItemGroupId)
                    .isGroup(1)
                    .itemHide(0L)
                    .creator(employeeId)
                    .createTime(now)
                    .updateTime(now)
                    .deleteType(NumberUtils.INTEGER_ZERO)
                    .tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY)
                    .build());
        }


        List<SalarySobItemPO> salarySobItems = Lists.newArrayListWithExpectedSize(defaultSalaryItemPOS.size());
        // 处理薪资账套默认的系统薪资项目
        Set<Long> sysSalaryItemIds = SalaryEntityUtil.properties(salarySobDefaultItemPOS, SalarySobDefaultItemPO::getSysSalaryItemId);
        Map<Long, SalaryItemPO> salaryItemPOMap = defaultSalaryItemPOS.stream()
                .filter(salaryItemPO -> sysSalaryItemIds.contains(salaryItemPO.getSysSalaryItemId()))
                .collect(Collectors.toMap(SalaryItemPO::getSysSalaryItemId, Function.identity(), (a, b) -> a));
        for (SalarySobDefaultItemPO salarySobDefaultItemPO : salarySobDefaultItemPOS) {
            SalaryItemPO salaryItemPO = salaryItemPOMap.get(salarySobDefaultItemPO.getSysSalaryItemId());
            if (salaryItemPO==null)continue;
            salarySobItems.add(SalarySobItemPO.builder()
                    .salarySobId(salarySobId)
                    .salarySobItemGroupId(salarySobItemGroupIdMap.getOrDefault(salarySobDefaultItemPO.getSobDefaultItemGroupId(), NumberUtils.LONG_ZERO))
                    .salaryItemId(salaryItemPO.getId())
                    .formulaId(salaryItemPO.getFormulaId())
                    .sortedIndex(salarySobDefaultItemPO.getSortedIndex())
                    .description(salaryItemPO.getDescription())
                    .canDelete(salarySobDefaultItemPO.getCanDelete())
                    .creator(employeeId)
                    .createTime(now)
                    .updateTime(now)
                    .tenantKey(tenantKey)
                    .deleteType(NumberUtils.INTEGER_ZERO)
                    .build());

            // 保存薪资项目隐藏信息
            needInsertItemHides.add(SalarySobItemHidePO.builder()
                    .id(IdGenerator.generate())
                    .salarySobId(salarySobId)
                    .salaryItemId(salaryItemPO.getId())
                    .isGroup(0)
                    .itemHide(Long.valueOf(salaryItemPO.getHideDefault()== null ? 0 : salaryItemPO.getHideDefault()))
                    .creator(employeeId)
                    .createTime(now)
                    .updateTime(now)
                    .deleteType(NumberUtils.INTEGER_ZERO)
                    .tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY)
                    .build());
        }
        // 处理薪资账套默认的自定义薪资项目（开启了"默认使用"）
        for (int i = 0; i < defaultSalaryItemPOS.size(); i++) {
            SalaryItemPO salaryItemPO = defaultSalaryItemPOS.get(i);
            if (sysSalaryItemIds.contains(salaryItemPO.getSysSalaryItemId())) {
                continue;
            }
            // 获取系统默认回算薪资项目的系统id
            List<Long> backItemSysItemIds = SalarySobBackItemBO.getDefault().stream().map(SalarySobDefaultBackItemPO::getSysSalaryItemId).collect(Collectors.toList());
            if (backItemSysItemIds.contains(salaryItemPO.getSysSalaryItemId())) {
                continue;
            }
            salarySobItems.add(SalarySobItemPO.builder()
                    .salarySobId(salarySobId)
                    .salarySobItemGroupId(NumberUtils.LONG_ZERO)
                    .salaryItemId(salaryItemPO.getId())
                    .formulaId(salaryItemPO.getFormulaId())
                    .sortedIndex(i)
                    .description(salaryItemPO.getDescription())
                    .canDelete(NumberUtils.INTEGER_ONE)
                    .creator(employeeId)
                    .createTime(now)
                    .updateTime(now)
                    .tenantKey(tenantKey)
                    .deleteType(NumberUtils.INTEGER_ZERO)
                    .build());
            // 保存薪资项目隐藏信息
            needInsertItemHides.add(SalarySobItemHidePO.builder()
                    .id(IdGenerator.generate())
                    .salarySobId(salarySobId)
                    .salaryItemId(salaryItemPO.getId())
                    .isGroup(0)
                    .itemHide(Long.valueOf(salaryItemPO.getHideDefault() == null ? 0 : salaryItemPO.getHideDefault()))
                    .creator(employeeId)
                    .createTime(now)
                    .updateTime(now)
                    .deleteType(NumberUtils.INTEGER_ZERO)
                    .tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY)
                    .build());
        }

        // 薪资账套默认的回算薪资项目
        List<SalarySobBackItemPO> salarySobBackItems = Lists.newArrayListWithExpectedSize(2);
        for (SalarySobDefaultBackItemPO salarySobDefaultBackItemPO : SalarySobBackItemBO.getDefault()) {
            Map<Long, SalaryItemPO> sysSalaryItemMap = SalaryEntityUtil.convert2Map(defaultSalaryItemPOS, SalaryItemPO::getSysSalaryItemId);
            SalaryItemPO salaryItemPO = sysSalaryItemMap.get(salarySobDefaultBackItemPO.getSysSalaryItemId());
            SalarySobBackItemPO salarySobBackItemPO = SalarySobBackItemPO.builder()
                    .id(IdGenerator.generate())
                    .salarySobId(salarySobId)
                    .salaryItemId(salaryItemPO.getId())
                    .salaryItemCode(salaryItemPO.getCode())
                    .dataType(salaryItemPO.getDataType())
                    .roundingMode(salaryItemPO.getRoundingMode())
                    .pattern(salaryItemPO.getPattern())
                    .valueType(salaryItemPO.getValueType())
                    .formulaId(salarySobDefaultBackItemPO.getFormulaId())
                    .backCalcType(salarySobDefaultBackItemPO.getBackCalcType())
                    .creator(employeeId)
                    .createTime(now)
                    .updateTime(now)
                    .deleteType(DeleteTypeEnum.NOT_DELETED.getValue())
                    .tenantKey(tenantKey).build();
            salarySobBackItems.add(salarySobBackItemPO);
        }

        return new Result().setNeedInsertSalarySobItems(salarySobItems).setNeedInsertSalarySobItemGroups(salarySobItemGroups)
                .setNeedInsertSalarySobBackItems(salarySobBackItems).setNeedInsertItemHides(needInsertItemHides);
    }

    @Data
    @Accessors(chain = true)
    public static class Result {

        /**
         * 需要保存的薪资项目
         */
        List<SalarySobItemPO> needInsertSalarySobItems;

        /**
         * 需要保存的薪资项目分类
         */
        List<SalarySobItemGroupPO> needInsertSalarySobItemGroups;

        /**
         * 需要保存的回算薪资项目
         */
        List<SalarySobBackItemPO> needInsertSalarySobBackItems;

        /**
         * 需要保存的薪资项目隐藏信息
         */
        List<SalarySobItemHidePO> needInsertItemHides;
    }
}
