package com.boman.web.core.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.boman.common.core.utils.DateUtils;
import com.boman.common.core.utils.SpringUtils;
import com.boman.common.core.utils.array.ArrayUtils;
import com.boman.common.core.utils.collection.CollectionUtils;
import com.boman.common.core.utils.obj.ObjectUtils;
import com.boman.domain.GenTableColumn;
import com.boman.domain.SysDictData;
import com.boman.domain.SysFile;
import com.boman.system.api.RemoteDictDataService;
import com.boman.web.core.service.select.IBaseSelectService;
import org.apache.commons.lang3.BooleanUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.nio.charset.StandardCharsets;
import java.util.*;

import static com.boman.common.core.utils.obj.ObjectUtils.*;
import static com.boman.domain.constant.FormDataConstant.*;
import static com.boman.domain.constant.FormDataConstant.DATE;
import static com.boman.web.core.utils.JSONObjectUtils.containsKeyIgnoreCase;

/**
 * @author shiqian
 * @date 2021年04月29日 14:32
 **/
public class HandlerFormDataUtils {

    private static final Logger LOGGER = LoggerFactory.getLogger(HandlerFormDataUtils.class);

    /**
     * 功能描述: 处理字典值，不查询所有的字典值, 不放入sysDictData,只根据dictValue查询dictLabel
     *
     * @param result     db中查出的结果
     * @param allColumns 所有的列
     */
    public static void handleDictForQueryList(List<JSONObject> result, List<GenTableColumn> allColumns) {
        if (isEmpty(result)) {
            return;
        }

        for (JSONObject jsonObject : result) {
            //获取到所有rows查询字段的值
            Set<String> strings = jsonObject.keySet();
            List<String> arrays = new ArrayList<>(strings);
            for (String string : arrays) {
                for (GenTableColumn column : allColumns) {
                    String dictType = column.getDictType();
                    String columnName = column.getColumnName();
                    if (string.equals(columnName) && isNotEmpty(dictType)) {
                        // 列表需要字典值的dictLabel, 不放入sysDictData
                        List<SysDictData> sysDictData = new ArrayList<>();
                        genDictData(column.getSysDictData(),  sysDictData);
                        //获取到字段的值
                        String value = String.valueOf(jsonObject.get(string));
                        if (sysDictData != null && sysDictData.size() > 0){
                            for (SysDictData sysDictDatum : sysDictData) {
                                if (sysDictDatum.getDictValue().equals(value)) {
                                    jsonObject.put(columnName, sysDictDatum.getDictLabel());
                                    jsonObject.put("list_class", sysDictDatum.getListClass());
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * 获取所有的字典数据
     * @param sysDictData
     * @return
     */
    private static List<SysDictData> genDictData(List<SysDictData> datas, List<SysDictData> sysDictData) {
        if(isEmpty(datas)) {
            return sysDictData;
        }
        for(SysDictData dictData : datas) {
            sysDictData.add(dictData);
            if(isNotEmpty(dictData.getChildren())) {
                genDictData(dictData.getChildren(), sysDictData);
            }
        }
        return sysDictData;
    }

    /**
     * 功能描述: 把timeStamp转为string, 默认类型为：YYYY_MM_DD
     *
     * @param result 被转的数据
     */
    public static void handleDateTimeForQueryList(List<JSONObject> result, List<GenTableColumn> allColumns) {
        if (isEmpty(result)) {
            return;
        }

        for (JSONObject jsonObject : result) {
            for (GenTableColumn column : allColumns) {
                String columnName = column.getColumnName(), columnType = column.getColumnType();

                if (!containsKeyIgnoreCase(jsonObject, columnName)) {
                    continue;
                }

                if (DATE.equals(columnType)) {
                    jsonObject.put(columnName, getStrDate(jsonObject.getTimestamp(columnName)));
                } else if (DATETIME.equals(columnType)) {
                    jsonObject.put(columnName, getStrTimeStamp(jsonObject.getTimestamp(columnName)));
                }
            }
        }
    }

    /**
     * 功能描述: yyyy-MM-dd
     *
     * @param date date
     * @return java.lang.String
     */
    public static String getStrTimeStamp(Date date) {
        if (null == date) {
            return null;
        }

        return DateUtils.getTime1(date);
    }

    /**
     * 功能描述: 处理外键
     *
     * @param result     result
     * @param allColumns 该表对应的所有的列
     */
    public static void handleFkForQueryList(List<JSONObject> result, List<GenTableColumn> allColumns) {
        if (isEmpty(result)) {
            return;
        }
        // 拿到所有有fk的列
        List<GenTableColumn> fkColumns = filter(allColumns, col -> ObjectUtils.isNotEmpty(col.getForeignKey()));
        if (isEmpty(fkColumns)) {
            return;
        }

        for (JSONObject jsonObject : result) {
            for (GenTableColumn column : fkColumns) {
                String selfColumnName = column.getColumnName();
                if (containsKeyIgnoreCase(jsonObject, selfColumnName)) {
                    JSONObject fkMap = getFkInfoForQueryList(column.getFkInfo(), jsonObject.get(selfColumnName));
                    jsonObject.put(selfColumnName.toLowerCase(), fkMap);
                }
            }
        }
    }

    /**
     * 功能描述: 根据从数据库查出来的返回值来确实是否是blob, 转为字符串! 转为字符串! 转为字符串!
     *
     * @param isContainsBlob 此表中的字段是否含有blob的列, true含
     * @param result         result
     */
    public static void handleBlob(List<JSONObject> result, Boolean isContainsBlob) {
        // 不包含
        if (BooleanUtils.isFalse(isContainsBlob)) {
            return;
        }

        for (JSONObject jsonObject : result) {
            for (Map.Entry<String, Object> entry : jsonObject.entrySet()) {
                Object value = entry.getValue();
                if (isNotEmpty(value) && BYTE_ARRAY.equals(value.getClass().getSimpleName())) {
                    entry.setValue(byteToString(((byte[]) value)));
                }
            }
        }
    }

    public static List<SysDictData> listSysDictDataByType(String dictType) {
        RemoteDictDataService remoteDictDataService = SpringUtils.getBean(RemoteDictDataService.class);
        List<SysDictData> list = null;
        try {
            list = remoteDictDataService.listByType(dictType);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return list;
    }

    /**
     * 功能描述: yyyy-MM-dd
     *
     * @param date date
     * @return java.lang.String
     */
    public static String getStrDate(Date date) {
        if (null == date) {
            return null;
        }

        return DateUtils.dateTime(date);
    }

    public static JSONObject getFkInfoForQueryList(Map<String, Object> fkInfoMap, Object value) {
        Object fkTableName = fkInfoMap.get(FK_TABLE_NAME);
        Object fkColumnName = fkInfoMap.get(FK_COLUMN_NAME);
        Object dkColumnName = fkInfoMap.get(DK_COLUMN_NAME);

        // 到子表中查
        JSONObject param = new JSONObject();
        param.put(fkColumnName.toString(), value);
        IBaseSelectService selectService = SpringUtils.getBean(IBaseSelectService.class);
        JSONObject fkInfo = selectService.getOneByMap(fkTableName.toString(), param);
        JSONObject result = new JSONObject();
        if (isEmpty(fkInfo)) {
            return result;
        }

        Object fkValue = fkInfo.get(dkColumnName);
        result.put(SINGLE_OBJ_NAME, value);
        result.put(SINGLE_OBJ_VALUE, fkValue);
        return result;
    }


    public static JSONObject getFkInfoForGetObject(Map<String, Object> fkInfoMap, Object value) {
        Object fkTableName = fkInfoMap.get(FK_TABLE_NAME);
        Object fkColumnName = fkInfoMap.get(FK_COLUMN_NAME);
        Object dkColumnName = fkInfoMap.get(DK_COLUMN_NAME);

        // 到子表中查
        JSONObject param = new JSONObject();
        param.put(fkColumnName.toString(), value);
        IBaseSelectService selectService = SpringUtils.getBean(IBaseSelectService.class);
        JSONObject fkInfo = selectService.getOneByMap(fkTableName.toString(), param);
        JSONObject result = new JSONObject();
        if (isEmpty(fkInfo)) {
            return result;
        }

        Object fkValue = fkInfo.get(dkColumnName);
        result.put(SINGLE_OBJ_NAME, value);
        result.put(SINGLE_OBJ_VALUE, fkValue);
        result.put(FK_TABLE_NAME, fkTableName);
        result.put(FK_COLUMN_NAME, fkColumnName);
        result.put(DK_COLUMN_NAME, dkColumnName);
        return result;
    }

    public static List<SysFile> getAnnex(String value) {
        if (ArrayUtils.equalsEmptyArray(value)) {
            return null;
        } else {
            return JSON.parseObject(value, new TypeReference<List<SysFile>>() {
            }.getType());
        }
    }

    public static String byteToString(byte[] bytes) {
        String result = "";
        if (ArrayUtils.isNotEmpty(bytes)) {
            result = new String(bytes, StandardCharsets.UTF_8);
        }

        return result;
    }

    /**
     * 功能描述: 查找result中是否有showData中不存在的列，如果不存在则置为null
     *
     * @param result   result
     * @param showData showData
     */
    public static void handleNullColumnValue(List<JSONObject> result, JSONArray showData) {
        for (JSONObject jsonObject : result) {
            Set<String> resultKeySet = jsonObject.keySet();
            for (Object columnNameObj : showData) {
                String columnName = (String) columnNameObj;
                if (!resultKeySet.contains(columnName)) {
                    jsonObject.put(columnName, "");
                }
            }
        }
    }

    /**
     * 功能描述: 查找result中是否有showData中不存在的列，如果不存在则置为null
     *
     * @param result   result
     * @param showData showData
     */
    public static void handleNullColumnValue(List<JSONObject> result, List<String> showData) {
        for (JSONObject jsonObject : result) {
            Set<String> resultKeySet = jsonObject.keySet();
            for (String columnName : showData) {
                if (!resultKeySet.contains(columnName)) {
                    jsonObject.put(columnName, "");
                }
            }
        }
    }

    /**
     * 功能描述: 列中extend的json使用到的列标记为true
     *
     * @param allColumns allColumns
     */
    public static void markTrueByExtend(List<GenTableColumn> allColumns) {
        Set<String> extendColumnNames = getExtendColumnNames(allColumns);
        if (isEmpty(extendColumnNames)) {
            return;
        }


        for (GenTableColumn column : allColumns) {
            if (extendColumnNames.contains(column.getColumnName())) {
                column.setIsUseExtend(true);
            }
        }
    }

    /**
     * 功能描述: 先拿到所有的和计算相关的列
     *
     * @param allColumns allColumns
     * @return java.util.Set<java.lang.String>
     */
    private static Set<String> getExtendColumnNames(List<GenTableColumn> allColumns) {
        Set<String> extendColumnNames = new HashSet<>(16);
        for (GenTableColumn col : allColumns) {
            String extendedAttributes = col.getExtendedAttributes();
            if (isNotEmpty(extendedAttributes)) {
                JSONObject jsonObject = JSON.parseObject(extendedAttributes);
                JSONArray jsonArray = jsonObject.getJSONArray(COL);
                CollectionUtils.addJSONArray(extendColumnNames, jsonArray);
            }
        }

        return extendColumnNames;
    }

}
