package com.yunzhupaas.base.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.base.CaseFormat;
import com.yunzhupaas.base.entity.VisualAliasEntity;
import com.yunzhupaas.base.entity.VisualdevReleaseEntity;
import com.yunzhupaas.base.mapper.VisualAliasMapper;
import com.yunzhupaas.base.model.VisualAliasForm;
import com.yunzhupaas.base.service.SuperServiceImpl;
import com.yunzhupaas.base.service.VisualAliasService;
import com.yunzhupaas.base.service.VisualdevReleaseService;
import com.yunzhupaas.base.util.common.AliasModel;
import com.yunzhupaas.constant.GenerateConstant;
import com.yunzhupaas.constant.MsgCode;
import com.yunzhupaas.exception.DataException;
import com.yunzhupaas.model.visualJson.TableFields;
import com.yunzhupaas.model.visualJson.TableModel;
import com.yunzhupaas.util.JsonUtil;
import com.yunzhupaas.util.RandomUtil;
import com.yunzhupaas.util.StringUtil;
import com.yunzhupaas.util.UserProvider;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 云筑产品开发平台组
 * @version v5.0.0
 * @copyright 深圳市乐程软件有限公司
 * @date 2024/4/13 14:05:48
 */
@Service
public class VisualAliasServiceImpl extends SuperServiceImpl<VisualAliasMapper, VisualAliasEntity> implements VisualAliasService {
    @Autowired
    private VisualdevReleaseService visualdevReleaseService;
    

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

    @Override
    public List<TableModel> getAliasInfo(String id) {
        VisualdevReleaseEntity visualdevEntity = visualdevReleaseService.getById(id);
        List<TableModel> tableModels = JsonUtil.getJsonToList(visualdevEntity.getVisualTables(), TableModel.class);
        List<VisualAliasEntity> list = this.getList(id);
        for (TableModel tableModel : tableModels) {
            tableModel.setComment(tableModel.getTableName());
            VisualAliasEntity tableAlias = list.stream().filter(t -> tableModel.getTable().equals(t.getTableName()) && t.getFieldName() == null).findFirst().orElse(null);
            if (tableAlias != null) {
                tableModel.setAliasName(tableAlias.getAliasName());
            }
            List<TableFields> fields = tableModel.getFields();
            List<TableFields> newFields = fields.stream().filter(t -> !GenerateConstant.SYS_KEYWORD.contains(t.getField().toLowerCase())).collect(Collectors.toList());
            for (TableFields field : newFields) {
                VisualAliasEntity fieldAlias = list.stream().filter(t -> tableModel.getTable().equals(t.getTableName()) && t.getFieldName() != null
                        && field.getField().equals(t.getFieldName())).findFirst().orElse(null);
                if (fieldAlias != null) {
                    field.setAliasName(fieldAlias.getAliasName());
                }
            }
            tableModel.setFields(newFields);
        }
        return tableModels;
    }

    @Transactional
    @Override
    public void aliasSave(String id, VisualAliasForm form) {
        List<TableModel> tableList = form.getTableList();
        List<VisualAliasEntity> list = this.getList(id);
        List<String> tableNameList = new ArrayList<>();
        List<String> listKeyword = GenerateConstant.getAllKeyWord();
        String regex = "[a-zA-Z_][a-zA-Z0-9_]*";
        for (TableModel tableModel : tableList) {
            VisualAliasEntity tableAlias = list.stream().filter(t -> tableModel.getTable().equals(t.getTableName()) && t.getFieldName() == null).findFirst().orElse(null);
            if (StringUtil.isNotEmpty(tableModel.getAliasName())) {
                if (tableNameList.contains(tableModel.getAliasName())) {
                    throw new DataException(tableModel.getAliasName() + MsgCode.VS018.get());
                } else {
                    tableNameList.add(tableModel.getAliasName());
                }

                if (listKeyword.contains(tableModel.getAliasName().toLowerCase())) {
                    throw new DataException(MsgCode.SYS128.get(tableModel.getTable() + "-" + tableModel.getAliasName()));
                }

                if (!tableModel.getAliasName().matches(regex)) {
                    throw new DataException(MsgCode.VS021.get(tableModel.getTable()));
                }
                if (twoCharactesUpperCase(tableModel.getAliasName())) {
                    throw new DataException(MsgCode.VS026.get());
                }
                if (tableAlias != null) {
                    tableAlias.setAliasName(tableModel.getAliasName());
                } else {
                    tableAlias = new VisualAliasEntity();
                    tableAlias.setId(RandomUtil.uuId());
                    tableAlias.setVisualId(id);
                    tableAlias.setTableName(tableModel.getTable());
                    tableAlias.setAliasName(tableModel.getAliasName());
                }
                this.saveOrUpdate(tableAlias);
            } else if (tableAlias != null) {
                this.removeById(tableAlias);
            }
            List<String> fieldNameList = new ArrayList<>();
            for (TableFields field : tableModel.getFields()) {
                VisualAliasEntity fieldAlias = list.stream().filter(t -> tableModel.getTable().equals(t.getTableName()) && t.getFieldName() != null
                        && field.getField().equals(t.getFieldName())).findFirst().orElse(null);
                if (StringUtil.isNotEmpty(field.getAliasName())) {
                    if (listKeyword.contains(field.getAliasName().toLowerCase())) {
                        throw new DataException(MsgCode.SYS128.get(field.getField() + "-" + field.getAliasName()));
                    }
                    if (!field.getAliasName().matches(regex)) {
                        throw new DataException(MsgCode.VS021.get(field.getField()));
                    }
                    if (twoCharactesUpperCase(field.getAliasName())) {
                        throw new DataException(MsgCode.VS026.get());
                    }
                    if (fieldNameList.contains(field.getAliasName())) {
                        throw new DataException(field.getAliasName() + MsgCode.VS020.get());
                    } else {
                        fieldNameList.add(field.getAliasName());
                    }
                    if (fieldAlias != null) {
                        fieldAlias.setAliasName(field.getAliasName());
                    } else {
                        fieldAlias = new VisualAliasEntity();
                        fieldAlias.setId(RandomUtil.uuId());
                        fieldAlias.setVisualId(id);
                        fieldAlias.setTableName(tableModel.getTable());
                        fieldAlias.setFieldName(field.getField());
                        fieldAlias.setAliasName(field.getAliasName());
                    }
                    this.saveOrUpdate(fieldAlias);
                } else if (fieldAlias != null) {
                    this.removeById(fieldAlias);
                }
            }
        }
    }

    @Override
    public Map<String, AliasModel> getAllFiledsAlias(String id) {
        Map<String, AliasModel> tableMap = new HashMap<>();
        VisualdevReleaseEntity visualdevEntity = visualdevReleaseService.getById(id);
        List<TableModel> tableModels = JsonUtil.getJsonToList(visualdevEntity.getVisualTables(), TableModel.class);
        List<VisualAliasEntity> list = this.getList(id);
        for (TableModel tableModel : tableModels) {
            AliasModel aliasModel = new AliasModel();
            aliasModel.setTableName(tableModel.getTable());
            VisualAliasEntity tableAlias = list.stream().filter(t -> tableModel.getTable().equals(t.getTableName()) && t.getFieldName() == null).findFirst().orElse(null);
            if (tableAlias != null) {
                aliasModel.setAliasName(tableAlias.getAliasName());
            } else {
                aliasModel.setAliasName(tableModel.getTable());
            }
            List<TableFields> fields = tableModel.getFields();
            Map<String, String> fieldMap = new HashMap<>();
            for (TableFields field : fields) {
                VisualAliasEntity fieldAlias = list.stream().filter(t -> tableModel.getTable().equals(t.getTableName()) && t.getFieldName() != null
                        && field.getField().equals(t.getFieldName())).findFirst().orElse(null);
                if (fieldAlias != null) {
                    fieldMap.put(field.getField(), fieldAlias.getAliasName());
                }
                //系统字段-以驼峰形式给别名
                else if (GenerateConstant.SYS_KEYWORD.contains(field.getField().toLowerCase())) {
                    String name = field.getField().toLowerCase();
                    name = name.startsWith("f_") ? name.substring(2) : name;
                    String fieldAliasName = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, name);
                    fieldMap.put(field.getField(), fieldAliasName);
                } else {
                    String name = field.getField();
                    String fieldAliasName = twoToLowerCase(name);
                    fieldMap.put(field.getField(), fieldAliasName);
                }
            }
            aliasModel.setFieldsMap(fieldMap);
            tableMap.put(tableModel.getTable(), aliasModel);
        }
        return tableMap;
    }

    @Override
    public void copy(String visualId, String uuid) {
        List<VisualAliasEntity> list = this.getList(visualId);
        if (CollectionUtils.isNotEmpty(list)) {
            for (VisualAliasEntity entity : list) {
                VisualAliasEntity copy = BeanUtil.copyProperties(entity, VisualAliasEntity.class);
                copyEntity(copy, uuid);
            }
        }
    }

    @Override
    public void copyEntity(VisualAliasEntity copy, String visualId) {
        copy.setId(RandomUtil.uuId());
        copy.setVisualId(visualId);
        copy.setCreatorTime(new Date());
        copy.setCreatorUserId(UserProvider.getUser().getUserId());
        copy.setLastModifyUserId(null);
        copy.setLastModifyTime(null);
        this.save(copy);
    }

    @Override
    public void removeByVisualId(String visualId) {
        QueryWrapper<VisualAliasEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(VisualAliasEntity::getVisualId, visualId);
        this.remove(queryWrapper);
    }

    /**
     * 判断前两字母是否大写
     *
     * @return
     */
    public boolean twoCharactesUpperCase(String name) {
        if (StringUtil.isEmpty(name)) {
            return false;
        }
        if (name.length() == 1) {
            return Character.isUpperCase(name.charAt(0));
        }
        if (name.length() >= 2) {
            return Character.isUpperCase(name.charAt(0)) || Character.isUpperCase(name.charAt(1));
        }
        return false;
    }

    /**
     * 两字母强制小写前
     *
     * @return
     */
    public String twoToLowerCase(String name) {
        if (StringUtil.isEmpty(name)) {
            return name;
        }
        name = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, name);
        if (name.length() <= 2) {
            return name.toLowerCase();
        }
        if (name.length() > 2) {
            return name.substring(0, 2).toLowerCase() + name.substring(2);
        }
        return name;
    }
}

