package nckd.jimin.jyyy.fi.task;

import com.google.common.collect.Lists;
import kd.bos.context.RequestContext;
import kd.bos.dataentity.OperateOption;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.entity.EntityMetadataCache;
import kd.bos.entity.operate.result.OperationResult;
import kd.bos.exception.KDBizException;
import kd.bos.exception.KDException;
import kd.bos.logging.Log;
import kd.bos.logging.LogFactory;
import kd.bos.orm.query.QCP;
import kd.bos.orm.query.QFilter;
import kd.bos.schedule.api.StopTask;
import kd.bos.schedule.executor.AbstractTask;
import kd.bos.servicehelper.BusinessDataServiceHelper;
import kd.bos.servicehelper.QueryServiceHelper;
import kd.bos.servicehelper.operation.OperationServiceHelper;
import kd.bos.servicehelper.user.UserServiceHelper;
import kd.bos.util.StringUtils;
import nckd.jimin.jyyy.fi.common.ReimAmountSourceTypeEnum;
import nckd.jimin.jyyy.fi.common.constant.BillTypeConstants;
import nckd.jimin.jyyy.fi.common.util.CommonUtils;

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

/**
 * 年度个人额度复制功能
 */
public class PersonReimYearQuotaCopyTask extends AbstractTask implements StopTask {
    private static final Log logger = LogFactory.getLog(PersonReimYearQuotaCopyTask.class);
    private static final String YEAR = "year";
    @Override
    public void execute(RequestContext requestContext, Map<String, Object> map) throws KDException {
        copyYearData(map);
    }

    /**
     * 年度个人额度复制功能
     * @param map
     */
    protected void copyYearData(Map<String, Object> map){
        logger.info("PersonReimYearCopyTask_begin------------");
        int year = getYear(map);

        // 复制的到第二年
        int copyYear = year + 1;
        // 查询去年的个人额度信息

        List<Object> copyDataId = QueryServiceHelper.query(BillTypeConstants.ER_REIMBURSEAMOUNT, "id", new QFilter[]{
                new QFilter("dateyear", QCP.equals, String.valueOf(year)),
                new QFilter("auditstatus", QCP.equals, "1")
        }).stream().map(r -> r.get("id")).collect(Collectors.toList());
        logger.info("PersonReimYearCopyTask copyDataId size : " + copyDataId.size());
        // 分批
        List<List<Object>> partition = Lists.partition(copyDataId, 100);
        List<String> failBillSet = new ArrayList<>();
        for(List<Object> patchIdList : partition){

            // 查询已经生成的数据
            Set<Object> hasCreateIdSet = QueryServiceHelper.query(BillTypeConstants.ER_REIMBURSEAMOUNT, "nckd_sourcebillid", new QFilter[]{
                    new QFilter("dateyear", QCP.equals, String.valueOf(copyYear)),
                    new QFilter("nckd_sourcetype", QCP.equals, ReimAmountSourceTypeEnum.YEARCOPY.getKey()),
                    new QFilter("nckd_sourcebillid", QCP.in, patchIdList),
            }).stream().map(r -> r.get("nckd_sourcebillid")).collect(Collectors.toSet());

            // 移除
            patchIdList.removeIf(r -> hasCreateIdSet.contains(r));

            DynamicObject[] copyDataList = BusinessDataServiceHelper.load(patchIdList.toArray(), EntityMetadataCache.getDataEntityType(BillTypeConstants.ER_REIMBURSEAMOUNT));
            for(DynamicObject reimburseQuota : copyDataList){
                String reimPerson = "";
                try{
                    reimPerson = reimburseQuota.getDynamicObject("employee").getString("number");
                    saveQuotaData(reimburseQuota,copyYear);
                }catch (Exception e){
                    failBillSet.add(reimPerson);
                    logger.error(String.format("【%s】的个人额度同步失败", reimPerson ), e);
                }
            }
        }
        logger.info(String.format("失败的单据条数为：%s，请monitor检查失败原因后，在任务中重试。",failBillSet.size()));
    }

    private void saveQuotaData(DynamicObject reimburseQuota , int dateYear) {

        Date now = new Date();
        long currentUserId = UserServiceHelper.getCurrentUserId();
        // 获取12月的个人额度，创建新年额度
        BigDecimal quatoAmount = reimburseQuota.getBigDecimal("month12");

        DynamicObject remiQuota = BusinessDataServiceHelper.newDynamicObject(BillTypeConstants.ER_REIMBURSEAMOUNT);
        remiQuota.set("company", reimburseQuota.get("company"));
        remiQuota.set("expenseitem", reimburseQuota.get("expenseitem"));
        remiQuota.set("currency", reimburseQuota.get("currency"));
        remiQuota.set("dateyear", dateYear);

        remiQuota.set("totalamount", quatoAmount.multiply(BigDecimal.valueOf(12L)));
        remiQuota.set("costcompany", reimburseQuota.get("costcompany"));

        for(int i = 1; i <= 12; i++) {
            remiQuota.set("month" + i, quatoAmount);
        }

        remiQuota.set("amounttype", "1");
        remiQuota.set("employee", reimburseQuota.get("employee"));
        remiQuota.set("dept", reimburseQuota.get("dept"));
        remiQuota.set("auditstatus", "0");
        remiQuota.set("createtime", now);
        remiQuota.set("modifytime", now);
        remiQuota.set("creator", currentUserId);
        remiQuota.set("modifier", currentUserId);
        remiQuota.set("wbsrcbilltype", "er_reimctl_new");

        remiQuota.set("nckd_sourcetype", ReimAmountSourceTypeEnum.YEARCOPY.getKey());
        remiQuota.set("nckd_sourcebillid", reimburseQuota.getPkValue());

        // 调用保存
        OperationResult saveOp = OperationServiceHelper.executeOperate("save", BillTypeConstants.ER_REIMBURSEAMOUNT, new DynamicObject[]{remiQuota}, OperateOption.create());
        if(!saveOp.isSuccess() || saveOp.getSuccessPkIds().size() == 0){
            throw new KDBizException(CommonUtils.getOperationResultErrorInfos(saveOp));
        }
        OperationResult approveOp = OperationServiceHelper.executeOperate("approve", BillTypeConstants.ER_REIMBURSEAMOUNT, new Object[]{saveOp.getSuccessPkIds().get(0)}, OperateOption.create());
        if(!approveOp.isSuccess() || approveOp.getSuccessPkIds().size() == 0){
            throw new KDBizException(CommonUtils.getOperationResultErrorInfos(approveOp));
        }
    }

    /**
     * 获取额度复制年
     * @param map
     * @return
     */
    protected int getYear(Map<String, Object> map){

        if(map.containsKey(YEAR) && StringUtils.isNotEmpty((String)map.get(YEAR))){
            return Integer.parseInt(map.get(YEAR).toString());
        }
        // 第二年执行前一年的数据
        return Calendar.getInstance().get(Calendar.YEAR);
    }

}
