package cc.smtweb.framework.core.mvc.service;

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.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.ModelField;
import cc.smtweb.framework.core.db.vo.ModelIndex;
import cc.smtweb.framework.core.db.vo.ModelTable;
import cc.smtweb.framework.core.exception.BizException;
import org.apache.commons.lang3.StringUtils;

import java.util.List;

/**
 * Created by Akmm at 2022/3/2 19:52
 * 默认实体实现
 */
public class DefaultSaveHandler<T extends DefaultEntity> extends AbstractHandler {
    protected String tableName;
    protected T bean;

    private List<T> listTreeBean = null;

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

    public R save() {
        ModelTable table = ModelTableCache.getInstance().getByName(tableName);
        long id = params.readLong(table.getIdField());
        boolean isNew = params.readBool(DefaultEntity.statusKey) || id <= 0L;

        final EntityDao<T> dao = DbEngine.getInstance().findDao(tableName);
        if (isNew) {
            bean = dao.createBean(us.getUserId());
        } else {
            bean = dao.queryEntity(id);
        }
        readFromPage();
        if (bean.getEntityId() <= 0L) bean.setEntityId(DbEngine.getInstance().nextId());
        checkValid();
        DbEngine.getInstance().doTrans(new IDbWorker() {
            @Override
            public void work() {
                saveDb();
            }

            @Override
            public void doAfterDbCommit() {
                saveSuccess();
            }

            @Override
            public void doAfterDbRollback() {
                saveFailed();
            }
        });
        bean.removeStatus();
        return R.success(bean);
    }

    protected void readFromPage() {
        bean.readFromMap(params);
    }

    protected void checkValid() {
        ModelTable table = ModelTableCache.getInstance().getByName(tableName);
        for (ModelField field : table.getFields()) {
            if (field.isNotNull() && StringUtils.isEmpty(bean.getStr(field.getName()))) {
                throw new BizException(field.getTitle() + "不能为空！");
            }
            if (field.getFieldType() == SwEnum.FieldType.PARENT_ID.value) {
                TreeHelper.getTreeHelper(tableName).checkParent(bean);
            }
        }

        EntityDao dao = DbEngine.getInstance().findDao(tableName);
        for (ModelIndex mi : table.getIndexes()) {
            if (mi.isUnique()) {
                dao.checkUnique(bean, mi.getFields().split(","));
            }
        }
    }

    protected void saveDb() {
        EntityDao<T> dao = DbEngine.getInstance().findDao(tableName);
        if (bean.isNew()) {
            insertBean(dao);
        } else {
            ModelTable table = ModelTableCache.getInstance().getByName(tableName);
            ModelField field = table.findFieldByType(SwEnum.FieldType.UPDATE_USER.value);
            if (field != null) bean.put(field.getName(), us.getUserId());

            updateBean(dao);
            if (table.getType() == SwEnum.TableType.TYPE_TREE.value) {
                listTreeBean = TreeHelper.getTreeHelper(tableName).resetTreeLevel(bean);
            }
        }
    }

    //更新入库
    protected void updateBean(EntityDao<T> dao) {
        dao.updateEntity(bean);
    }

    //更新入库
    protected void insertBean(EntityDao<T> dao) {
        dao.insertEntity(bean);
    }


    protected void saveSuccess() {
        ModelTable table = ModelTableCache.getInstance().getByName(tableName);
        if (table.isNeedCache()) {
            AbstractCache<T> cache = CacheManager.getIntance().getCache(tableName);
            //树型表，父亲改变了，要多处理下缓存；还有个东东：级次码
            if (listTreeBean != null && !listTreeBean.isEmpty()) {
                for (T b : listTreeBean) {
                    cache.put(b);
                }
            } else {
                cache.put(bean);
            }
        }
    }

    protected void saveFailed() {
        ModelTable table = ModelTableCache.getInstance().getByName(tableName);
        if (table.isNeedCache()) {
            AbstractCache<T> cache = CacheManager.getIntance().getCache(tableName);
            cache.reset(bean);
        }
    }

    //树，改变父亲
    public R changeParent() {
        ModelTable table = ModelTableCache.getInstance().getByName(tableName);
        if (table.getType() != SwEnum.TableType.TYPE_TREE.value) throw new BizException("非树型表，不支持更改父节点");

        long id = params.readLong("id");
        long parentId = params.readLong("parent_id");

        final EntityDao<T> dao = DbEngine.getInstance().findDao(tableName);
        AbstractCache<T> cache = CacheManager.getIntance().getCache(tableName);
        if (table.isNeedCache()) {
            bean = cache.get(id);
        } else {
            bean = dao.queryEntity(id);
        }
        TreeHelper.getTreeHelper(tableName).checkParent(bean);
        //不考虑没有级次码等情况，这个在表设计时校验
        ModelField fieldParentId = table.findFieldByType(SwEnum.FieldType.PARENT_ID.value);

        bean.put(fieldParentId.getName(), parentId);
        DbEngine.getInstance().doTrans(new IDbWorker() {
            @Override
            public void work() {
                listTreeBean = TreeHelper.getTreeHelper(tableName).resetTreeLevel(bean);
                dao.updateEntity(bean, fieldParentId.getName());
            }

            @Override
            public void doAfterDbCommit() {
                saveSuccess();
            }

            @Override
            public void doAfterDbRollback() {
                saveFailed();
            }
        });
        return R.success();
    }
}
