package com.engine.salary.service.impl;

import com.engine.common.util.ServiceUtil;
import com.engine.core.impl.Service;
import com.engine.salary.entity.salaryacct.po.SalaryAcctRecordPO;
import com.engine.salary.entity.salaryitem.param.SalaryItemSearchParam;
import com.engine.salary.entity.salaryitem.po.SalaryItemPO;
import com.engine.salary.entity.salarysob.bo.SalaryApprovalBO;
import com.engine.salary.entity.salarysob.dto.SalaryApprovalDTO;
import com.engine.salary.entity.salarysob.dto.SalarySobItemAggregateDTO;
import com.engine.salary.entity.salarysob.param.ApprovalRequestSaveParam;
import com.engine.salary.entity.salarysob.param.SalaryApprovalQueryParam;
import com.engine.salary.entity.salarysob.po.SalaryApprovalRulePO;
import com.engine.salary.entity.salarysob.po.SalarySobItemPO;
import com.engine.salary.entity.salarysob.po.SalarySobPO;
import com.engine.salary.exception.SalaryRunTimeException;
import com.engine.salary.mapper.salaryacct.SalaryAcctRecordMapper;
import com.engine.salary.mapper.salarysob.SalaryApprovalRuleMapper;
import com.engine.salary.service.*;
import com.engine.salary.sys.constant.SalarySysConstant;
import com.engine.salary.sys.entity.po.SalarySysConfPO;
import com.engine.salary.sys.service.SalarySysConfService;
import com.engine.salary.sys.service.impl.SalarySysConfServiceImpl;
import com.engine.salary.util.JsonUtil;
import com.engine.salary.util.db.IdGenerator;
import com.engine.salary.util.db.MapperProxyFactory;
import com.engine.salary.util.valid.ValidUtil;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import weaver.conn.RecordSet;
import weaver.hrm.User;

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

/**
 * @author Harryxzy
 * @ClassName SalaryApprovalRuleServiceImpl
 * @date 2024/04/23 17:35
 * @description
 */
public class SalaryApprovalRuleServiceImpl extends Service implements SalaryApprovalRuleService {

    private SalaryApprovalRuleMapper getSalaryApprovalRuleMapper() {
        return MapperProxyFactory.getProxy(SalaryApprovalRuleMapper.class);
    }

    private SalaryAcctRecordMapper getSalaryAcctRecordMapper() {
        return MapperProxyFactory.getProxy(SalaryAcctRecordMapper.class);
    }

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

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

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

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

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

    @Override
    public List<SalaryApprovalRulePO> listAll() {
        return getSalaryApprovalRuleMapper().listAll();
    }

    @Override
    public SalaryApprovalRulePO getById(Long id) {
        return getSalaryApprovalRuleMapper().getById(id);
    }

    @Override
    public int insertIgnoreNull(SalaryApprovalRulePO po) {
        return getSalaryApprovalRuleMapper().insertIgnoreNull(po);
    }

    @Override
    public int update(SalaryApprovalRulePO salaryApprovalRule) {
        return getSalaryApprovalRuleMapper().update(salaryApprovalRule);
    }

    @Override
    public int updateIgnoreNull(SalaryApprovalRulePO salaryApprovalRule) {
        return getSalaryApprovalRuleMapper().updateIgnoreNull(salaryApprovalRule);
    }

    @Override
    public int delete(SalaryApprovalRulePO salaryApprovalRule) {
        return getSalaryApprovalRuleMapper().delete(salaryApprovalRule);
    }

    @Override
    public SalaryApprovalRulePO getBySalarySobId(Long salarySobId) {
        if(salarySobId == null) {
            return null;
        }
        List<SalaryApprovalRulePO> salaryApprovalRulePOS = getSalaryApprovalRuleMapper().listSome(SalaryApprovalRulePO.builder().salarySobId(salarySobId).build());
        if (CollectionUtils.isNotEmpty(salaryApprovalRulePOS) && salaryApprovalRulePOS.size() == 1) {
            return salaryApprovalRulePOS.get(0);
        }
        return null;
    }

    @Override
    public void deleteBySalarySobId(Long salarySobId) {
        if (salarySobId == null) {
            return;
        }
        getSalaryApprovalRuleMapper().deleteBySalarySobId(salarySobId);
    }

    @Override
    public SalaryApprovalDTO salaryApprovalForm(SalaryApprovalQueryParam queryParam) {
        // 查询薪资审批设置
        SalaryApprovalRulePO approvalRulePO = getBySalarySobId(queryParam.getSalarySobId());
        if (approvalRulePO == null) {
            // 没有审批设置信息，创建默认设置信息
            Date now = new Date();
            approvalRulePO = SalaryApprovalRulePO.builder()
                    .id(IdGenerator.generate())
                    .salarySobId(queryParam.getSalarySobId())
                    .openApproval(0)
                    .createTime(now)
                    .updateTime(now)
                    .creator(Long.valueOf(user.getUID()))
                    .deleteType(0)
                    .build();
            // 获取账套的薪资项目设置信息
            SalarySobItemAggregateDTO aggregateBySalarySobId = getSalarySobItemService(user).getAggregateBySalarySobId(queryParam.getSalarySobId());
            String setting = SalaryApprovalBO.sobItemAggregate2approvalGroupSetting(aggregateBySalarySobId);
            approvalRulePO.setApprovalGroupSetting(setting);
            insertIgnoreNull(approvalRulePO);
        }

        List<SalaryItemPO> salaryItemList = getSalaryItemService(user).listAll();
        return SalaryApprovalBO.convert2DTO(approvalRulePO, salaryItemList);
    }

    @Override
    public void saveSalaryApprovalForm(SalaryApprovalDTO salaryApprovalDTO) {
        SalarySobPO salarySobPO = getSalarySobService(user).getById(salaryApprovalDTO.getSalarySobId());
        if (salarySobPO == null) {
            throw new RuntimeException("薪资账套不存在");
        }
        // 删除原来的
        deleteBySalarySobId(salaryApprovalDTO.getSalarySobId());
        // 保存最新的
        Date now = new Date();
        SalaryApprovalRulePO po = SalaryApprovalRulePO.builder()
                .id(IdGenerator.generate())
                .salarySobId(salaryApprovalDTO.getSalarySobId())
                .openApproval(salaryApprovalDTO.getIsOpenApproval() ? 1 : 0)
                .approvalGroupSetting(JsonUtil.toJsonString(salaryApprovalDTO.getApprovalItemGroup()))
                .workflowUrl(salaryApprovalDTO.getApprovalWorkflowUrl())
                .createTime(now)
                .updateTime(now)
                .creator(Long.valueOf(user.getUID()))
                .deleteType(0)
                .build();
        insertIgnoreNull(po);
    }

    @Override
    public List<SalaryItemPO> listSalaryApprovalItem(SalaryItemSearchParam queryParam) {
        List<SalarySobItemPO> salarySobItemPOS = getSalarySobItemService(user).listBySalarySobId(queryParam.getSalarySobId());
        List<Long> salaryItemIds = salarySobItemPOS.stream()
                .filter(po -> !queryParam.getExcludeIds().contains(po.getSalaryItemId()))
                .map(SalarySobItemPO::getSalaryItemId)
                .collect(Collectors.toList());
        List<SalaryItemPO> salaryItemPOList = getSalaryItemService(user).listByIds(salaryItemIds);
        return salaryItemPOList;
    }

    @Override
    public SalaryApprovalDTO getApprovalInfoByRecordId(Long salaryAcctRecordId) {
        SalaryAcctRecordPO acctRecordPO = getSalaryAcctRecordService(user).getById(salaryAcctRecordId);
        if (acctRecordPO == null) {
            throw new SalaryRunTimeException("薪资核算记录不存在或已被删除");
        }
        SalaryApprovalRulePO approvalRulePO = getBySalarySobId(acctRecordPO.getSalarySobId());

        List<SalaryItemPO> salaryItemList = getSalaryItemService(user).listAll();
        SalaryApprovalDTO salaryApprovalDTO = SalaryApprovalBO.convert2DTO(approvalRulePO, salaryItemList);
        // 查询是否可以核算、编辑(默认开启)
        salaryApprovalDTO.setCanEdit(getRecordIsCanEdit(acctRecordPO));
        return salaryApprovalDTO;
    }

    public boolean getRecordIsCanEdit(SalaryAcctRecordPO acctRecordPO) {
        // 审批总开关，默认关闭
        SalarySysConfPO approvalStatus = getSalarySysConfService(user).getOneByCode(SalarySysConstant.SALARY_APPROVAL_STATUS);
        if (approvalStatus == null || approvalStatus.getConfValue().equals("0")) {
            return true;
        }
        // 查询是否可以核算、编辑(默认开启)
        SalarySysConfPO canEdit = getSalarySysConfService(user).getOneByCode(SalarySysConstant.APPROVAL_CAN_EDIT_RESULT_STATUS);
        if (canEdit == null || canEdit.getConfValue().equals("1")) {
            return true;
        } else {
            // 发起审批后不能核损，判断流程id是否存在
            if (StringUtils.isBlank(acctRecordPO.getApprovalId())) {
                return true;
            } else {
                RecordSet rs = new RecordSet();
                rs.execute("SELECT * FROM workflow_requestbase where REQUESTID =" + acctRecordPO.getApprovalId());
                return !rs.next();
            }
        }
    }

    @Override
    public void saveApprovalRequestId(ApprovalRequestSaveParam saveParam) {
        ValidUtil.doValidator(saveParam);
        // 获取核算记录信息
        SalaryAcctRecordPO salaryAcctRecordPO = getSalaryAcctRecordService(user).getById(saveParam.getSalaryAcctRecordId());
        if (salaryAcctRecordPO == null) {
            throw new SalaryRunTimeException("薪资核素记录不存在或已被删除");
        }
        salaryAcctRecordPO.setApprovalId(saveParam.getRequestId());
        getSalaryAcctRecordMapper().updateIgnoreNull(salaryAcctRecordPO);
    }

    @Override
    public void deleteBySalarySobIds(Collection<Long> ids) {
        ids.stream().forEach(this::deleteBySalarySobId);
    }

    @Override
    public List<SalaryApprovalRulePO> listBySalarySobIds(Collection<Long> salarySobIds) {
        if (CollectionUtils.isEmpty(salarySobIds)) {
            return Collections.emptyList();
        }
        return getSalaryApprovalRuleMapper().listSome(SalaryApprovalRulePO.builder().salarySobIds(salarySobIds).build());
    }
}
