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

import com.engine.salary.constant.SalaryDefaultTenantConstant;
import com.engine.salary.entity.salarysob.po.*;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.engine.salary.util.db.IdGenerator;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.math.NumberUtils;

import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

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

    /**
     * 薪资账套
     */
    private SalarySobPO salarySob;

    /**
     * 薪资账套的员工信息字段
     */
    private List<SalarySobEmpFieldPO> salarySobEmpFields;

    /**
     * 薪资账套的薪资项目副本
     */
    private List<SalarySobItemPO> salarySobItems;

    /**
     * 薪资账套的薪资项目分类
     */
    private List<SalarySobItemGroupPO> salarySobItemGroups;

    /**
     * 薪资账套的调薪计薪规则
     */
    private List<SalarySobAdjustRulePO> salaryAdjustmentRules;

    /**
     * 薪资账套的校验规则
     */
    private List<SalarySobCheckRulePO> salarySobCheckRules;

    /**
     * 薪资账套的回算薪资项目
     */
    List<SalarySobBackItemPO> salarySobBackItemPOS;

    /**
     * 复制
     *
     * @param employeeId
     * @return
     */
    public Result duplicate( Long employeeId) {
        Result result = new Result();
        // 复制基础设置
        duplicateBase(result, salarySob, employeeId);
        // 复制员工信息字段
        duplicateEmpField(result, salarySobEmpFields, employeeId);
        // 复制薪资项目分类
        Map<Long, Long> groupIdMap = duplicateSalarySobItemGroup(result, salarySobItemGroups, employeeId);
        // 复制薪资项目副本
        duplicateSalarySobItem(result, salarySobItems, groupIdMap, employeeId);
        // 复制调薪计薪规则
        duplicateSalaryAdjustmentRule(result, salaryAdjustmentRules, employeeId);
        // 复制校验规则
        duplicateSalarySobCheckRule(result, salarySobCheckRules, employeeId);
        duplicateEmpField(result, salarySobEmpFields, employeeId);
        // 复制回算薪资项目
        duplicateSalarySobBackItem(result, salarySobBackItemPOS, employeeId);
        return result;
    }


    /**
     * 复制薪资账套的基础设置
     *
     * @param salarySobPO 薪资账套po
     * @param employeeId  人员id
     
     * @return
     */
    private void duplicateBase(Result result, SalarySobPO salarySobPO, Long employeeId) {
        Date now = new Date();
        result.setSalarySob(salarySobPO);
    }

    /**
     * 复制员工信息字段
     *
     * @param result
     * @param salarySobEmpFieldPOS
     * @param employeeId
     
     */
    private void duplicateEmpField(Result result, List<SalarySobEmpFieldPO> salarySobEmpFieldPOS, Long employeeId) {
        if (CollectionUtils.isEmpty(salarySobEmpFieldPOS)) {
            return;
        }
        Date now = new Date();
        List<SalarySobEmpFieldPO> newSalarySobEmpFieldPOS = salarySobEmpFieldPOS.stream()
                .map(salarySobEmpFieldPO -> new SalarySobEmpFieldPO()
                        .setSalarySobId(result.getSalarySob().getId())
                        .setFieldCode(salarySobEmpFieldPO.getFieldCode())
                        .setSortedIndex(salarySobEmpFieldPO.getSortedIndex())
                        .setCanDelete(salarySobEmpFieldPO.getCanDelete())
                        .setCreator(employeeId)
                        .setCreateTime(now)
                        .setUpdateTime(now)
                        .setDeleteType(NumberUtils.INTEGER_ZERO)
                        .setTenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY)
                ).collect(Collectors.toList());
        result.setSalarySobEmpFields(newSalarySobEmpFieldPOS);
    }

    /**
     * 复制薪资项目分组
     *
     * @param result              结果集
     * @param salarySobItemGroups 薪资项目分类po
     * @param employeeId          人员id
                租户key
     * @return
     */
    private Map<Long, Long> duplicateSalarySobItemGroup(Result result, List<SalarySobItemGroupPO> salarySobItemGroups, Long employeeId) {
        Date now = new Date();
        if (CollectionUtils.isEmpty(salarySobItemGroups)) {
            return Collections.emptyMap();
        }
        Map<Long, Long> oldIdKeyNewIdValueMap = Maps.newHashMapWithExpectedSize(salarySobItemGroups.size());
        List<SalarySobItemGroupPO> newSalarySobItemGroups = Lists.newArrayListWithExpectedSize(salarySobItemGroups.size());
        for (SalarySobItemGroupPO salarySobItemGroup : salarySobItemGroups) {
            SalarySobItemGroupPO newSalarySobItemGroup = SalarySobItemGroupPO.builder()
                    .id(IdGenerator.generate())
                    .name(salarySobItemGroup.getName())
                    .salarySobId(result.getSalarySob().getId())
                    .sortedIndex(salarySobItemGroup.getSortedIndex())
                    .description(salarySobItemGroup.getDescription())
                    .itemHide(salarySobItemGroup.getItemHide())
                    .creator(employeeId)
                    .createTime(now)
                    .updateTime(now)
                    .tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY)
                    .deleteType(NumberUtils.INTEGER_ZERO)
                    .build();
            newSalarySobItemGroups.add(newSalarySobItemGroup);
            oldIdKeyNewIdValueMap.put(salarySobItemGroup.getId(), newSalarySobItemGroup.getId());
        }
        result.setSalarySobItemGroups(newSalarySobItemGroups);
        return oldIdKeyNewIdValueMap;
    }

    /**
     * 复制薪资账套的薪资项目副本
     *
     * @param salarySobItems 薪资项目副本po
     * @param employeeId     人员id
           租户key
     * @return
     */
    private void duplicateSalarySobItem(Result result, List<SalarySobItemPO> salarySobItems, Map<Long, Long> groupIdMap, Long employeeId) {
        Date now = new Date();
        if (CollectionUtils.isEmpty(salarySobItems)) {
            return;
        }
        List<SalarySobItemPO> newSalarySobItems = Lists.newArrayListWithExpectedSize(salarySobItems.size());
        for (SalarySobItemPO salarySobItem : salarySobItems) {
            SalarySobItemPO newSalarySobItem = SalarySobItemPO.builder()
                    .salarySobId(result.getSalarySob().getId())
                    .salarySobItemGroupId(groupIdMap.getOrDefault(salarySobItem.getSalarySobItemGroupId(), NumberUtils.LONG_ZERO))
                    .salaryItemId(salarySobItem.getSalaryItemId())
                    .formulaId(salarySobItem.getFormulaId())
                    .sortedIndex(salarySobItem.getSortedIndex())
                    .description(salarySobItem.getDescription())
                    .canDelete(salarySobItem.getCanDelete())
                    .itemHide(salarySobItem.getItemHide())
                    .roundingMode(salarySobItem.getRoundingMode())
                    .pattern(salarySobItem.getPattern())
                    .valueType(salarySobItem.getValueType())
                    .creator(employeeId)
                    .createTime(now)
                    .updateTime(now)
                    .tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY)
                    .deleteType(NumberUtils.INTEGER_ZERO)
                    .build();
            newSalarySobItems.add(newSalarySobItem);
        }
        result.setSalarySobItems(newSalarySobItems);
    }

    /**
     * 复制调薪计薪规则
     *
     * @param result                结果集
     * @param salaryAdjustmentRules 调薪计薪规则po
     * @param employeeId            人员id
                  租户key
     */
    private void duplicateSalaryAdjustmentRule(Result result, List<SalarySobAdjustRulePO> salaryAdjustmentRules, Long employeeId) {
        Date now = new Date();
        if (CollectionUtils.isEmpty(salaryAdjustmentRules)) {
            return;
        }
        List<SalarySobAdjustRulePO> newSalaryAdjustmentRules = Lists.newArrayListWithExpectedSize(salaryAdjustmentRules.size());
        for (SalarySobAdjustRulePO salaryAdjustmentRule : salaryAdjustmentRules) {
            SalarySobAdjustRulePO newSalaryAdjustmentRule = new SalarySobAdjustRulePO()
                    .setSalarySobId(result.getSalarySob().getId())
                    .setSalaryItemId(salaryAdjustmentRule.getSalaryItemId())
                    .setDayOfMonth(salaryAdjustmentRule.getDayOfMonth())
                    .setBeforeAdjustmentType(salaryAdjustmentRule.getBeforeAdjustmentType())
                    .setAfterAdjustmentType(salaryAdjustmentRule.getAfterAdjustmentType())
                    .setCreator(employeeId)
                    .setCreateTime(now)
                    .setUpdateTime(now)
                    .setTenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY)
                    .setDeleteType(NumberUtils.INTEGER_ZERO);
            newSalaryAdjustmentRules.add(newSalaryAdjustmentRule);
        }
        result.setSalaryAdjustmentRules(newSalaryAdjustmentRules);
    }

    /**
     * 复制校验规则
     *
     * @param result              结果集
     * @param salarySobCheckRules 校验规则po
     * @param employeeId          人员id
                租户key
     * @return
     */
    private void duplicateSalarySobCheckRule(Result result, List<SalarySobCheckRulePO> salarySobCheckRules, Long employeeId) {
        if (CollectionUtils.isEmpty(salarySobCheckRules)) {
            return;
        }
        Date now = new Date();
        List<SalarySobCheckRulePO> newSalarySobCheckRules = salarySobCheckRules.stream()
                .map(e -> SalarySobCheckRulePO.builder()
                        .salarySobId(result.getSalarySob().getId())
                        .name(e.getName())
                        .formulaId(e.getFormulaId())
                        .description(e.getDescription())
                        .creator(employeeId)
                        .createTime(now)
                        .updateTime(now)
                        .tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY)
                        .deleteType(0)
                        .build())
                .collect(Collectors.toList());
        result.setSalarySobCheckRules(newSalarySobCheckRules);
    }

    /**
     * @description 复制回算薪资项目
     * @return void
     * @author Harryxzy
     * @date 2022/12/13 16:11
     */
    private void duplicateSalarySobBackItem(Result result, List<SalarySobBackItemPO> salarySobBackItemPOS, Long employeeId) {
        if (CollectionUtils.isEmpty(salarySobBackItemPOS)) {
            return;
        }
        Date now = new Date();
        List<SalarySobBackItemPO> newSalarySobBackItems = salarySobBackItemPOS.stream()
                .map(e -> SalarySobBackItemPO.builder()
                        .id(IdGenerator.generate())
                        .salarySobId(result.getSalarySob().getId())
                        .salaryItemId(e.getSalaryItemId())
                        .salaryItemCode(e.getSalaryItemCode())
                        .dataType(e.getDataType())
                        .roundingMode(e.getRoundingMode())
                        .pattern(e.getPattern())
                        .valueType(e.getValueType())
                        .formulaId(e.getFormulaId())
                        .backCalcType(e.getBackCalcType())
                        .creator(employeeId)
                        .createTime(now)
                        .updateTime(now)
                        .tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY)
                        .deleteType(0)
                        .build())
                .collect(Collectors.toList());
        result.setSalarySobBackItems(newSalarySobBackItems);
    }

    @Data
    public static class Result {

        /**
         * 薪资账套
         */
        private SalarySobPO salarySob;

        /**
         * 员工信息字段
         */
        private List<SalarySobEmpFieldPO> salarySobEmpFields;

        /**
         * 薪资项目副本
         */
        private List<SalarySobItemPO> salarySobItems;

        /**
         * 薪资项目分类
         */
        private List<SalarySobItemGroupPO> salarySobItemGroups;

        /**
         * 调薪计薪规则
         */
        private List<SalarySobAdjustRulePO> salaryAdjustmentRules;

        /**
         * 校验规则
         */
        private List<SalarySobCheckRulePO> salarySobCheckRules;

        /**
         * 薪资回算项目
         */
        private List<SalarySobBackItemPO> salarySobBackItems;
    }
}
