package cn.stylefeng.team.project.modular.businessrender.factory;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.stylefeng.roses.kernel.rule.enums.YesOrNotEnum;
import cn.stylefeng.roses.kernel.rule.exception.base.ServiceException;
import cn.stylefeng.team.form.api.entity.FormItem;
import cn.stylefeng.team.form.api.entity.FormItemTable;
import cn.stylefeng.team.form.api.pojo.FormDesignVo;
import cn.stylefeng.team.meta.api.MetaModelServiceApi;
import cn.stylefeng.team.meta.api.entity.MetaModel;
import cn.stylefeng.team.project.modular.business.enums.BusinessExceptionEnum;
import cn.stylefeng.team.project.modular.businessrender.pojo.MetaModelData;

import java.util.*;

public class ModelDataFactory {

    public static MetaModelData createModelDataByFormData(Long primaryKeyId,
                                                          List<MetaModel> businessMetaModelList,
                                                          List<FormDesignVo> businessFormDesignList,
                                                          Map<String, Map<String, Object>> formData) {

        MetaModelData metaModelData = new MetaModelData();
        metaModelData.setPrimaryKeyId(primaryKeyId);

        MetaModel mainMetaModel = getMainMetaModel(businessMetaModelList);
        metaModelData.setMainTableName(mainMetaModel.getMetaModelCode());

        Map<String, Object> mainTableData = new HashMap<>();
        Map<String, List<Map<String, Object>>> subTableData = new HashMap<>();

        for (FormDesignVo formDesignVo : businessFormDesignList) {

            Long formDefinitionId = formDesignVo.getFormDefinitionId();

            List<FormItem> formItemList = formDesignVo.getFormItemList();

            List<FormItem> newExpandFormItemList = new ArrayList<>();
            FormDataFactory.expandFormItem(formItemList, newExpandFormItemList);

            Map<String, Object> thisFormDefinitionData = formData.get(formDefinitionId.toString());
            if (ObjectUtil.isEmpty(thisFormDefinitionData)) {
                continue;
            }

            analyseFormDefinitionData(newExpandFormItemList, thisFormDefinitionData, mainMetaModel.getMetaModelCode(), mainTableData, subTableData);
        }

        metaModelData.setMainTableData(mainTableData);
        metaModelData.setSubTableData(subTableData);

        return metaModelData;
    }

    public static MetaModel getMainMetaModel(List<MetaModel> businessMetaModelList) {
        for (MetaModel model : businessMetaModelList) {
            if (YesOrNotEnum.Y.getCode().equals(model.getMainFlag())) {
                return model;
            }
        }
        throw new ServiceException(BusinessExceptionEnum.CANT_FIND_MAIN_META_MODEL);
    }

    public static void analyseFormDefinitionData(List<FormItem> formItemList,
                                                 Map<String, Object> thisFormDefinitionData,
                                                 String mainTableName,
                                                 Map<String, Object> mainTableData,
                                                 Map<String, List<Map<String, Object>>> subTableData) {
        for (FormItem formItem : formItemList) {

            String formItemCode = formItem.getFieldCode();

            Object formItemValue = thisFormDefinitionData.get(formItemCode);

            if (ObjectUtil.isEmpty(formItemValue)) {
                continue;
            }

            String tableName = formItem.getMetaModelCode();

            FormItemTable formItemTable = formItem.getFormItemTable();

            if (formItemTable == null) {
                if (tableName.equals(mainTableName)) {
                    mainTableData.put(formItemCode, formItemValue);
                } else {
                    putSubTableData(tableName, formItemCode, formItemValue, subTableData);
                }
            }

            else {

                if (!ArrayUtil.isArray(formItemValue) && !(formItemValue instanceof Iterable) && !(formItemValue instanceof Iterator)) {
                    continue;
                }

                Long subMetaModelDefinitionId = formItemTable.getSubMetaModelDefinitionId();
                MetaModelServiceApi bean = SpringUtil.getBean(MetaModelServiceApi.class);
                String modelDefinitionTableName = bean.getModelDefinitionTableName(subMetaModelDefinitionId);

                List<Map<String, Object>> subTableDataList = subTableData.computeIfAbsent(modelDefinitionTableName, k -> new ArrayList<>());
                subTableDataList.addAll((Collection<? extends Map<String, Object>>) formItemValue);
            }
        }
    }

    public static void putSubTableData(String tableName,
                                       String fieldCode,
                                       Object formItemValue,
                                       Map<String, List<Map<String, Object>>> subTableData) {

        List<Map<String, Object>> tableDataList = subTableData.get(tableName);

        if (tableDataList == null) {
            tableDataList = new ArrayList<>();
        }

        Map<String, Object> thisRecord = null;

        if (ObjectUtil.isEmpty(tableDataList)) {
            thisRecord = new HashMap<>();
            tableDataList.add(thisRecord);
        } else {
            thisRecord = tableDataList.get(0);
        }

        thisRecord.put(fieldCode, formItemValue);

        subTableData.put(tableName, tableDataList);
    }

}
