package com.yunzhupaas.onlinedev.util.onlineDevUtil;

import com.yunzhupaas.base.UserInfo;
import com.yunzhupaas.base.entity.VisualdevEntity;
import com.yunzhupaas.base.model.CheckFormModel;
import com.yunzhupaas.base.model.OnlineImport.VisualdevModelDataInfoVO;
import com.yunzhupaas.base.model.VisualLogModel;
import com.yunzhupaas.base.model.flow.DataModel;
import com.yunzhupaas.base.model.flow.FlowFormDataModel;
import com.yunzhupaas.base.util.FlowFormDataUtil;
import com.yunzhupaas.base.util.FormCheckUtils;
import com.yunzhupaas.base.util.ServiceBaseUtil;
import com.yunzhupaas.constant.MsgCode;
import com.yunzhupaas.database.model.entity.DbLinkEntity;
import com.yunzhupaas.exception.DataException;
import com.yunzhupaas.exception.WorkFlowException;
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.RecursionForm;
import com.yunzhupaas.onlinedev.model.OnlineInfoModel;
import com.yunzhupaas.onlinedev.model.log.VisualLogForm;
import com.yunzhupaas.onlinedev.service.VisualDevInfoService;
import com.yunzhupaas.onlinedev.service.VisualLogService;
import com.yunzhupaas.permission.entity.UserEntity;
import com.yunzhupaas.util.JsonUtil;
import com.yunzhupaas.util.StringUtil;
import com.yunzhupaas.util.TableFeildsEnum;
import com.yunzhupaas.util.UserProvider;
import org.mybatis.dynamic.sql.SqlTable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 自定义流程表单处理
 *
 * @author 云筑产品开发平台组
 * @version V3.4.5
 * @copyright 深圳市乐程软件有限公司（http://www.szlecheng.cn）
 * @date 2024/10/21
 */
@Component
public class FlowFormCustomUtils {

    @Autowired
    private FlowFormDataUtil flowDataUtil;
    @Autowired
    private FormCheckUtils formCheckUtils;
    @Autowired
    private ServiceBaseUtil serviceUtil;
    @Autowired
    private VisualLogService visualLogService;
    @Autowired
    private VisualDevInfoService visualDevInfoService;

    public void create(VisualdevEntity visualdevEntity, FlowFormDataModel flowFormDataModel) throws WorkFlowException {
        String id = flowFormDataModel.getId();
        Map<String, Object> map = flowFormDataModel.getMap();
        UserEntity delegateUser = flowFormDataModel.getDelegateUser();
        List<Map<String, Object>> listFlowOperate = flowFormDataModel.getFormOperates();
        FormDataModel formData = JsonUtil.getJsonToBean(visualdevEntity.getFormData(), FormDataModel.class);
        List<FieLdsModel> list = JsonUtil.getJsonToList(formData.getFields(), FieLdsModel.class);
        List<TableModel> tableModels = JsonUtil.getJsonToList(visualdevEntity.getVisualTables(), TableModel.class);
        DbLinkEntity linkEntity = serviceUtil.getDbLink(visualdevEntity.getDbLinkId());

        //递归遍历模板
        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;
        }
        //单行唯一校验
        CheckFormModel checkFormModel = CheckFormModel.builder().formFieldList(list).dataMap(map).linkEntity(linkEntity).tableModelList(tableModels)
                .visualdevEntity(visualdevEntity).id(null).isTransfer(flowFormDataModel.getIsTransfer()).build();
        String b = formCheckUtils.checkForm(checkFormModel);
        if (StringUtil.isNotEmpty(b)) {
            throw new WorkFlowException(b);
        }
        String mainId = id;
        UserEntity userEntity;
        UserInfo userInfo = UserProvider.getUser();
        if (delegateUser != null) {
            delegateUser.setId(userInfo.getUserId());
            userEntity = delegateUser;
        } else {
            userEntity = serviceUtil.getUserInfo(userInfo.getUserId());
        }
        DataModel dataModel = DataModel.builder().visualId(visualdevEntity.getId())
                .dataNewMap(map).fieLdsModelList(list).tableModelList(tableModels).formAllModel(formAllModel).mainId(mainId).link(linkEntity)
                .userEntity(userEntity).concurrencyLock(concurrency).primaryKeyPolicy(primaryKeyPolicy).flowFormOperates(listFlowOperate).build();
        flowDataUtil.create(dataModel);

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

    public DataModel update(VisualdevEntity visualdevEntity, FlowFormDataModel flowFormDataModel) throws WorkFlowException, SQLException, DataException {
        Map<String, Object> map = flowFormDataModel.getMap();
        String id = flowFormDataModel.getId();
        List<Map<String, Object>> listFlowOperate = flowFormDataModel.getFormOperates();
        FormDataModel formData = JsonUtil.getJsonToBean(visualdevEntity.getFormData(), FormDataModel.class);
        List<TableModel> tableModels = JsonUtil.getJsonToList(visualdevEntity.getVisualTables(), TableModel.class);
        TableModel mainT = tableModels.stream().filter(t -> t.getTypeId().equals("1")).findFirst().orElse(null);
        DbLinkEntity linkEntity = serviceUtil.getDbLink(visualdevEntity.getDbLinkId());
        List<FieLdsModel> list = JsonUtil.getJsonToList(formData.getFields(), FieLdsModel.class);

        //递归遍历模板
        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 {
                Object realId = id;
                if (Objects.equals(primaryKeyPolicy, 2)) {
                    realId = Long.parseLong(id);
                }
                boolean version = flowDataUtil.getVersion(mainT.getTable(), linkEntity, map, realId);
                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;
        }

        CheckFormModel checkFormModel = CheckFormModel.builder().formFieldList(list).dataMap(map).linkEntity(linkEntity).tableModelList(tableModels)
                .visualdevEntity(visualdevEntity).id(id).isTransfer(flowFormDataModel.getIsTransfer()).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 userEntity = serviceUtil.getUserInfo(userInfo.getUserId());
        DataModel dataModel = DataModel.builder().visualId(visualdevEntity.getId())
                .dataNewMap(map).fieLdsModelList(list).formAllModel(formAllModel).tableModelList(tableModels).mainId(id).link(linkEntity)
                .userEntity(userEntity).concurrencyLock(isConcurrencyLock).primaryKeyPolicy(primaryKeyPolicy).flowFormOperates(listFlowOperate)
                .logicalDelete(formData.getLogicalDelete()).build();
        flowDataUtil.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()) {
            form.setListLog(listLog);
            visualLogService.createEventLog(form);
        }
        return dataModel;
    }

    public DataModel saveOrUpdate(VisualdevEntity visualdevEntity, FlowFormDataModel flowFormDataModel) throws WorkFlowException, SQLException, DataException {
        List<TableModel> tableModels = JsonUtil.getJsonToList(visualdevEntity.getVisualTables(), TableModel.class);
        TableModel mainT = tableModels.stream().filter(t -> t.getTypeId().equals("1")).findFirst().orElse(null);
        DbLinkEntity linkEntity = serviceUtil.getDbLink(visualdevEntity.getDbLinkId());
        FormDataModel formDataModel = JsonUtil.getJsonToBean(visualdevEntity.getFormData(), FormDataModel.class);
        boolean autoIncrement = Objects.equals(formDataModel.getPrimaryKeyPolicy(), 2);
        String id = flowFormDataModel.getId();
        Object mainId = id;
        if (autoIncrement) {
            mainId = Long.parseLong(id);
        }
        SqlTable sqlTable = SqlTable.of(mainT.getTable());
        String realId = formCheckUtils.getCount(mainId, sqlTable, mainT, linkEntity);

        if (StringUtil.isNotEmpty(realId)) {
            flowFormDataModel.setId(realId);
            return this.update(visualdevEntity, flowFormDataModel);
        } else {
            this.create(visualdevEntity, flowFormDataModel);
        }
        return null;
    }

    public Map<String, Object> info(VisualdevEntity visualdevEntity, String id) {
        return flowDataUtil.getEditDataInfo(visualdevEntity, id, OnlineInfoModel.builder().build());
    }
}

