package nckd.jimin.jyyy.fi.plugin.form;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.kingdee.util.StringUtils;
import kd.bos.context.RequestContext;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.entity.EntityMetadataCache;
import kd.bos.entity.datamodel.ListSelectedRowCollection;
import kd.bos.entity.operate.result.OperationResult;
import kd.bos.form.*;
import kd.bos.form.events.AfterDoOperationEventArgs;
import kd.bos.form.events.BeforeDoOperationEventArgs;
import kd.bos.form.events.ClosedCallBackEvent;
import kd.bos.form.events.MessageBoxClosedEvent;
import kd.bos.form.operate.FormOperate;
import kd.bos.list.BillList;
import kd.bos.list.plugin.AbstractListPlugin;
import kd.bos.orm.query.QCP;
import kd.bos.orm.query.QFilter;
import kd.bos.schedule.api.JobInfo;
import kd.bos.schedule.api.JobType;
import kd.bos.schedule.api.TaskInfo;
import kd.bos.schedule.form.JobForm;
import kd.bos.servicehelper.BusinessDataServiceHelper;
import kd.bos.servicehelper.QueryServiceHelper;
import kd.bos.servicehelper.operation.SaveServiceHelper;
import nckd.jimin.jyyy.fi.common.ReimAmountSourceTypeEnum;
import nckd.jimin.jyyy.fi.common.constant.JobPositionBakBillConstant;
import nckd.jimin.jyyy.fi.common.constant.LimitRelasetConstant;
import nckd.jimin.jyyy.fi.plugin.operate.Helper.PersonReimQuotaHelper;
import nckd.jimin.jyyy.fi.plugin.operate.Helper.PersonReimQuotaVO;

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

public class LimitRelasetList extends AbstractListPlugin {
    // 额度同步
    private static final String OP_SYNCQUOTA = "syncquota";
    // 额度更新
    private static final String OP_ADJUSTQUOTA = "adjustquota";

    // 额度同步：作废额度回调
    private static final String COMFIRMCALLBACK_SYNCQUOTA_CANCEL = "comfirmcallback_syncquota_cancel";
    // 额度同步：同步回调
    private static final String COMFIRMCALLBACK_SYNCQUOTA_SYNC = "comfirmcallback_syncquota_sync";


    // 费用标准作废
    private static final String OP_CANCEL = "cancel";


    @Override
    public void beforeDoOperation(BeforeDoOperationEventArgs args) {
        super.beforeDoOperation(args);
        FormOperate operate = (FormOperate)args.getSource();
        String operateKey = operate.getOperateKey();
        BillList billList = (BillList)this.getControl("billlistap");
        ListSelectedRowCollection selectedRows = billList.getSelectedRows();
        // 额度同步和变更仅允许选择一条记录
        if(OP_SYNCQUOTA.equals(operateKey) || OP_ADJUSTQUOTA.equals(operateKey)){
            if(selectedRows.size() > 1){
                this.getView().showTipNotification("仅允许选择一条数据进行操作。");
                args.setCancel( true);
                return;
            }
        }
    }

    @Override
    public void afterDoOperation(AfterDoOperationEventArgs args) {
        super.afterDoOperation(args);
        String operateKey = args.getOperateKey();
        OperationResult operationResult = args.getOperationResult();
        if(operationResult == null || !operationResult.isSuccess() || operationResult.getSuccessPkIds().size() == 0){

            return;
        }

        List<Object> successPkIds = operationResult.getSuccessPkIds();
        if ( OP_ADJUSTQUOTA.equals(operateKey)) {
            // 打开额度调整界面
            showUpdateQuota(successPkIds.get(0).toString());
        }

        if ( OP_SYNCQUOTA.equals(operateKey)) {
            DynamicObject limitRelasetInfo = BusinessDataServiceHelper.loadSingle(successPkIds.get(0),LimitRelasetConstant.ENTITYID);
            String status = limitRelasetInfo.getString(LimitRelasetConstant.KEY_STATUS);
            Map<String, Object> varMap = new HashMap<>();
            varMap.put("billid", successPkIds.get(0));
            // 已作废
            if("I".equals(status)){
                ConfirmCallBackListener confirmCallBackListener = new ConfirmCallBackListener(COMFIRMCALLBACK_SYNCQUOTA_CANCEL, this);
                // 设置页面确认框，参数为：标题，选项框类型，回调监听
                getView().showConfirm(String.format("费用标准%s状态为已作废，额度同步后将作废费用项目%s下的额度信息，请确认是否同步?",
                                limitRelasetInfo.getString(LimitRelasetConstant.KEY_NUMBER),limitRelasetInfo.getDynamicObject(LimitRelasetConstant.KEY_NCKD_EXPENSEITEM).getString(LimitRelasetConstant.KEY_NAME)),
                        MessageBoxOptions.YesNo, confirmCallBackListener);
            }
            // 已审核
            else if("C".equals(status)){
                ConfirmCallBackListener confirmCallBackListener = new ConfirmCallBackListener(COMFIRMCALLBACK_SYNCQUOTA_SYNC, this);
                // 设置页面确认框，参数为：标题，选项框类型，回调监听
                getView().showConfirm(String.format("费用标准%s状态为已审核，额度同步后将更新费用项目%s下的额度信息，请确认是否同步?",
                        limitRelasetInfo.getString(LimitRelasetConstant.KEY_NUMBER),limitRelasetInfo.getDynamicObject(LimitRelasetConstant.KEY_NCKD_EXPENSEITEM).getString(LimitRelasetConstant.KEY_NAME))
                ,MessageBoxOptions.YesNo, confirmCallBackListener);
            }else{
                this.getView().showTipNotification("仅已审核、已作废状态允许进行额度同步。");
            }

        }

        if(OP_CANCEL.equals(operateKey)){
            successPkIds.stream().forEach(pkId -> saveLimitRelasetLog((Long)pkId, operateKey, "额度作废"));
        }
    }
    protected void showUpdateQuota(String pkId) {
        FormShowParameter parameter = new FormShowParameter();
        parameter.setFormId("nckd_limitrelasetadjust");
        parameter.getOpenStyle().setShowType(ShowType.Modal);
        Map<String, Object> customParams = parameter.getCustomParams();
        customParams.put("billid",pkId);
        getView().showForm(parameter);
    }


    @Override
    public void confirmCallBack(MessageBoxClosedEvent event) {
        super.confirmCallBack(event);
        String callBackId = event.getCallBackId();
        if(!MessageBoxResult.Yes.equals(event.getResult())){
            return;
        }
        BillList billList = (BillList)this.getControl("billlistap");
        ListSelectedRowCollection selectedRows = billList.getSelectedRows();
        if(selectedRows.size() == 1){
            Object billid = selectedRows.get(0).getPrimaryKeyValue();
            PersonReimQuotaHelper personReimQuotaHelper = new PersonReimQuotaHelper();

            DynamicObject limitRelasetInfo = BusinessDataServiceHelper.loadSingle(billid,LimitRelasetConstant.ENTITYID);
            // 作废
            if(COMFIRMCALLBACK_SYNCQUOTA_CANCEL.equals(callBackId)){
                personReimQuotaHelper.doInvalidPersonReim(new QFilter[]{
                        new QFilter("nckd_limitrelaset", QCP.equals, limitRelasetInfo.getLong(LimitRelasetConstant.ID)),
                });
                getView().showSuccessNotification("关闭关联的个人额度成功。");
                saveLimitRelasetLog(Long.valueOf(billid.toString()), OP_SYNCQUOTA, "额度同步-费用标准废弃后，关闭关联个人额度。");
            }
            // 同步
            if(COMFIRMCALLBACK_SYNCQUOTA_SYNC.equals(callBackId)){

                DynamicObject[] personPositionJobBakArray = getPersonPositionJobBakCol();
                String classType = limitRelasetInfo.getString(LimitRelasetConstant.KEY_NCKD_CLASSTYPE_JOBPOS);

                DynamicObject jobPosition = limitRelasetInfo.getDynamicObject(LimitRelasetConstant.KEY_NCKD_CLASSFIELD_JOBPOS);
                if(jobPosition == null){
                    return;
                }
                long expenseItemId = limitRelasetInfo.getDynamicObject(LimitRelasetConstant.KEY_NCKD_EXPENSEITEM).getLong(LimitRelasetConstant.ID);
                long currencyId = limitRelasetInfo.getDynamicObject(LimitRelasetConstant.KEY_NCKD_CURRENCY).getLong(LimitRelasetConstant.ID);
                BigDecimal quotaAmont = limitRelasetInfo.getBigDecimal(LimitRelasetConstant.KEY_NCKD_AMOUNT);

                for(DynamicObject jobBakInfo : personPositionJobBakArray){
                    // 职级或者岗位能够匹配
                    if(("hbjm_joblevelhr".equals(classType) && jobBakInfo.getDynamicObject(JobPositionBakBillConstant.KEY_NCKD_JOBLEVEL_NEW) != null
                            && jobBakInfo.getDynamicObject(JobPositionBakBillConstant.KEY_NCKD_JOBLEVEL_NEW).getLong(JobPositionBakBillConstant.ID) == jobPosition.getLong(LimitRelasetConstant.ID))
                            || ("hbpm_positionhr".equals(classType) && jobBakInfo.getDynamicObject(JobPositionBakBillConstant.KEY_NCKD_POSITION_NEW) != null
                            && jobBakInfo.getDynamicObject(JobPositionBakBillConstant.KEY_NCKD_POSITION_NEW).getLong(JobPositionBakBillConstant.ID) == jobPosition.getLong(LimitRelasetConstant.ID))){

                        PersonReimQuotaVO personReimQuotaVO = new PersonReimQuotaVO(
                                jobBakInfo.getDynamicObject(JobPositionBakBillConstant.KEY_NCKD_USER).getLong(JobPositionBakBillConstant.ID),
                                jobBakInfo.getDynamicObject(JobPositionBakBillConstant.KEY_NCKD_ORG_NEW).getLong(JobPositionBakBillConstant.ID),
                                expenseItemId,
                                currencyId,
                                quotaAmont,
                                ReimAmountSourceTypeEnum.STANDARDCHANGE,
                                "",
                                limitRelasetInfo.getString(LimitRelasetConstant.ID));
                        personReimQuotaHelper.createPersonReimAmount(personReimQuotaVO);
                    }
                }
                getView().showSuccessNotification("个人额度同步成功。");
                saveLimitRelasetLog(Long.valueOf(billid.toString()), OP_SYNCQUOTA, "额度同步-费用标准额度同步到个人额度。");
            }
        }
    }


    /**
     * 回调事件，在任务处理完毕后继续后续处理
     */
    @Override
    public void closedCallBack(ClosedCallBackEvent closedCallBackEvent) {
        super.closedCallBack(closedCallBackEvent);
        if (StringUtils.equals(closedCallBackEvent.getActionId(), "taskcloseback")) {
            Object returnData = closedCallBackEvent.getReturnData();
            if (returnData == null) {
                return;
            }
            if (returnData instanceof Map) {
                Map<String, Object> result = (Map<String, Object>)returnData;
                if (result.containsKey("taskinfo")) {
                    String taskInfoStr = (String)result.get("taskinfo");
                    if (!StringUtils.isEmpty(taskInfoStr)) {
                        TaskInfo taskInfo = JSON.parseObject(taskInfoStr,TaskInfo.class);
                        if (taskInfo.isTaskEnd()) {
                            // 获取任务执行完毕，生成的内容
                            String data = taskInfo.getData();
                            if(!StringUtils.isEmpty(data)){
                                JSONObject dataJson = JSON.parseObject(data);
                                this.getView().showSuccessNotification(dataJson.getString("message"));
                            }else{
                                this.getView().showSuccessNotification("执行成功。");
                            }
                        }
                    }
                }
            }
        }
    }
    /**
     * 创建任务目标，发布新任务
     */
    private void dispatch(String jobName,String updateType) {
        // 创建任务目标
        JobInfo jobInfo = new JobInfo();
        jobInfo.setAppId("em");                // 执行类所在的应用名
        jobInfo.setJobType(JobType.REALTIME);   // 即时执行
        jobInfo.setName(jobName);
        jobInfo.setId(UUID.randomUUID().toString());        // 随机产生一个JobId (任务目标的标识)
        jobInfo.setTaskClassname("nckd.jimin.jyyy.fi.task.PersonReimBigJobTask");
        // 自定义参数
        Map<String,Object> params = new HashMap<>();
        params.put("updatetype", updateType);
        jobInfo.setParams(params);
        jobInfo.setRunByUserId(RequestContext.get().getCurrUserId());
        // 回调参数，设置一个回调处理标识(actionId)
        CloseCallBack closeCallBack = new CloseCallBack(this, "taskcloseback");
        // 发布任务，并显示进度
        JobForm.dispatch(jobInfo, this.getView(), closeCallBack);
    }


    private void saveLimitRelasetLog(long limitRelasetId, String operate ,String description){
        DynamicObject limitRelasetOperateInfo = BusinessDataServiceHelper.newDynamicObject("nckd_limitrelasetoperate");
        limitRelasetOperateInfo.set("nckd_operator", RequestContext.get().getCurrUserId());
        limitRelasetOperateInfo.set("nckd_operatetime",new Date());
        limitRelasetOperateInfo.set("nckd_limitrelaset", limitRelasetId);
        limitRelasetOperateInfo.set("nckd_operate", operate);
        limitRelasetOperateInfo.set("nckd_description", description);
        SaveServiceHelper.save(new DynamicObject[]{ limitRelasetOperateInfo });
    }

    protected DynamicObject[] getPersonPositionJobBakCol() {
        Set<Long> bakBillIdSet = QueryServiceHelper.query(JobPositionBakBillConstant.ENTITYID, JobPositionBakBillConstant.ID, QFilter.isNotNull(JobPositionBakBillConstant.ID).toArray())
                .stream()
                .map(r -> r.getLong(JobPositionBakBillConstant.ID))
                .collect(Collectors.toSet());
        return BusinessDataServiceHelper.load(bakBillIdSet.toArray(), EntityMetadataCache.getDataEntityType(JobPositionBakBillConstant.ENTITYID));
    }
}
