package cc.smtweb.system.bpm.web.engine.dynPage;

import cc.smtweb.framework.core.cache.AbstractCache;
import cc.smtweb.framework.core.cache.CacheManager;
import cc.smtweb.framework.core.common.R;
import cc.smtweb.framework.core.common.SwEnum;
import cc.smtweb.framework.core.db.DbEngine;
import cc.smtweb.framework.core.db.EntityDao;
import cc.smtweb.framework.core.db.EntityHelper;
import cc.smtweb.framework.core.db.cache.ModelTableCache;
import cc.smtweb.framework.core.db.impl.DefaultEntity;
import cc.smtweb.framework.core.db.jdbc.IDbWorker;
import cc.smtweb.framework.core.db.vo.ModelTable;
import cc.smtweb.framework.core.exception.BizException;
import cc.smtweb.system.bpm.web.design.form.define.PageDataset;
import cc.smtweb.system.bpm.web.design.form.define.PageDatasetFilter;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by Akmm at 2022/4/21 17:53
 * 删除操作
 */
public class DynPageDelHandler extends AbstractDynPageHandler {
    /**
     * 删除指定数据集，入参{pageId, dataset, id}
     *
     * @return
     */
    public R delOne() {
        long id = params.readLong("id");
        if (id == 0) throw new BizException("没有收到待删除记录Id(" + id + ")！");
        //数据集
        PageDataset pageDataSet = readParamDs();

        checkBean(pageDataSet, id);

        DbEngine.getInstance().doTrans(new IDbWorker() {
            @Override
            public void work() {
                ModelTable table = ModelTableCache.getInstance().get(pageDataSet.masterTable);
                if (table == null) throw new BizException("没有找到指定的的表定义：" + pageDataSet.name + "！");
                EntityDao dao = DbEngine.getInstance().findDao(table.getName());
                dao.deleteEntity(id);
                localDel(id, table);
            }

            @Override
            public void doAfterDbCommit() {
                ModelTable table = ModelTableCache.getInstance().get(pageDataSet.masterTable);
                if (table.isNeedCache()) {
                    AbstractCache cache = CacheManager.getIntance().getCache(table.getName());
                    cache.remove(id);
                }
                localDelSuccess(id, table);
            }
        });
        return R.success();
    }

    protected void localDel(long id, ModelTable table) {

    }

    protected void localDelSuccess(long id, ModelTable table) {

    }

    public R delAll() {
        long id = params.readLong("id");
        if (id == 0) throw new BizException("没有收到待删除记录Id(" + id + ")！");
        //校验主表即可
        PageDataset masterDs = findMasterDataset();
        if (masterDs == null || !masterDs.canEdit || !SwEnum.DatasetType.FORM.value.equals(masterDs.type))
            throw new BizException("主表不允许删除！");
        checkBean(masterDs, id);

        Map<String, RemovableInfo> mapRemovableInfo = new HashMap<>();
        for (PageDataset pageDataSet : datasets.list) {
            //非表单编辑，不管
            if (!pageDataSet.canEdit || !SwEnum.DatasetType.FORM.value.equals(pageDataSet.type)) continue;
            ModelTable table = ModelTableCache.getInstance().get(pageDataSet.masterTable);
            RemovableInfo info = mapRemovableInfo.computeIfAbsent(table.getName(), k -> {
                RemovableInfo ret = new RemovableInfo(k);
                if (pageDataSet != masterDs) {//非主表，记录一下关联字段
                    PageDatasetFilter f = pageDataSet.findFilterByDs(masterDs.name);
                    if (f == null) {
                        throw new BizException("无法删除表【" + pageDataSet.name + "】，此表未关联主表！");
                    }
                    ret.field = f.field;
                }
                return ret;
            });

            if (pageDataSet == masterDs || !table.isNeedCache()) {
                //主表或没有缓存，直接按FK删除
                info.addId(id);
            } else {
                info.needCache = true;
                //有缓存，需要先把id查出来
                EntityDao<DefaultEntity> dao = DbEngine.getInstance().findDao(table.getName());
                List<Long> list = dao.queryIdListWhere(info.field + " = ?", id);
                info.ids.addAll(list);
            }
        }
        DbEngine.getInstance().doTrans(new IDbWorker() {
            @Override
            public void work() {
                for (RemovableInfo info : mapRemovableInfo.values()) {
                    EntityDao<DefaultEntity> dao = DbEngine.getInstance().findDao(info.tableName);
                    if (!info.needCache && StringUtils.isNotEmpty(info.field)) {
                        //按外键来删除
                        dao.deleteEntity(" where " + info.field + "=?", id);
                    } else {
                        dao.deleteEntity(info.ids);
                    }
                }
            }

            @Override
            public void doAfterDbCommit() {
                for (RemovableInfo info : mapRemovableInfo.values()) {
                    if (!info.needCache) continue;
                    AbstractCache cache = CacheManager.getIntance().getCache(info.tableName);
                    cache.remove(id);

                }
            }
        });
        return R.success();
    }

    /**
     * 删除校验
     *
     * @param pageDataSet
     * @param id
     */
    protected void checkBean(PageDataset pageDataSet, long id) {
        //校验外键引用关系
        EntityHelper.checkExists(pageDataSet.masterTable, id);
    }

    /**
     * 待删除信息
     */
    class RemovableInfo {
        String tableName;
        String field = null;
        boolean needCache = false;
        List<Long> ids = new ArrayList<>();

        public RemovableInfo(String tableName) {
            this.tableName = tableName;
        }

        void addId(long id) {
            ids.add(id);
        }
    }
}
