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

import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.stylefeng.roses.kernel.rule.enums.FieldTypeEnum;
import cn.stylefeng.roses.kernel.rule.pojo.clazz.ClassParseResult;
import cn.stylefeng.roses.kernel.rule.util.ClassTypeUtil;
import cn.stylefeng.roses.kernel.rule.util.ObjectConvertUtil;
import cn.stylefeng.team.form.api.FormItemFormatApi;
import cn.stylefeng.team.form.api.FormModelServiceApi;
import cn.stylefeng.team.form.api.entity.FormItem;
import cn.stylefeng.team.form.api.pojo.FormDesignVo;
import cn.stylefeng.team.view.api.ViewApi;
import cn.stylefeng.team.view.api.enums.ParserTypeEnum;
import cn.stylefeng.team.view.api.pojo.ViewColumnField;
import cn.stylefeng.team.view.api.pojo.ViewConfig;

import java.time.LocalDateTime;
import java.util.*;

public class ViewResultFactory {

    public static List<Map<String, Object>> parseViewListResult(List<Map<String, Object>> records, ViewConfig viewConfig, ViewApi viewApi) {

        if (ObjectUtil.isEmpty(records)) {
            return new ArrayList<>();
        }

        Map<Long, FormDesignVo> formDesignVoMap = getFormDesignList(viewConfig);

        for (Map<String, Object> record : records) {
            for (ViewColumnField recordConfig : viewConfig.getViewColumnFieldList()) {

                if (ObjectUtil.isEmpty(recordConfig.getParserType()) && ObjectUtil.isNotEmpty(recordConfig.getParserName())) {
                    commonParserProcess(viewApi, record, recordConfig);
                    continue;
                }

                if (ObjectUtil.isNotEmpty(recordConfig.getParserType())) {

                    if (ParserTypeEnum.COMMON_PARSER.getCode().equals(recordConfig.getParserType())
                            && ObjectUtil.isNotEmpty(recordConfig.getParserName())) {
                        commonParserProcess(viewApi, record, recordConfig);
                        continue;
                    }

                    if (ParserTypeEnum.FORM_PARSER.getCode().equals(recordConfig.getParserType())) {
                        if (ObjectUtil.isEmpty(recordConfig.getFormDefinitionId()) || ObjectUtil.isEmpty(recordConfig.getFieldCode())) {
                            continue;
                        }
                        formParserProcess(formDesignVoMap, record, recordConfig);
                    }
                }
            }
        }

        for (Map<String, Object> record : records) {
            for (Map.Entry<String, Object> entry : record.entrySet()) {
                String key = entry.getKey();
                Object value = entry.getValue();

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

                if (value instanceof LocalDateTime) {
                    record.put(key, LocalDateTimeUtil.format((LocalDateTime) value, "yyyy-MM-dd HH:mm:ss"));
                    continue;
                }

                ClassParseResult classParseResult = ClassTypeUtil.getClassFieldType(value.getClass());
                FieldTypeEnum classFieldType = classParseResult.getFieldTypeEnum();

                if (FieldTypeEnum.STRING.equals(classFieldType) || FieldTypeEnum.NUMBER.equals(classFieldType)) {
                    continue;
                }

                if (FieldTypeEnum.COLLECTION.equals(classFieldType)) {
                    Collection<?> originValueList = (Collection<?>) value;
                    String afterValue = StrUtil.join(",", originValueList);
                    record.put(key, afterValue);
                }

                if (FieldTypeEnum.ARRAY.equals(classFieldType)) {
                    Object[] originList = ObjectConvertUtil.objToArray(value);
                    String afterValue = StrUtil.join(",", originList);
                    record.put(key, afterValue);
                }
            }
        }

        return records;
    }

    public static List<List<Object>> parseToExcelLine(ViewConfig viewConfig, List<List<String>> dynamicTableHead, List<Map<String, Object>> originData) {

        List<List<Object>> finalResult = new ArrayList<>();

        if (ObjectUtil.isEmpty(originData)) {
            return finalResult;
        }

        for (Map<String, Object> mapData : originData) {
            List<Object> objectData = new ArrayList<>();

            for (List<String> headChineseName : dynamicTableHead) {
                for (ViewColumnField viewColumnField : viewConfig.getViewColumnFieldList()) {
                    if (viewColumnField.getShowName().equals(headChineseName.get(0))) {
                        Object value = mapData.get(viewColumnField.getFieldName());
                        objectData.add(value);
                    }
                }
            }

            finalResult.add(objectData);
        }

        return finalResult;
    }

    private static void commonParserProcess(ViewApi viewApi, Map<String, Object> record, ViewColumnField recordConfig) {
        Object beforeParseValue = record.get(recordConfig.getFieldName());
        Object afterParseValue = viewApi.getFormattedValue(recordConfig.getParserName(), beforeParseValue);
        record.put(recordConfig.getFieldName(), afterParseValue);
    }

    private static void formParserProcess(Map<Long, FormDesignVo> formDesignVoMap, Map<String, Object> record, ViewColumnField recordConfig) {

        FormItem formItem = null;

        String formItemComponentCode = null;

        FormDesignVo formDesignVo = formDesignVoMap.get(recordConfig.getFormDefinitionId());
        if (ObjectUtil.isEmpty(formDesignVo)) {
            return;
        }

        List<FormItem> formItemList = formDesignVo.getFormItemList();
        for (FormItem item : formItemList) {
            if (recordConfig.getFieldCode().equals(item.getFieldCode())) {
                formItem = item;
                formItemComponentCode = item.getComponentCode();
                break;
            }
        }

        Object beforeParseValue = record.get(recordConfig.getFieldName());

        FormItemFormatApi formItemFormatApi = SpringUtil.getBean(FormItemFormatApi.class);
        Object afterParseValue = formItemFormatApi.format(formItemComponentCode, formItem, beforeParseValue);
        record.put(recordConfig.getFieldName(), afterParseValue);
    }

    private static Map<Long, FormDesignVo> getFormDesignList(ViewConfig viewConfig) {

        Map<Long, FormDesignVo> formDesignVoList = new HashMap<>();

        List<Long> formDefinitionIds = new ArrayList<>();

        for (ViewColumnField viewColumnField : viewConfig.getViewColumnFieldList()) {
            if (ParserTypeEnum.FORM_PARSER.getCode().equals(viewColumnField.getParserType())) {
                Long formDefinitionId = viewColumnField.getFormDefinitionId();
                if (ObjectUtil.isNotEmpty(formDefinitionId)) {
                    formDefinitionIds.add(formDefinitionId);
                }
            }
        }

        if (ObjectUtil.isNotEmpty(formDefinitionIds)) {
            FormModelServiceApi formModelServiceApi = SpringUtil.getBean(FormModelServiceApi.class);
            List<FormDesignVo> fromDesignList = formModelServiceApi.getFromDesignList(formDefinitionIds);
            for (FormDesignVo formDesignVo : fromDesignList) {
                formDesignVoList.put(formDesignVo.getFormDefinitionId(), formDesignVo);
            }
        }

        return formDesignVoList;
    }
}
