package yem.wm.cm.csrm.op;


import cn.hutool.core.util.CreditCodeUtil;
import kd.bos.context.RequestContext;
import kd.bos.dataentity.OperateOption;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.dataentity.utils.StringUtils;
import kd.bos.entity.ExtendedDataEntity;
import kd.bos.entity.plugin.AbstractOperationServicePlugIn;
import kd.bos.entity.plugin.AddValidatorsEventArgs;
import kd.bos.entity.plugin.PreparePropertysEventArgs;
import kd.bos.entity.plugin.args.AfterOperationArgs;
import kd.bos.entity.plugin.args.BeforeOperationArgs;
import kd.bos.entity.validate.AbstractValidator;
import kd.bos.logging.Log;
import kd.bos.logging.LogFactory;
import kd.bos.servicehelper.BusinessDataServiceHelper;
import kd.bos.servicehelper.operation.OperationServiceHelper;
import kd.bos.servicehelper.operation.SaveServiceHelper;
import kd.bos.threads.ThreadPool;
import kd.bos.threads.ThreadPools;
import kd.sdk.plugin.Plugin;
import yem.wm.cm.csrm.enums.PageIdEnum;
import yem.wm.cm.csrm.enums.TaskItemTypeEnum;
import yem.wm.cm.csrm.enums.TaskLogStatusEnum;
import yem.wm.cm.csrm.utils.QccUtils;
import yem.wm.cm.csrm.utils.TaskUtils;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

/**
 * 单据操作插件
 */
public class MerchanApplyOperationFixPlugin extends AbstractOperationServicePlugIn implements Plugin {
    private final static Log logger = LogFactory.getLog(MerchanApplyOperationFixPlugin.class);
    private static Long START_TIME;
    private static Long TASK_TIME;
    private static String SUBMIT_TAG = "yem_submit";
    private static String QCC_TAG = "yem_qccflag";


    class MyTask implements Runnable {
        private RequestContext rc;

        private DynamicObject[] data;

        private DynamicObject  merchantApply;;
        private Map<String, String> map;

        public MyTask(RequestContext rc, DynamicObject merchantApply, Map<String, String> map) {
            this.rc = rc;
            this.merchantApply = merchantApply;
            this.map = map;
        }

        //同步更新企查查对应的业务数据
        @Override
        public void run() {
            try {
                RequestContext.set(rc);
                startTask(merchantApply, map);
            } catch (ExecutionException e) {
                throw new RuntimeException(e);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }

        }

    }

    @Override
    public void onPreparePropertys(PreparePropertysEventArgs e) {
        super.onPreparePropertys(e);
        List<String> fieldKeys = e.getFieldKeys();
        fieldKeys.add("billno");
        fieldKeys.add("yem_societycreditcode");
        fieldKeys.add("yem_finish_status");
        fieldKeys.add("yem_isadmit");
    }

    @Override
    public void onAddValidators(AddValidatorsEventArgs e) {
        e.addValidator(new AbstractValidator() {
            @Override
            public void validate() {
                ExtendedDataEntity[] dataEntities = this.getDataEntities();
                for (ExtendedDataEntity dataEntity : dataEntities) {
                    DynamicObject entity = dataEntity.getDataEntity();
                    String isFiniyem_finish_statussh = entity.getString("yem_finish_status");
                    if (isFiniyem_finish_statussh.equals("1")) {
                        this.addErrorMessage(dataEntity, "该表单已经在对接处理中,不可重复提交");
                    }
                    String societyCreditCode = entity.getString("yem_societycreditcode");
                    if (StringUtils.isEmpty(societyCreditCode)) {
                        this.addErrorMessage(dataEntity, "统一社会信用代码不能为空！");
                    }
                }
            }
        });
    }

    @Override
    public void beforeExecuteOperationTransaction(BeforeOperationArgs e) {
        super.beforeExecuteOperationTransaction(e);
        String operationKey = e.getOperationKey();
        DynamicObject[] data = e.getDataEntities();
        Map<String, String> retuenMap = null;
        switch (operationKey) {
            case "submitdonothing":
                for (DynamicObject merchantApply : data) {
                    //创建日志底表
                    String CreditCode = CreditCodeUtil.randomCreditCode();
                    merchantApply.set("yem_societycreditcode",CreditCode);
                    retuenMap = TaskUtils.creatTaskTable(merchantApply, SUBMIT_TAG);
                    this.getOperationResult().setMessage(retuenMap.get(merchantApply.get("yem_societycreditcode")));
                    retuenMap.put("option", operationKey);
                    //修改页面状态为对接中
                    QccUtils.updateApplyMessage(merchantApply.getString("billno"), TaskLogStatusEnum.TASK_ING.getStatus());
                    //启动线程
                    MyTask myTask = new MyTask(RequestContext.get(), merchantApply, retuenMap);
                    ThreadPools.executeOnce("CACHEKEY_PROGRESS", myTask);
                }
                break;
            //重载企查查
            case "dockingqcc":
                for (DynamicObject merchantApply : data) {
                    retuenMap = TaskUtils.creatTaskTable(merchantApply, QCC_TAG);
                    this.getOperationResult().setMessage(retuenMap.get(merchantApply.get("yem_societycreditcode")));
                    DynamicObject yemScoringscheme = (DynamicObject) merchantApply.get("yem_scoringscheme");
                    String pkValue = String.valueOf(yemScoringscheme.getPkValue());
                    retuenMap.put("scorPlanId",pkValue);
                    retuenMap.put("option", operationKey);
                    //启动线程
                    MyTask task = new MyTask(RequestContext.get(), merchantApply, retuenMap);
                    ThreadPools.executeOnce("CACHEKEY_PROGRESS", task);
                }
                break;
            default:
                break;
        }
    }


    @Override
    public void afterExecuteOperationTransaction(AfterOperationArgs e) {
        super.afterExecuteOperationTransaction(e);
        String operationKey = e.getOperationKey();
        DynamicObject[] data = e.getDataEntities();
        DynamicObject merchantApply = Arrays.stream(data).iterator().next();
    }

    /**
     * @param merchantApply     客商申请页面数据
     * @param stringMap 日志表社会信用code
     * @throws ExecutionException
     * @throws InterruptedException
     */
    public void startTask(DynamicObject merchantApply, Map<String, String> stringMap) throws ExecutionException, InterruptedException {
            //获取任务底表
            String taskId = stringMap.getOrDefault(merchantApply.getString("yem_societycreditcode"), "");
            //任务日志任务项
            DynamicObject task = BusinessDataServiceHelper.loadSingle(taskId, PageIdEnum.TASK_ITEM_LOG.getPageId());
            DynamicObjectCollection loads = task.getDynamicObjectCollection("yem_entryentity");
            START_TIME = System.currentTimeMillis();
            Map<String,Object> paramType = new HashMap();
            paramType.put("merchantApply",merchantApply);
            paramType.put("loads",loads);
            paramType.put("rc",RequestContext.get());
            //执行对应任务项目
            taskExcute(paramType);
            //修改时间
            task.set("yem_totaltime", timeFormat(System.currentTimeMillis() - START_TIME));
            SaveServiceHelper.save(new DynamicObject[]{task});
            QccUtils.updateApplyMessage(String.valueOf(merchantApply.get("billno")), TaskLogStatusEnum.FINISHED.getStatus());
            if (stringMap.get("option").equals("submitdonothing")) {
                OperateOption op = OperateOption.create();
                op.setVariableValue("ignoreValidation", String.valueOf(true));
                OperationServiceHelper.executeOperate("submit", PageIdEnum.MERCHANT_APPLY.getPageId(),
                        new Object[]{merchantApply.getPkValue()}, op);
                SaveServiceHelper.clearDataEntityCache(PageIdEnum.MERCHANT_APPLY.getPageId());
            }
    }

    /**
     * 执行对应线程任务，任务完成后修改任务项状态
     * @param paramType
     */
    public void taskExcute(Map<String,Object> paramType) {
        ThreadPool executorService = ThreadPools.getOrCreateFixedThreadPool(String.valueOf(UUID.randomUUID()), 1);
        //创建对应任务项
        List<Callable<Map<String, Object>>> tasks = TaskUtils.creatTaskList(paramType);
        if (!tasks.isEmpty()) {
            //执行线程任务
            for (Callable<Map<String, Object>> task : tasks) {
                try {
                    // 等待任务完成并获取结果
                    TASK_TIME = System.currentTimeMillis();
                    Future<Map<String, Object>> future = executorService.submit(task);
                    Map<String, Object> objectMap = future.get();
                    if ((Boolean) objectMap.get("flag")) {
                        //任务成功，修改对应任务项状态
                        DynamicObject load = (DynamicObject) objectMap.getOrDefault("load", "");
                        QccUtils.updateStatus(load, TaskLogStatusEnum.FINISHED.getStatus(), System.currentTimeMillis()-TASK_TIME,"");
                    }
                } catch (InterruptedException | ExecutionException e) {
                    throw new RuntimeException(e);
                }
            }
        }
        // 关闭线程
        executorService.close();
    }

    private static String timeFormat(long ms) {
        long diffInSeconds = ms / 1000;
        long hours = diffInSeconds / 3600;
        long minutes = (diffInSeconds % 3600) / 60;
        long seconds = diffInSeconds % 60;
        long millis = ms % 1000;

        // 使用String.format来格式化输出，确保每部分都是两位数（不足的话前面补0）
        return String.format("%02d:%02d:%02d.%03d", hours, minutes, seconds, millis);
    }

}

