package yem.wm.cm.csrm.form;

import com.kingdee.bos.qing.util.StringUtils;
import kd.bos.cache.CacheFactory;
import kd.bos.cache.DistributeSessionlessCache;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.entity.datamodel.IDataModel;
import kd.bos.exception.KDBizException;
import kd.bos.form.FormShowParameter;
import kd.bos.form.IFormView;
import kd.bos.form.StyleCss;
import kd.bos.form.cardentry.CardEntry;
import kd.bos.form.container.Tab;
import kd.bos.form.control.Label;
import kd.bos.form.control.ProgressBar;
import kd.bos.form.control.events.ProgressEvent;
import kd.bos.form.control.events.ProgresssListener;
import kd.bos.form.plugin.AbstractFormPlugin;
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.servicehelper.BusinessDataServiceHelper;
import kd.bos.threads.ThreadPools;
import kd.sdk.plugin.Plugin;
import yem.base.common.utils.YEM;
import yem.wm.cm.csrm.enums.PageIdEnum;
import yem.wm.cm.csrm.enums.TaskLogStatusEnum;
import yem.wm.cm.csrm.utils.BillCommonUtils;

import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 多任务处理进度卡片分录
 *
 * @Author yunshuaiwei
 * @Date 2024/5/28 16:50
 **/
public class MultiTaskingProgressCard extends AbstractFormPlugin implements Plugin, ProgresssListener {

    private final static String PROGRESS_KEY = "MultiTaskingProgressCard";
    private final static String TASK_INDEX = "index";
    private final static String TASK_START_TIME = "startTime";
    //进度条
    private final static String PROGRESS_BAR = "yem_progressbarap";
    private final static String LABEL_PERCENT = "yem_labelap1";
    //耗时
    private final static String LABEL_TIME = "yem_labelap2";
    private final static String LABEL_TASK_NAME = "yem_labelap";
    //总耗时
    private final static String LABEL_TOTAL_TIME = "yem_labelap3";

    Log log = LogFactory.getLog(MultiTaskingProgressCard.class);

    private static final List<String> labels = new ArrayList<>();

    DistributeSessionlessCache cache = CacheFactory.getCommonCacheFactory().getDistributeSessionlessCache("customRegion");

    private static Long start = 0L;

    static {
        labels.add("yem_vectorap");//图标：已完成
        labels.add("yem_vectorap2");//图标：进行中
        labels.add("yem_vectorap3");//图标：已终止
        labels.add("yem_vectorap4");//图标：未开始
    }

    @Override
    public void registerListener(EventObject e) {
        super.registerListener(e);
        ProgressBar progressBar = this.getControl(PROGRESS_BAR);
        progressBar.addProgressListener(this);
    }

    @Override
    public void onProgress(ProgressEvent progressEvent) {
        FormShowParameter formShowParameter = this.getView().getFormShowParameter();
        PageIdEnum billNo = PageIdEnum.getPageEnumById(formShowParameter.getCustomParam("billNo"));
        int progress = progressEvent.getProgress();
        ProgressBar progressBar = this.getControl(PROGRESS_BAR);
        String cacheProgress = this.getPageCache().get(PROGRESS_KEY);
        if (YEM.isNotEmpty(cacheProgress)) {
            progress = Integer.parseInt(cacheProgress);
        }
        if (progress >= 100) {
            if (PageIdEnum.CM_PYRAMID.equals(billNo)) {
                companyRiskAssessment();
            }
            if (PageIdEnum.MERCHANT_APPLY.equals(billNo)) {
                parentTabVisible();
            }
            progressEvent.setProgress(100);
            progressBar.stop();
            this.getPageCache().batchRemove(Arrays.asList(PROGRESS_KEY, TASK_START_TIME, TASK_INDEX));
        } else {
            this.getPageCache().put(PROGRESS_KEY, String.valueOf(progress + 10));
            progressEvent.setProgress(progress);
            String taskLogId = this.getView().getFormShowParameter().getCustomParam("taskLogId");
            DynamicObject taskItemLog = getTaskLog(taskLogId);
            DynamicObjectCollection logEntryEntity = taskItemLog.getDynamicObjectCollection("yem_entryentity");
            logEntryEntity.sort(new Comparator<DynamicObject>() {
                @Override
                public int compare(DynamicObject o1, DynamicObject o2) {
                    return o1.getInt("yem_ordernum") - o2.getInt("yem_ordernum");
                }
            });
            String strIndex = this.getPageCache().get(TASK_INDEX);
            int index = Integer.parseInt(strIndex == null ? "-1" : strIndex);
            //所有任务执行完成 或 有任务异常终止
            if (logEntryEntity.size() == index || index == -1) {
                if (PageIdEnum.CM_PYRAMID.equals(billNo)) {
                    companyRiskAssessment();
                }
                if (PageIdEnum.MERCHANT_APPLY.equals(billNo)) {
                    parentTabVisible();
                }
                this.getPageCache().batchRemove(Arrays.asList(PROGRESS_KEY, TASK_START_TIME, TASK_INDEX));
                progressEvent.setProgress(100);
                progressBar.stop();
                return;
            }
            multiTaskProcess(taskItemLog, index);
        }
    }

    @Override
    public void beforeBindData(EventObject e) {
        super.beforeBindData(e);
        IDataModel model = this.getModel();
        String taskLogId = this.getView().getFormShowParameter().getCustomParam("taskLogId");
        DynamicObject taskItemLog = getTaskLog(taskLogId);
        if (taskItemLog != null) {
            DynamicObjectCollection logEntryEntity = taskItemLog.getDynamicObjectCollection("yem_entryentity");
            if (logEntryEntity != null && !logEntryEntity.isEmpty()) {
                //创建卡片分录
                model.batchCreateNewEntryRow("yem_entryentity", logEntryEntity.size());
            }
        }
    }

    @Override
    public void afterBindData(EventObject e) {
        super.afterBindData(e);
        String taskLogId = this.getView().getFormShowParameter().getCustomParam("taskLogId");
        DynamicObject taskItemLog = getTaskLog(taskLogId);
        if (taskItemLog != null) {
            ThreadPools.executeOnce("taskItemLog", () -> {
                DynamicObjectCollection logEntryEntity = taskItemLog.getDynamicObjectCollection("yem_entryentity");
                logEntryEntity.sort(new Comparator<DynamicObject>() {
                    @Override
                    public int compare(DynamicObject o1, DynamicObject o2) {
                        return o1.getInt("yem_ordernum") - o2.getInt("yem_ordernum");
                    }
                });
                pageInitData(logEntryEntity);
            });
            ProgressBar progressBar = this.getControl(PROGRESS_BAR);
            progressBar.setPercent(0);
            start = System.currentTimeMillis();
            this.getPageCache().put(TASK_START_TIME, String.valueOf(start));
            this.getPageCache().put(TASK_INDEX, "0");
            this.getPageCache().put(PROGRESS_KEY, "0");
            progressBar.start();
        }
    }

    /**
     * 多任务页面数据刷新
     *
     * @Author yunshuaiwei
     * @Date 2024/5/30 9:10
     **/
    private void multiTaskProcess(DynamicObject taskItemLog, int index) {
        DynamicObjectCollection logEntryEntity = taskItemLog.getDynamicObjectCollection("yem_entryentity");
        //任务百分比
        Map<String, Object> percentMap = new HashMap<>();
        //耗时
        Map<String, Object> timeMap = new HashMap<>();
        Map<String, Object> map = new HashMap<>();
        //卡片分录控件
        CardEntry cardEntry = this.getControl("yem_entryentity");
        DynamicObject taskItem = logEntryEntity.get(index);
        //任务项
        DynamicObject task = taskItem.getDynamicObject("yem_basedatafield");
        //超时时间
        double timeOut = (double) task.getInt("yem_timeoutperiod") * 1000;
        //任务状态
        String status = taskItem.getString("yem_taskstatus");
        if (StringUtils.isNotEmpty(status)) {
            long startTime = Long.parseLong(this.getPageCache().get("startTime"));
            if (TaskLogStatusEnum.TASK_ING.getStatus().equals(status)) {//处理中
                //显示进行中标签
                cardVisible("yem_vectorap2", cardEntry, index);
                long endTime = System.currentTimeMillis();
                long time = endTime - startTime;
                int percent = (int) (time / timeOut * 100);
                percent = Math.min(percent, 99);
                percentMap.put("text", percent + "%");
                timeMap.put("text", timeFormat(time));
                map.put(LABEL_PERCENT, percentMap);
                map.put(LABEL_TIME, timeMap);
            }
            if (TaskLogStatusEnum.FINISHED.getStatus().equals(status)) {//已完成
                cardVisible("yem_vectorap", cardEntry, index);
                percentMap.put("text", "100%");
                long endTime = System.currentTimeMillis();
                long time = endTime - startTime;
                timeMap.put("text", timeFormat(time));
                map.put(LABEL_PERCENT, percentMap);
                map.put(LABEL_TIME, timeMap);
                //当前任务的结束时间为下个任务的开始时间
                this.getPageCache().put(TASK_START_TIME, String.valueOf(endTime));
                this.getPageCache().put(TASK_INDEX, String.valueOf(Integer.parseInt(this.getPageCache().get(TASK_INDEX)) + 1));
            }
            if (TaskLogStatusEnum.STOP.getStatus().equals(status)) {//已终止
                cardVisible("yem_vectorap3", cardEntry, index);
                long endTime = System.currentTimeMillis();
                long time = endTime - startTime;
                int percent = (int) (time / timeOut * 100);
                timeMap.put("text", timeFormat(time));
                percent = Math.min(percent, 99);
                percentMap.put("text", percent + "%");
                map.put(LABEL_PERCENT, percentMap);
                map.put(LABEL_TIME, timeMap);
                //当前任务的结束时间为下个任务的开始时间
                this.getPageCache().put(TASK_START_TIME, String.valueOf(endTime));
                this.getPageCache().put(TASK_INDEX, "-1");
            }
            updateCardStats(index, cardEntry, map);
        }
    }

    /**
     * 更新卡片属性
     *
     * @Author yunshuaiwei
     * @Date 2024/6/5 9:19
     **/
    private void updateCardStats(int index, CardEntry cardEntry, Map<String, Object> map) {
        long end = System.currentTimeMillis();
        long totalTime = end - start;
        long l = TimeUnit.MILLISECONDS.toSeconds(totalTime) % 60;
        Label label = this.getView().getControl(LABEL_TOTAL_TIME);
        label.setText("总耗时：" + l + "s" + (totalTime - (l * 1000)) + "ms");
        cardEntry.setCustomProperties(cardEntry.getKey(), index, map);
    }

    /**
     * 卡片页面初始化
     *
     * @Author yunshuaiwei
     * @Date 2024/5/30 11:03
     **/
    private void pageInitData(DynamicObjectCollection logEntryEntity) {
        //任务百分比
        Map<String, Object> percentMap = new HashMap<>();
        //耗时
        Map<String, Object> timeMap = new HashMap<>();
        CardEntry cardEntry = this.getControl("yem_entryentity");
        for (int i = 0; i < logEntryEntity.size(); i++) {
            //任务名称
            Map<String, Object> taskNameMap = new HashMap<>();
            Map<String, Object> map = new HashMap<>();
            DynamicObject taskItem = logEntryEntity.get(i);
            DynamicObject yemBaseData = taskItem.getDynamicObject("yem_basedatafield");
            taskNameMap.put("text", yemBaseData.getString("name"));
            timeMap.put("text", "耗时：0ms");
            percentMap.put("text", "0%");
            cardVisible("yem_vectorap4", cardEntry, i);
            //进度百分比
            map.put(LABEL_PERCENT, percentMap);
            //任务名称
            map.put(LABEL_TASK_NAME, taskNameMap);
            //耗时
            map.put(LABEL_TIME, timeMap);
            Label label = this.getView().getControl(LABEL_TOTAL_TIME);
            label.setText("总耗时：0s");
            cardEntry.setCustomProperties(cardEntry.getKey(), i, map);
        }
    }

    /**
     * 在企业风险评估页面内嵌客商准入
     *
     * @Author yunshuaiwei
     * @Date 2024/6/27 11:25
     **/
    private void openMerchantApplyLayout(IFormView parentView, Long merchantId) {
        Map<Object, DynamicObject> objectDynamicObjectMap = BusinessDataServiceHelper.loadFromCache(new Object[]{merchantId}, PageIdEnum.MERCHANT_APPLY.getPageId());
        DynamicObject object = objectDynamicObjectMap.get(merchantId);
        if (YEM.isNotEmpty(object)) {
            parentView.getModel().setValue("yem_keyno", object.get("yem_societycreditcode"));
            parentView.getModel().setValue("yem_registration", object.get("yem_registranumber"));
            parentView.getModel().setValue("yem_name", object.get("yem_nameqcc"));
        }
        Map<String, Object> maps = new HashMap<>();
        maps.put("merchantId", merchantId);
        BillCommonUtils.openTargetInContainerBill(parentView, maps, PageIdEnum.MERCHANT_APP_LAYOUT.getPageId(), "yem_flexpanelap11");
    }

    /**
     * 企业风险评估页面打开评分单
     * scoreId：评分单ID
     *
     * @Author yunshuaiwei
     * @Date 2024/6/27 11:26
     **/
    private void openMerchantScoreLayout(IFormView parentView, DynamicObject scoreMerchant) {
        Map<String, Object> map = new HashMap<>();
        Map<String, Object> tagMap = new HashMap<>();
        tagMap.put("text", map);
        DynamicObject scoringScheme = scoreMerchant.getDynamicObject("yem_scoringscheme");
        map.put("zh_CN", scoringScheme.getString("name"));
        parentView.updateControlMetadata("yem_tabpageap2", tagMap);
        //显示页签控件
        parentView.setVisible(true, "yem_tabap1");
        Map<String, Object> maps = new HashMap<>();
        maps.put("scoreId", scoreMerchant.getLong("id"));
        BillCommonUtils.openTargetInContainerBill(parentView, maps, PageIdEnum.SCORE_MERCHANT_LAYOUT.getPageId(), "yem_flexpanelap5");
    }

    /**
     * 耗时 格式化
     *
     * @Author yunshuaiwei
     * @Date 2024/5/30 17:44
     **/
    private String timeFormat(long ms) {
        long l = TimeUnit.MILLISECONDS.toSeconds(ms) % 60;
        return "耗时：" + l + "s" + (ms - (l * 1000)) + "ms";
    }

    /**
     * 控制卡片标签页签显隐
     *
     * @Author yunshuaiwei
     * @Date 2024/5/30 11:26
     **/
    private void cardVisible(String label, CardEntry cardEntry, int index) {
        for (String s : labels) {
            cardEntry.setChildVisible(s.equals(label), index, s);
        }
    }

    /**
     * 控制父页面页签显示
     *
     * @Author yunshuaiwei
     * @Date 2024/6/3 16:49
     **/
    private void parentTabVisible() {
        IFormView parentView = this.getView().getParentView();
        //显示父页面金字塔页签
        parentView.setVisible(true, "yem_tabpageap12");
        Tab tab = parentView.getControl("yem_tabap2");
        //切换金字塔页签
        tab.activeTab("yem_tabpageap12");
        pyramidPage(parentView, "yem_flexpanelap6", null);
        parentView.setEnable(true, "yem_societycreditcode", "yem_bar_dockingqcc", "yem_submitdothing");
        this.getView().sendFormAction(parentView);
    }

    /**
     * 企业风险评估页面逻辑处理
     *
     * @Author yunshuaiwei
     * @Date 2024/6/20 9:17
     **/
    private void companyRiskAssessment() {
        IFormView view = this.getView();
        IFormView parentView = view.getParentView();
        //显示父页面金字塔页签
        parentView.setVisible(true, "yem_tabpageap1");
        Tab tab = parentView.getControl("yem_tabap");
        //切换金字塔页签
        tab.activeTab("yem_tabpageap1");
        FormShowParameter formShowParameter = view.getFormShowParameter();
        Long merchantId = formShowParameter.getCustomParam("merchantId");
        String searchKey = formShowParameter.getCustomParam("searchKey");
        //评分方案ID
        Long scorePlan = formShowParameter.getCustomParam("scorePlan");
        DynamicObject scoreMerchant = BusinessDataServiceHelper.loadSingle(PageIdEnum.SCORE_MERCHANT.getPageId(), new QFilter[]{
                new QFilter("yem_societycreditcode", QCP.equals, searchKey),
                new QFilter("yem_scoringscheme", QCP.equals, scorePlan)});
        openMerchantApplyLayout(parentView, merchantId);
        if (YEM.isNotEmpty(scoreMerchant)) {
            pyramidPage(parentView, "yem_flexpanelap4", scoreMerchant.getLong("id"));
            openMerchantScoreLayout(parentView, scoreMerchant);
        }
        view.sendFormAction(parentView);
    }

    /**
     * 内嵌金字塔表单
     *
     * @Author yunshuaiwei
     * @Date 2024/6/6 14:09
     **/
    private void pyramidPage(IFormView parentView, String targetKey, Long id) {
        FormShowParameter formShowParameter = this.getView().getFormShowParameter();
        String searchKey = formShowParameter.getCustomParam("searchKey");
        StyleCss styleCss = new StyleCss();
        styleCss.setWidth("100%");
        styleCss.setHeight("100%");
        Map<String, Object> maps = new HashMap<>();
        maps.put("searchKey", searchKey);
        if (YEM.isNotEmpty(id)) {
            maps.put("id", id);
        }
        BillCommonUtils.openTargetInContainerBill(parentView, maps, PageIdEnum.SCORE_PYRAMID.getPageId(), targetKey, styleCss);
    }

    /**
     * 查询任务日志表数据
     *
     * @Author yunshuaiwei
     * @Date 2024/5/30 10:52
     **/
    private DynamicObject getTaskLog(String taskLogId) {
        if (YEM.isEmpty(taskLogId)) {
            log.error("任务日志ID为空");
            throw new KDBizException("查询任务日志表数据异常");
        }
        return BusinessDataServiceHelper.loadSingle(PageIdEnum.TASK_ITEM_LOG.getPageId(),
                "id,number,name,yem_entryentity.yem_taskstatus,yem_entryentity.yem_basedatafield,yem_entryentity.yem_ordernum", new QFilter[]{new QFilter("id", QCP.equals, Long.parseLong(taskLogId))});
    }
}