package com.yunzhupaas.onlinedev.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yunzhupaas.base.ActionResult;
import com.yunzhupaas.base.UserInfo;
import com.yunzhupaas.base.entity.ModuleEntity;
import com.yunzhupaas.base.entity.VisualdevEntity;
import com.yunzhupaas.base.entity.VisualdevReleaseEntity;
import com.yunzhupaas.base.mapper.FlowFormDataMapper;
import com.yunzhupaas.base.model.*;
import com.yunzhupaas.base.model.OnlineImport.VisualdevModelDataInfoVO;
import com.yunzhupaas.base.model.flow.DataModel;
import com.yunzhupaas.base.model.flow.FlowFormDataModel;
import com.yunzhupaas.base.model.form.ModuleFormModel;
import com.yunzhupaas.base.model.module.PropertyJsonModel;
import com.yunzhupaas.base.service.DbLinkService;
import com.yunzhupaas.base.service.ModuleService;
import com.yunzhupaas.base.service.SuperServiceImpl;
import com.yunzhupaas.base.service.VisualdevReleaseService;
import com.yunzhupaas.base.util.FlowFormDataUtil;
import com.yunzhupaas.base.util.FormCheckUtils;
import com.yunzhupaas.constant.MsgCode;
import com.yunzhupaas.database.model.entity.DbLinkEntity;
import com.yunzhupaas.database.model.superQuery.SuperJsonModel;
import com.yunzhupaas.database.model.superQuery.SuperQueryJsonModel;
import com.yunzhupaas.database.util.ConnUtil;
import com.yunzhupaas.database.util.DynamicDataSourceUtil;
import com.yunzhupaas.exception.DataException;
import com.yunzhupaas.exception.WorkFlowException;
import com.yunzhupaas.flowable.entity.TaskEntity;
import com.yunzhupaas.model.OnlineDevData;
import com.yunzhupaas.model.visualJson.FieLdsModel;
import com.yunzhupaas.model.visualJson.FormCloumnUtil;
import com.yunzhupaas.model.visualJson.FormDataModel;
import com.yunzhupaas.model.visualJson.TableModel;
import com.yunzhupaas.model.visualJson.analysis.FormAllModel;
import com.yunzhupaas.model.visualJson.analysis.FormModel;
import com.yunzhupaas.model.visualJson.analysis.RecursionForm;
import com.yunzhupaas.onlinedev.entity.VisualdevModelDataEntity;
import com.yunzhupaas.onlinedev.mapper.VisualdevModelDataMapper;
import com.yunzhupaas.onlinedev.model.OnlineDevListModel.VisualColumnSearchVO;
import com.yunzhupaas.onlinedev.model.OnlineInfoModel;
import com.yunzhupaas.onlinedev.model.PaginationModel;
import com.yunzhupaas.onlinedev.model.PaginationModelExport;
import com.yunzhupaas.onlinedev.model.VisualParamModel;
import com.yunzhupaas.onlinedev.model.log.VisualLogForm;
import com.yunzhupaas.onlinedev.service.VisualDevInfoService;
import com.yunzhupaas.onlinedev.service.VisualDevListService;
import com.yunzhupaas.onlinedev.service.VisualLogService;
import com.yunzhupaas.onlinedev.service.VisualdevModelDataService;
import com.yunzhupaas.onlinedev.util.onlineDevUtil.OnlineDevInfoUtils;
import com.yunzhupaas.onlinedev.util.onlineDevUtil.OnlineProductSqlUtils;
import com.yunzhupaas.onlinedev.util.onlineDevUtil.OnlinePublicUtils;
import com.yunzhupaas.onlinedev.util.onlineDevUtil.OnlineSwapDataUtils;
import com.yunzhupaas.permission.entity.UserEntity;
import com.yunzhupaas.permission.model.authorize.OnlineDynamicSqlModel;
import com.yunzhupaas.permission.service.UserService;
import com.yunzhupaas.permissions.PermissionInterfaceImpl;
import com.yunzhupaas.util.*;
import com.yunzhupaas.util.context.RequestContext;
import com.yunzhupaas.util.visiual.YunzhupaasKeyConsts;
import com.yunzhupaas.workflow.service.TaskApi;
import com.yunzhupaas.workflow.service.TemplateApi;
import lombok.Cleanup;
import org.mybatis.dynamic.sql.SqlBuilder;
import org.mybatis.dynamic.sql.SqlTable;
import org.mybatis.dynamic.sql.delete.DeleteDSL;
import org.mybatis.dynamic.sql.delete.DeleteModel;
import org.mybatis.dynamic.sql.render.RenderingStrategies;
import org.mybatis.dynamic.sql.select.QueryExpressionDSL;
import org.mybatis.dynamic.sql.select.SelectModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import java.text.ParseException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 云筑产品开发平台组
 * @version V3.1.0
 * @copyright 深圳市乐程软件有限公司（http://www.szlecheng.cn）
 * @date 2024/3/16
 */
@Service
public class VisualdevModelDataServiceImpl extends SuperServiceImpl<VisualdevModelDataMapper, VisualdevModelDataEntity>
        implements VisualdevModelDataService {

    @Autowired
    private UserService userApi;
    @Autowired
    private DbLinkService dblinkService;
    @Autowired
    private VisualdevReleaseService visualdevReleaseService;
    @Autowired
    private VisualDevListService visualDevListService;
    @Autowired
    private OnlineSwapDataUtils onlineSwapDataUtils;
    @Autowired
    private OnlineDevInfoUtils onlineDevInfoUtils;
    @Autowired
    private FlowFormDataUtil flowFormDataUtil;
    @Autowired
    private FormCheckUtils formCheckUtils;
    @Autowired
    private TemplateApi templateApi;
    @Autowired
    private TaskApi taskApi;
    @Autowired
    private ModuleService moduleService;
    @Autowired
    private VisualLogService visualLogService;
    @Autowired
    private VisualDevInfoService visualDevInfoService;
    @Autowired
    private FlowFormDataMapper flowFormDataMapper;

    @Override
    public List<VisualdevModelDataEntity> getList(String modelId) {
        QueryWrapper<VisualdevModelDataEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(VisualdevModelDataEntity::getVisualDevId, modelId);
        return this.list(queryWrapper);
    }

    /**
     * 表单字段
     *
     * @param id
     * @param filterType 过滤类型，0或者不传为默认过滤子表和关联表单，1-弹窗配置需要过滤掉的类型
     * @return
     */
    @Override
    public List<FormDataField> fieldList(String id, Integer filterType) {
        VisualdevReleaseEntity entity = visualdevReleaseService.getById(id);
        FormDataModel formData = JsonUtil.getJsonToBean(entity.getFormData(), FormDataModel.class);

        List<FieLdsModel> fieLdsModelList = JsonUtil.getJsonToList(formData.getFields(), FieLdsModel.class);
        List<FieLdsModel> mainFieldModelList = new ArrayList<>();

        OnlinePublicUtils.recursionFields(mainFieldModelList, fieLdsModelList);
        // 过滤掉无法传递的组件
        List<String> notInList = new ArrayList<>();
        notInList.add(YunzhupaasKeyConsts.RELATIONFORM);
        notInList.add(YunzhupaasKeyConsts.CHILD_TABLE);
        if (Objects.equals(filterType, 1)) {
            notInList.add("link");
            notInList.add("button");
            notInList.add("YUNZHUPAASText");
            notInList.add("alert");
            notInList.add(YunzhupaasKeyConsts.POPUPSELECT);
            notInList.add(YunzhupaasKeyConsts.QR_CODE);
            notInList.add(YunzhupaasKeyConsts.BARCODE);
            notInList.add(YunzhupaasKeyConsts.CREATEUSER);
            notInList.add(YunzhupaasKeyConsts.CREATETIME);
            notInList.add(YunzhupaasKeyConsts.UPLOADIMG);
            notInList.add(YunzhupaasKeyConsts.UPLOADFZ);
            notInList.add(YunzhupaasKeyConsts.MODIFYUSER);
            notInList.add(YunzhupaasKeyConsts.MODIFYTIME);

            notInList.add(YunzhupaasKeyConsts.CURRORGANIZE);
            notInList.add(YunzhupaasKeyConsts.CURRPOSITION);
            notInList.add(YunzhupaasKeyConsts.IFRAME);
            notInList.add(YunzhupaasKeyConsts.RELATIONFORM_ATTR);
            notInList.add(YunzhupaasKeyConsts.POPUPSELECT_ATTR);
        }

        List<FormDataField> formDataFieldList = mainFieldModelList.stream()
                .filter(fieLdsModel -> !"".equals(fieLdsModel.getVModel())
                        && StringUtil.isNotEmpty(fieLdsModel.getVModel())
                        && !notInList.contains(fieLdsModel.getConfig().getYunzhupaasKey()))
                .map(fieLdsModel -> {
                    FormDataField formDataField = new FormDataField();
                    formDataField.setLabel(fieLdsModel.getConfig().getLabel());
                    formDataField.setVModel(fieLdsModel.getVModel());
                    return formDataField;
                }).collect(Collectors.toList());

        return formDataFieldList;
    }

    @Override
    public List<Map<String, Object>> getPageList(VisualdevEntity entity, PaginationModel paginationModel) {
        // String json = null;
        // if (StringUtil.isNotEmpty(paginationModel.getKeyword())) {
        // Map<String, Object> map = new HashMap<>();
        // map.put(paginationModel.getRelationField(), paginationModel.getKeyword());
        // json = JsonUtil.getObjectToString(map);
        // }
        // paginationModel.setQueryJson(json);
        VisualDevJsonModel visualJsonModel = OnlinePublicUtils.getVisualJsonModel(entity);

        // 判断请求客户端来源
        if (!RequestContext.isOrignPc()) {
            visualJsonModel.setColumnData(visualJsonModel.getAppColumnData());
        }
        List<Map<String, Object>> dataList = visualDevListService.getRelationFormList(visualJsonModel, paginationModel);
        return dataList;
    }

    @Override
    public List<Map<String, Object>> exportData(String[] keys, PaginationModelExport paginationModelExport,
            VisualDevJsonModel visualDevJsonModel) {
        PaginationModel paginationModel = new PaginationModel();
        BeanUtil.copyProperties(paginationModelExport, paginationModel);
        List<String> keyList = Arrays.asList(keys);
        List<Map<String, Object>> noSwapDataList;
        ColumnDataModel columnDataModel = visualDevJsonModel.getColumnData();
        List<VisualColumnSearchVO> searchVOList = new ArrayList<>();
        List<TableModel> visualTables = visualDevJsonModel.getVisualTables();
        TableModel mainTable = visualTables.stream().filter(vi -> vi.getTypeId().equals("1")).findFirst().orElse(null);
        // 解析控件
        FormDataModel formDataModel = visualDevJsonModel.getFormData();
        List<FieLdsModel> fieLdsModels = JsonUtil.getJsonToList(formDataModel.getFields(), FieLdsModel.class);
        RecursionForm recursionForm = new RecursionForm(fieLdsModels, visualTables);
        List<FormAllModel> formAllModel = new ArrayList<>();
        FormCloumnUtil.recursionForm(recursionForm, formAllModel);
        // 封装查询条件
        if (StringUtil.isNotEmpty(paginationModel.getQueryJson())) {
            Map<String, Object> keyJsonMap = JsonUtil.stringToMap(paginationModel.getQueryJson());
            searchVOList = JsonUtil.getJsonToList(columnDataModel.getSearchList(), VisualColumnSearchVO.class);
            searchVOList = searchVOList.stream().map(searchVO -> {
                searchVO.setValue(keyJsonMap.get(searchVO.getId()));
                return searchVO;
            }).filter(vo -> vo.getValue() != null && StringUtil.isNotEmpty(String.valueOf(vo.getValue())))
                    .collect(Collectors.toList());
            // 左侧树查询
            boolean b = false;
            if (columnDataModel.getTreeRelation() != null) {
                b = keyJsonMap.keySet().stream()
                        .anyMatch(t -> t.equalsIgnoreCase(String.valueOf(columnDataModel.getTreeRelation())));
            }
            if (b && keyJsonMap.size() > searchVOList.size()) {
                String relation = String.valueOf(columnDataModel.getTreeRelation());
                VisualColumnSearchVO vo = new VisualColumnSearchVO();
                vo.setSearchType("1");
                vo.setVModel(relation);
                vo.setValue(keyJsonMap.get(relation));
                searchVOList.add(vo);
            }
        }
        // 菜单id
        String menuId = paginationModel.getMenuId();
        // 菜单判断是否启用流程-添加流程状态
        ModuleEntity info = moduleService.getInfo(menuId);
        if (info != null) {
            // 流程菜单
            boolean enableFlow = Objects.equals(info.getType(), 9);
            visualDevJsonModel.setEnableFlow(enableFlow);
            if (enableFlow) {
                PropertyJsonModel model = JsonUtil.getJsonToBean(info.getPropertyJson(), PropertyJsonModel.class);
                List<String> flowVersionIds = templateApi.getFlowIdsByTemplateId(model.getModuleId());
                visualDevJsonModel.setFlowId(model.getModuleId());
                visualDevJsonModel.setFlowVersionIds(flowVersionIds);
            }
        }

        if (visualDevJsonModel.getVisualTables().size() > 0) {
            // 当前用户信息
            UserInfo userInfo = UserProvider.getUser();
            // 封装搜索数据
            OnlineProductSqlUtils.queryList(formAllModel, visualDevJsonModel, paginationModel);
            noSwapDataList = visualDevListService.getListWithTable(visualDevJsonModel, paginationModel, userInfo,
                    keyList);
        } else {
            noSwapDataList = visualDevListService.getWithoutTableData(visualDevJsonModel.getId());
            noSwapDataList = visualDevListService.getList(noSwapDataList, searchVOList, paginationModel);
        }

        // 数据转换
        List<FieLdsModel> fields = new ArrayList<>();
        OnlinePublicUtils.recursionFields(fields, fieLdsModels);
        noSwapDataList = onlineSwapDataUtils.getSwapList(noSwapDataList, fields, visualDevJsonModel.getId(), false);

        return noSwapDataList;
    }

    @Override
    public VisualdevModelDataEntity getInfo(String id) {
        QueryWrapper<VisualdevModelDataEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(VisualdevModelDataEntity::getId, id);
        return this.getOne(queryWrapper);
    }

    @Override
    public VisualdevModelDataInfoVO infoDataChange(String id, VisualdevEntity visualdevEntity)
            throws IOException, ParseException, DataException, SQLException {
        FormDataModel formDataModel = JsonUtil.getJsonToBean(visualdevEntity.getFormData(), FormDataModel.class);
        List<FieLdsModel> modelList = JsonUtil.getJsonToList(formDataModel.getFields(), FieLdsModel.class);

        VisualdevModelDataEntity visualdevModelDataEntity = this.getInfo(id);

        List<FieLdsModel> childFieldModelList = new ArrayList<>();
        List<FieLdsModel> mainFieldModelList = new ArrayList<>();
        // 二维码 条形码
        List<FormModel> models = new ArrayList<>();
        OnlinePublicUtils.recurseFiled(modelList, mainFieldModelList, childFieldModelList, models);

        if (visualdevModelDataEntity != null) {
            Map<String, Object> DataMap = JsonUtil.stringToMap(visualdevModelDataEntity.getData());
            Map<String, Object> childTableMap = DataMap.entrySet().stream()
                    .filter(m -> m.getKey().contains("tableField"))
                    .collect(Collectors.toMap((e) -> (String) e.getKey(),
                            (e) -> ObjectUtil.isNotEmpty(e.getValue()) ? e.getValue() : ""));
            Map<String, Object> mainTableMap = DataMap.entrySet().stream()
                    .filter(m -> !m.getKey().contains("tableField"))
                    .collect(Collectors.toMap((e) -> (String) e.getKey(),
                            (e) -> ObjectUtil.isNotEmpty(e.getValue()) ? e.getValue() : ""));
            mainTableMap = onlineDevInfoUtils.swapChildTableDataInfo(mainFieldModelList, mainTableMap, models);

            for (Map.Entry<String, Object> entry : childTableMap.entrySet()) {
                List<Map<String, Object>> listMap = JsonUtil.getJsonToListMap(String.valueOf(entry.getValue()));
                FieLdsModel fieLdsModel = childFieldModelList.stream()
                        .filter(child -> child.getVModel().equalsIgnoreCase(entry.getKey())).findFirst().orElse(null);
                if (ObjectUtil.isNotEmpty(fieLdsModel)) {
                    List<Map<String, Object>> tableValueList = new ArrayList<>();
                    if (Objects.nonNull(listMap)) {
                        for (Map<String, Object> map : listMap) {
                            Map<String, Object> childFieldMap = onlineDevInfoUtils
                                    .swapChildTableDataInfo(fieLdsModel.getConfig().getChildren(), map, models);
                            tableValueList.add(childFieldMap);
                        }
                    }
                    Map<String, Object> childFieldsMap = new HashMap<>();
                    childFieldsMap.put(entry.getKey(), tableValueList);
                    mainTableMap.putAll(childFieldsMap);
                }
            }
            String objectToString = JsonUtilEx.getObjectToString(mainTableMap);
            VisualdevModelDataInfoVO vo = new VisualdevModelDataInfoVO();
            vo.setData(objectToString);
            vo.setId(id);
            return vo;
        }
        return null;
    }

    @Override
    public DataModel visualCreate(VisualParamModel visualParamModel) throws Exception {
        VisualdevEntity visualdevEntity = visualParamModel.getVisualdevEntity();
        Map<String, Object> map = visualParamModel.getData();
        boolean isLink = visualParamModel.getIsLink();
        boolean isUpload = visualParamModel.getIsUpload();
        FormDataModel formData = JsonUtil.getJsonToBean(visualdevEntity.getFormData(), FormDataModel.class);
        ColumnDataModel columnDataModel = JsonUtil.getJsonToBean(visualdevEntity.getColumnData(),
                ColumnDataModel.class);
        Boolean needP = false;
        List<String> formPerList = new ArrayList<>();
        if (columnDataModel != null && StringUtil.isNotEmpty(visualParamModel.getMenuId())) {
            needP = columnDataModel.getUseFormPermission();
            Map<String, Object> pMap = PermissionInterfaceImpl.getFormMap();
            if (pMap.get(visualParamModel.getMenuId()) != null) {
                formPerList = JsonUtil.getJsonToList(pMap.get(visualParamModel.getMenuId()), ModuleFormModel.class)
                        .stream()
                        .map(ModuleFormModel::getEnCode).collect(Collectors.toList());
            }
        }
        List<FieLdsModel> list = JsonUtil.getJsonToList(formData.getFields(), FieLdsModel.class);
        List<TableModel> tableModels = JsonUtil.getJsonToList(visualdevEntity.getVisualTables(), TableModel.class);
        DbLinkEntity linkEntity = StringUtil.isNotEmpty(visualdevEntity.getDbLinkId())
                ? dblinkService.getInfo(visualdevEntity.getDbLinkId())
                : null;

        // 递归遍历模板
        RecursionForm recursionForm = new RecursionForm(list, tableModels);
        List<FormAllModel> formAllModel = new ArrayList<>();
        FormCloumnUtil.recursionForm(recursionForm, formAllModel);
        // 是否开启并发锁
        Boolean concurrency = false;
        Integer primaryKeyPolicy = formData.getPrimaryKeyPolicy();
        if (formData.getConcurrencyLock()) {
            // 初始化version值
            map.put(TableFeildsEnum.VERSION.getField(), 0);
            concurrency = true;
        }
        OnlineSwapDataUtils.swapDatetime(list, map);
        // 单行唯一校验
        if (!isUpload) {
            CheckFormModel checkFormModel = CheckFormModel.builder().formFieldList(list).dataMap(map)
                    .linkEntity(linkEntity).tableModelList(tableModels)
                    .visualdevEntity(visualdevEntity).id(null).isLink(isLink).build();
            String b = formCheckUtils.checkForm(checkFormModel);
            if (StringUtil.isNotEmpty(b)) {
                throw new WorkFlowException(b);
            }
        }
        String mainId = RandomUtil.uuId();
        UserInfo userInfo = UserProvider.getUser();
        UserEntity info = userApi.getInfo(userInfo.getUserId());
        DataModel dataModel = DataModel.builder().visualId(visualdevEntity.getId())
                .dataNewMap(map).fieLdsModelList(list).tableModelList(tableModels).formAllModel(formAllModel)
                .mainId(mainId).link(linkEntity).userEntity(info).concurrencyLock(concurrency)
                .primaryKeyPolicy(primaryKeyPolicy).linkOpen(isLink)
                .needPermission(needP).formPerList(formPerList)
                .build();
        flowFormDataUtil.create(dataModel);

        // 数据日志
        if (formData.isDataLog() && !isUpload && !isLink) {
            visualLogService.createEventLog(VisualLogForm.builder().modelId(visualdevEntity.getId())
                    .dataId(dataModel.getMainId()).newData(map).type(0).build());
        }
        return dataModel;
    }

    @Override
    public DataModel visualUpdate(VisualParamModel visualParamModel) throws Exception {
        VisualdevEntity visualdevEntity = visualParamModel.getVisualdevEntity();
        Map<String, Object> map = visualParamModel.getData();
        String id = visualParamModel.getId();
        boolean isUpload = visualParamModel.getIsUpload();
        boolean onlyUpdate = visualParamModel.getOnlyUpdate();
        ColumnDataModel columnDataModel = JsonUtil.getJsonToBean(visualdevEntity.getColumnData(),
                ColumnDataModel.class);
        FormDataModel formData = JsonUtil.getJsonToBean(visualdevEntity.getFormData(), FormDataModel.class);
        Boolean needP = false;
        List<String> formPerList = new ArrayList<>();
        if (columnDataModel != null && StringUtil.isNotEmpty(visualParamModel.getMenuId())) {
            needP = columnDataModel.getUseFormPermission();
            Map<String, Object> pMap = PermissionInterfaceImpl.getFormMap();
            if (pMap.get(visualParamModel.getMenuId()) != null) {
                formPerList = JsonUtil.getJsonToList(pMap.get(visualParamModel.getMenuId()), ModuleFormModel.class)
                        .stream()
                        .map(ModuleFormModel::getEnCode).collect(Collectors.toList());
            }
        }
        List<FieLdsModel> list = JsonUtil.getJsonToList(formData.getFields(), FieLdsModel.class);
        boolean inlineEdit = columnDataModel.getType() != null && columnDataModel.getType() == 4;
        if (inlineEdit && RequestContext.isOrignPc()) {
            list = JsonUtil.getJsonToList(columnDataModel.getColumnList(), FieLdsModel.class);
            list = list.stream().filter(f -> !f.getId().toLowerCase().contains(YunzhupaasKeyConsts.CHILD_TABLE_PREFIX))
                    .collect(Collectors.toList());
        }
        List<TableModel> tableModels = JsonUtil.getJsonToList(visualdevEntity.getVisualTables(), TableModel.class);
        TableModel mainT = tableModels.stream().filter(t -> t.getTypeId().equals("1")).findFirst().orElse(null);
        DbLinkEntity linkEntity = StringUtil.isNotEmpty(visualdevEntity.getDbLinkId())
                ? dblinkService.getInfo(visualdevEntity.getDbLinkId())
                : null;

        // 递归遍历模板
        RecursionForm recursionForm = new RecursionForm(list, tableModels);
        List<FormAllModel> formAllModel = new ArrayList<>();
        FormCloumnUtil.recursionForm(recursionForm, formAllModel);
        // 是否开启并发锁
        Boolean isConcurrencyLock = false;
        Integer primaryKeyPolicy = formData.getPrimaryKeyPolicy();
        if (formData.getConcurrencyLock()) {
            if (map.get(TableFeildsEnum.VERSION.getField()) == null) {
                map.put(TableFeildsEnum.VERSION.getField(), 0);
            } else {
                boolean version = true;
                try {
                    Object realId = id;
                    if (Objects.equals(primaryKeyPolicy, 2)) {
                        realId = Long.parseLong(id);
                    }
                    version = flowFormDataUtil.getVersion(mainT.getTable(), linkEntity, map, realId);
                } catch (Exception e) {
                    throw new WorkFlowException(e.getMessage(), e);
                }
                if (!version) {
                    throw new WorkFlowException(MsgCode.VS405.get());
                } else {
                    Integer vs = Integer.valueOf(String.valueOf(map.get(TableFeildsEnum.VERSION.getField())));
                    map.put(TableFeildsEnum.VERSION.getField(), vs + 1);
                }
            }
            isConcurrencyLock = true;
        }
        OnlineSwapDataUtils.swapDatetime(list, map);
        // 单行唯一校验
        if (!isUpload) {
            CheckFormModel checkFormModel = CheckFormModel.builder().formFieldList(list).dataMap(map)
                    .linkEntity(linkEntity).tableModelList(tableModels)
                    .visualdevEntity(visualdevEntity).id(id).build();
            String b = formCheckUtils.checkForm(checkFormModel);
            if (StringUtil.isNotEmpty(b)) {
                throw new WorkFlowException(b);
            }
        }

        // 数据日志
        VisualdevModelDataInfoVO resOld = visualDevInfoService.getDetailsDataInfo(id, visualdevEntity,
                OnlineInfoModel.builder().needRlationFiled(true).needSwap(false).formAllModel(formAllModel).build());
        Map<String, Object> oldData = JsonUtil.stringToMap(resOld.getData());

        UserInfo userInfo = UserProvider.getUser();
        UserEntity info = userApi.getInfo(userInfo.getUserId());
        DataModel dataModel = DataModel.builder().visualId(visualdevEntity.getId())
                .dataNewMap(map).fieLdsModelList(list).tableModelList(tableModels).formAllModel(formAllModel)
                .mainId(id).link(linkEntity).userEntity(info).concurrencyLock(isConcurrencyLock)
                .primaryKeyPolicy(primaryKeyPolicy).onlyUpdate(onlyUpdate).logicalDelete(formData.getLogicalDelete())
                .needPermission(needP).formPerList(formPerList)
                .build();
        flowFormDataUtil.update(dataModel);
        VisualdevModelDataInfoVO res = visualDevInfoService.getDetailsDataInfo(id, visualdevEntity,
                OnlineInfoModel.builder().needRlationFiled(true).needSwap(false).formAllModel(formAllModel).build());
        Map<String, Object> newData = JsonUtil.stringToMap(res.getData());
        VisualLogForm form = VisualLogForm.builder().modelId(visualdevEntity.getId()).dataId(id).oldData(oldData)
                .newData(newData).type(1).build();
        // 处理变更字段信息-任务流程用
        List<VisualLogModel> listLog = new ArrayList<>();
        visualLogService.addLog(form, listLog);
        dataModel.setListLog(listLog);
        // 数据日志
        if (formData.isDataLog() && !isUpload) {
            form.setListLog(listLog);
            visualLogService.createEventLog(form);
        }
        return dataModel;
    }

    @Override
    public void visualDelete(VisualdevEntity visualdevEntity, List<Map<String, Object>> data) throws Exception {
        VisualDevJsonModel visualJsonModel = OnlinePublicUtils.getVisualJsonModel(visualdevEntity);
        // 判断请求客户端来源
        if (!RequestContext.isOrignPc()) {
            visualJsonModel.setColumnData(visualJsonModel.getAppColumnData());
        }
        List<String> idsList = new ArrayList<>();
        StringJoiner errMess = new StringJoiner(",");
        // todo 流程关联
        for (Map<String, Object> map : data) {
            String id = String.valueOf(map.get(FlowFormConstant.ID));
            TaskEntity taskEntity = taskApi.getInfoSubmit(String.valueOf(map.get(FlowFormConstant.FLOWTASKID)),
                    TaskEntity::getId,
                    TaskEntity::getParentId, TaskEntity::getFullName, TaskEntity::getStatus);
            if (taskEntity != null) {
                try {
                    taskApi.delete(taskEntity);
                    idsList.add(id);
                } catch (Exception e) {
                    errMess.add(e.getMessage());
                }
            } else {
                idsList.add(id);
            }
        }
        if (idsList.size() == 0) {
            throw new WorkFlowException(errMess.toString());
        }
        if (!StringUtil.isEmpty(visualdevEntity.getVisualTables())
                && !OnlineDevData.TABLE_CONST.equals(visualdevEntity.getVisualTables())) {
            for (String id : idsList) {
                try {
                    tableDelete(id, visualJsonModel);
                } catch (Exception e) {
                    throw new WorkFlowException(e.getMessage(), e);
                }
            }
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(VisualdevModelDataEntity entity) {
        if (entity != null) {
            this.removeById(entity.getId());
        }
    }

    @Override
    public boolean tableDelete(String id, VisualDevJsonModel visualDevJsonModel) throws Exception {
        DbLinkEntity linkEntity = dblinkService.getInfo(visualDevJsonModel.getDbLinkId());
        VisualDevJsonModel model = BeanUtil.copyProperties(visualDevJsonModel, VisualDevJsonModel.class);
        return flowFormDataUtil.deleteTable(id, model, linkEntity);
    }

    @Override
    public ActionResult tableDeleteMore(List<String> ids, VisualDevJsonModel visualDevJsonModel) throws Exception {
        List<String> dataInfoVOList = new ArrayList<>();
        for (String id : ids) {
            boolean isDel = tableDelete(id, visualDevJsonModel);
            if (isDel) {
                dataInfoVOList.add(id);
            }
        }
        visualDevJsonModel.setDataIdList(dataInfoVOList);
        return ActionResult.success(MsgCode.SU003.get());
    }

    @Override
    @DSTransactional
    public void deleteByTableName(FlowFormDataModel model) throws Exception {
        String tableName = model.getTableName();
        List<Map<String, Object>> ruleList = model.getRuleList();
        String realTableName = tableName;
        VisualdevReleaseEntity entity = visualdevReleaseService.getById(model.getFormId());
        List<TableModel> tableModels = JsonUtil.getJsonToList(entity.getVisualTables(), TableModel.class);
        FormDataModel formData = JsonUtil.getJsonToBean(entity.getFormData(), FormDataModel.class);
        Boolean logicalDelete = formData.getLogicalDelete();
        DbLinkEntity linkEntity = StringUtil.isNotEmpty(entity.getDbLinkId())
                ? dblinkService.getInfo(entity.getDbLinkId())
                : null;
        List<FieLdsModel> fieLdsModels = JsonUtil.getJsonToList(formData.getFields(), FieLdsModel.class);
        List<FieLdsModel> fields = new ArrayList<>();
        OnlinePublicUtils.recursionFields(fields, fieLdsModels);
        if (StringUtil.isNotEmpty(tableName)
                && tableName.toLowerCase().contains(YunzhupaasKeyConsts.CHILD_TABLE_PREFIX)) {
            FieLdsModel fieLdsModel = fields.stream().filter(t -> t.getVModel().equalsIgnoreCase(tableName)).findFirst()
                    .orElse(null);
            if (fieLdsModel != null) {
                realTableName = fieLdsModel.getConfig().getTableName();
            }
        }
        String finalRealTableName = realTableName;
        TableModel tableModel = tableModels.stream().filter(t -> t.getTable().equals(finalRealTableName)).findFirst()
                .orElse(null);
        List<OnlineDynamicSqlModel> sqlModelList = new ArrayList<>();
        OnlineDynamicSqlModel sqlModel = new OnlineDynamicSqlModel();
        SqlTable sqlTable = SqlTable.of(tableModel.getTable());
        sqlModel.setSqlTable(sqlTable);
        sqlModel.setTableName(tableModel.getTable());
        sqlModelList.add(sqlModel);
        SuperJsonModel ruleJsonModel = null;
        // 组装查询条件
        if (ObjectUtil.isNotEmpty(ruleList)) {
            ruleJsonModel = new SuperJsonModel();
            ruleJsonModel.setMatchLogic(model.getRuleMatchLogic());
            List<SuperQueryJsonModel> superQueryJsonModelList = new ArrayList<>();
            for (Object obj : ruleList) {
                SuperQueryJsonModel ruleQueryModel = JsonUtil.getJsonToBean(obj, SuperQueryJsonModel.class);
                List<FieLdsModel> groups = ruleQueryModel.getGroups();
                if (ObjectUtil.isNotEmpty(groups)) {
                    groups.stream().forEach(group -> {
                        if (group.getId().toLowerCase().contains(YunzhupaasKeyConsts.CHILD_TABLE_PREFIX)) {
                            group.setVModel(group.getId().split("-")[1]);
                        }
                    });
                }
                superQueryJsonModelList.add(ruleQueryModel);
            }
            ruleJsonModel.setConditionList(superQueryJsonModelList);
        }
        DynamicDataSourceUtil.switchToDataSource(linkEntity);
        try {
            @Cleanup
            Connection conn = ConnUtil.getConnOrDefault(linkEntity);
            String dbType = conn.getMetaData().getDatabaseProductName().trim();
            String pkeyId = flowFormDataUtil.getKey(tableModel, dbType);
            List<Object> idStringList = new ArrayList<>();
            if (ObjectUtil.isNotEmpty(ruleJsonModel)) {
                QueryExpressionDSL<SelectModel>.QueryExpressionWhereBuilder where = SqlBuilder
                        .selectDistinct(sqlTable.column(pkeyId)).from(sqlTable).where();
                OnlineProductSqlUtils.getSuperSql(where, ruleJsonModel, sqlModelList, dbType, null, false);
                List<Map<String, Object>> dataList = flowFormDataMapper
                        .selectManyMappedRows(where.build().render(RenderingStrategies.MYBATIS3));
                idStringList = dataList.stream().map(m -> m.get(pkeyId)).distinct().collect(Collectors.toList());
                if (ObjectUtil.isEmpty(idStringList)) {
                    idStringList.add("nodata");
                }
            }
            // if (logicalDelete) {
            // SqlTable sqlt = SqlTable.of(tableModel.getTable());
            // UpdateDSL<UpdateModel> updateModelUpdateDSL = SqlBuilder.update(sqlt);
            // updateModelUpdateDSL.set(sqlt.column(TableFeildsEnum.DELETEMARK.getField())).equalTo(1);
            // updateModelUpdateDSL.set(sqlt.column(TableFeildsEnum.DELETETIME.getField())).equalTo(new
            // Date());
            // updateModelUpdateDSL.set(sqlt.column(TableFeildsEnum.DELETEUSERID.getField())).equalTo(UserProvider.getUser().getUserId());
            // UpdateDSL<UpdateModel>.UpdateWhereBuilder whereU =
            // updateModelUpdateDSL.where();
            // if (ObjectUtil.isNotEmpty(idStringList)) {
            // whereU.and(sqlTable.column(pkeyId), SqlBuilder.isIn(idStringList));
            // }
            // flowFormDataMapper.update(whereU.build().render(RenderingStrategies.MYBATIS3));
            // } else {
            DeleteDSL<DeleteModel>.DeleteWhereBuilder whereD = SqlBuilder.deleteFrom(SqlTable.of(tableModel.getTable()))
                    .where();
            if (ObjectUtil.isNotEmpty(idStringList)) {
                whereD.and(sqlTable.column(pkeyId), SqlBuilder.isIn(idStringList));
            }
            flowFormDataMapper.delete(whereD.build().render(RenderingStrategies.MYBATIS3));
            // }
        } catch (Exception e) {
            e.printStackTrace();
            throw new DataException(MsgCode.FA103.get());
        } finally {
            DynamicDataSourceUtil.clearSwitchDataSource();
        }
    }
}
