package com.engine.salary.service.impl;

import com.engine.common.util.ServiceUtil;
import com.engine.core.impl.Service;
import com.engine.salary.cache.SalaryCacheKey;
import com.engine.salary.entity.salaryacct.bo.SalaryAcctConfig;
import com.engine.salary.entity.salaryacct.po.SalaryAcctRecordPO;
import com.engine.salary.entity.salaryacct.po.SalaryAcctSobConfigPO;
import com.engine.salary.entity.salaryformula.ExpressFormula;
import com.engine.salary.entity.salaryitem.po.SalaryItemPO;
import com.engine.salary.entity.salarysob.bo.SalarySobItemAggregateBO;
import com.engine.salary.entity.salarysob.dto.SalarySobItemAggregateDTO;
import com.engine.salary.entity.salarysob.po.*;
import com.engine.salary.exception.SalaryRunTimeException;
import com.engine.salary.mapper.salaryacct.SalaryAcctSobConfigMapper;
import com.engine.salary.service.*;
import com.engine.salary.util.JsonUtil;
import com.engine.salary.util.SalaryEntityUtil;
import com.engine.salary.util.SalaryI18nUtil;
import com.engine.salary.util.db.MapperProxyFactory;
import org.apache.commons.lang3.StringUtils;
import weaver.hrm.User;

import java.util.*;

/**
 * 薪资核算的账套副本配置
 * <p>Copyright: Copyright (c) 2024</p>
 * <p>Company: 泛微软件</p>
 *
 * @author qiantao
 * @version 1.0
 **/
public class SalaryAcctSobConfigServiceImpl extends Service implements SalaryAcctSobConfigService {

    private SalaryAcctSobConfigMapper getSalaryAcctSobConfigMapper() {
        return MapperProxyFactory.getProxy(SalaryAcctSobConfigMapper.class);
    }

    private SalaryFormulaService getSalaryFormulaService(User user) {
        return ServiceUtil.getService(SalaryFormulaServiceImpl.class, user);
    }

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

    private SalaryAcctRecordService getSalaryAcctRecordService(User user) {
        return ServiceUtil.getService(SalaryAcctRecordServiceImpl.class, user);
    }

    private SalarySobService getSalarySobService(User user) {
        return ServiceUtil.getService(SalarySobServiceImpl.class, user);
    }

    private SalarySobEmpFieldService getSalarySobEmpFieldService(User user) {
        return ServiceUtil.getService(SalarySobEmpFieldServiceImpl.class, user);
    }

    private SalarySobItemGroupService getSalarySobItemGroupService(User user) {
        return ServiceUtil.getService(SalarySobItemGroupServiceImpl.class, user);
    }

    private SalarySobItemService getSalarySobItemService(User user) {
        return ServiceUtil.getService(SalarySobItemServiceImpl.class, user);
    }

    private SalarySobBackItemService getSalarySobBackItemService(User user) {
        return ServiceUtil.getService(SalarySobBackItemServiceImpl.class, user);
    }

    private SalarySobAdjustRuleService getSalarySobAdjustRuleService(User user) {
        return ServiceUtil.getService(SalarySobAdjustRuleServiceImpl.class, user);
    }

    private SalarySobCheckRuleService salarySobCheckRuleService;

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

    @Override
    public SalaryAcctSobConfigPO getBySalaryAcctRecordId(Long salaryAcctRecordId) {
        return getBySalaryAcctRecordId(true, salaryAcctRecordId);
    }

    @Override
    public SalaryAcctConfig getSalaryAcctConfig(Long salaryAcctRecordId) {
        SalaryAcctSobConfigPO po = getBySalaryAcctRecordId(true, salaryAcctRecordId);
        return SalaryAcctConfig.parse(po);
    }

    @Override
    public SalaryAcctSobConfigPO getBySalaryAcctRecordId(boolean needInit, Long salaryAcctRecordId) {
        SalaryAcctSobConfigPO salaryAcctSobConfig = getSalaryAcctSobConfigMapper().getBySalaryAcctRecordId(salaryAcctRecordId);
        if (Objects.nonNull(salaryAcctSobConfig)) {
            return salaryAcctSobConfig;
        }
        // 查询薪资核算记录
        SalaryAcctRecordPO salaryAcctRecord = getSalaryAcctRecordService(user).getById(salaryAcctRecordId);
        // 初始化薪资核算记录的列配置
        if (needInit) {
            salaryAcctSobConfig = initBySalaryAcctRecord(salaryAcctRecord);
        }
        return salaryAcctSobConfig;
    }

    @Override
    public SalarySobItemAggregateDTO getSalarySobItemAggregate(Long salaryAcctRecordId) {
        return getSalarySobItemAggregate(true, salaryAcctRecordId);
    }

    @Override
    public SalarySobItemAggregateDTO getSalarySobItemAggregateNoFormula(Long salaryAcctRecordId) {
        return getSalarySobItemAggregate(false, salaryAcctRecordId);
    }

    private SalarySobItemAggregateDTO getSalarySobItemAggregate(boolean needFormula, Long salaryAcctRecordId) {
        // 查询薪资核算
        SalaryAcctSobConfigPO salaryAcctSobConfig = getBySalaryAcctRecordId(salaryAcctRecordId);
        // 薪资账套的基本信息
        SalarySobPO salarySob = JsonUtil.parseObject(salaryAcctSobConfig.getBasicConfig(), SalarySobPO.class);
        // 员工信息字段
        List<SalarySobEmpFieldPO> salarySobEmpFields = JsonUtil.parseList(salaryAcctSobConfig.getEmployeeFieldConfig(), SalarySobEmpFieldPO.class);
        // 薪资项目分类
        List<SalarySobItemGroupPO> salarySobItemGroups = JsonUtil.parseList(salaryAcctSobConfig.getItemGroupConfig(), SalarySobItemGroupPO.class);
        // 薪资项目
        List<SalarySobItemPO> salarySobItems = JsonUtil.parseList(salaryAcctSobConfig.getItemConfig(), SalarySobItemPO.class);
        // 回算薪资项目
        List<SalarySobBackItemPO> salarySobBackItems = JsonUtil.parseList(salaryAcctSobConfig.getBackItemConfig(), SalarySobBackItemPO.class);
        // 查询薪资账套的薪资项目所关联的薪资项目
        Set<Long> salaryItemIds = SalaryEntityUtil.properties(salarySobItems, SalarySobItemPO::getSalaryItemId);
        salaryItemIds.addAll(SalaryEntityUtil.properties(salarySobBackItems, SalarySobBackItemPO::getSalaryItemId));
        List<SalaryItemPO> salaryItems = getSalaryItemService(user).listByIds(salaryItemIds);
        // 函数公式
        List<ExpressFormula> expressFormulas = Collections.emptyList();
        if (needFormula) {
            Set<Long> formulaIds = SalaryEntityUtil.properties(salarySobItems, SalarySobItemPO::getFormulaId);
            formulaIds.addAll(SalaryEntityUtil.properties(salarySobBackItems, SalarySobBackItemPO::getFormulaId));
            expressFormulas = getSalaryFormulaService(user).listExpressFormula(formulaIds);
        }
        // 转换成聚合dto
        SalarySobItemAggregateBO salarySobItemAggregateBO = new SalarySobItemAggregateBO(salarySob, salarySobEmpFields,
                salarySobItemGroups, salarySobItems, expressFormulas, salaryItems, salarySobBackItems, Collections.emptyList());
        return salarySobItemAggregateBO.convert2AggregateDTO();
    }

    @Override
    public SalaryAcctSobConfigPO initBySalaryAcctRecord(SalaryAcctRecordPO salaryAcctRecord) {
        // 薪资账套的基本信息
        SalarySobPO salarySob = getSalarySobService(user).getById(salaryAcctRecord.getSalarySobId());
        // 薪资账套的员工信息字段
        List<SalarySobEmpFieldPO> salarySobEmpFields = getSalarySobEmpFieldService(user).listBySalarySobId(salaryAcctRecord.getSalarySobId());
        // 薪资账套的薪资项目分类
        List<SalarySobItemGroupPO> salarySobItemGroups = getSalarySobItemGroupService(user).listBySalarySobId(salaryAcctRecord.getSalarySobId());
        // 薪资账套的薪资项目
        List<SalarySobItemPO> salarySobItems = getSalarySobItemService(user).listBySalarySobId(salaryAcctRecord.getSalarySobId());
        // 薪资账套的回算薪资项目
        List<SalarySobBackItemPO> salarySobBackItemPOS = getSalarySobBackItemService(user).listBySalarySobId(salaryAcctRecord.getSalarySobId());

        SalaryAcctConfig salaryAcctConfig = new SalaryAcctConfig(salaryAcctRecord, salarySob, salarySobEmpFields,
                salarySobItems, salarySobItemGroups, salarySobBackItemPOS, Collections.emptyList(), Collections.emptyList());
        return salaryAcctConfig.buildAcctSobConfig();
    }

    @Override
    public synchronized void save(SalaryAcctSobConfigPO salaryAcctSobConfig) {
        deleteBySalaryAcctRecordIds(Collections.singleton(salaryAcctSobConfig.getSalaryAcctRecordId()));
        getSalaryAcctSobConfigMapper().insertIgnoreNull(salaryAcctSobConfig);
        String cacheIndex = salaryAcctSobConfig.getSalaryAcctRecordId().toString();
        getSalaryCacheService(user).set(SalaryCacheKey.ACCT_SOB_CONFIG + cacheIndex, "FALSE");
    }

    @Override
    public void updateBySalaryAcctRecordId(Long salaryAcctRecordId) {
        SalaryAcctRecordPO salaryAcctRecord = getSalaryAcctRecordService(user).getById(salaryAcctRecordId);
        if (salaryAcctRecord == null) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(156474, "参数错误，薪资核算记录不存在或已被删除"));
        }
        SalaryAcctSobConfigPO salaryAcctSobConfig = initBySalaryAcctRecord(salaryAcctRecord);

        String acctSobConfigFlag = getSalaryCacheService(user).get(SalaryCacheKey.ACCT_SOB_CONFIG + salaryAcctRecordId);
        if (acctSobConfigFlag != null && StringUtils.equals(acctSobConfigFlag, "TRUE")) {
            return;
        }
        getSalaryCacheService(user).set(SalaryCacheKey.ACCT_SOB_CONFIG + salaryAcctRecordId, "TRUE");

        try {
            deleteBySalaryAcctRecordIds(Collections.singleton(salaryAcctRecordId));
            getSalaryAcctSobConfigMapper().insertIgnoreNull(salaryAcctSobConfig);
        } finally {
            getSalaryCacheService(user).set(SalaryCacheKey.ACCT_SOB_CONFIG + salaryAcctRecordId, "FALSE");
        }
    }

    @Override
    public void deleteBySalaryAcctRecordIds(Collection<Long> salaryAcctRecordIds) {
        getSalaryAcctSobConfigMapper().deleteBySalaryAcctRecordIds(salaryAcctRecordIds);
    }
}
