package cn.com.tenlion.configtable.service.configtableoperation.impl;

import cn.com.tenlion.configtable.dao.configtableoperation.IConfigTableOperationDao;
import cn.com.tenlion.configtable.pojo.dtos.configtable.ConfigTableDTO;
import cn.com.tenlion.configtable.pojo.dtos.configtablefield.ConfigTableFieldDTO;
import cn.com.tenlion.configtable.pojo.dtos.configtableoperation.ConfigTableOperationDTO;
import cn.com.tenlion.configtable.pojo.dtos.configtableoperation.ConfigTableOperationGroupDTO;
import cn.com.tenlion.configtable.service.configtable.IConfigTableService;
import cn.com.tenlion.configtable.service.configtablefield.IConfigTableFieldService;
import cn.com.tenlion.configtable.service.configtableoperation.IConfigTableOperationSubService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import ink.wgink.common.base.DefaultBaseService;
import ink.wgink.exceptions.SaveException;
import ink.wgink.module.dictionary.pojo.dtos.DataDTO;
import ink.wgink.module.dictionary.service.IDataService;
import ink.wgink.module.dictionary.service.impl.DataServiceImpl;
import ink.wgink.pojo.ListPage;
import ink.wgink.pojo.app.AppTokenUser;
import ink.wgink.pojo.bos.UserInfoBO;
import ink.wgink.pojo.result.SuccessResultList;
import ink.wgink.util.UUIDUtil;
import ink.wgink.util.date.DateUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.*;

/**
 * @ClassName: ConfigTableOperationServiceImpl
 * @Description: 崔宝铖
 * @Author: CodeFactory
 * @Date: 2021年6月28日09:56:58
 * @Version: 3.0
 **/
@Service
public class ConfigTableOperationServiceImpl extends DefaultBaseService implements IConfigTableOperationSubService {

    @Autowired
    private IConfigTableService iConfigTableService;
    @Autowired
    private IConfigTableFieldService iConfigTableFieldService;
    @Autowired
    private IConfigTableOperationDao iConfigTableOperationDao;
    @Autowired
    private IDataService iDataService;

    @Override
    public void deleteDataById(String token, String configTableId, String uid) {
        ConfigTableDTO configTableDTO = iConfigTableService.get(configTableId);
        if(configTableDTO == null) {
            throw new SaveException("该动态表单不存在");
        }
        if(!"1".equals(configTableDTO.getConfigTableActivation())){
            throw new SaveException("该动态表单未激活");
        }
        String configTableCode = configTableDTO.getConfigTableCode();
        Integer tableCount = getTableExist(configTableCode);
        if(tableCount <= 0) {
            throw new SaveException("该表在数据库不存在");
        }
        Map<String, Object> query = new HashMap<String, Object>();
        query.put("uid", uid);
        List<Map<String, Object>> tableFieldDataList = getTableFieldData(configTableCode, query);
        if(tableFieldDataList.size() <= 0) {
            throw new SaveException("该数据不存在");
        }
        /**
         * 执行删除操作并返回
         */
        deleteTableFieldData(configTableCode, uid);
    }

    @Override
    public void deleteDataByNumber(String token, String configTableNumber, String uid) {
        ConfigTableDTO configTableDTO = iConfigTableService.getByNumber(configTableNumber);
        if(configTableDTO == null) {
            throw new SaveException("该动态表单不存在");
        }
        deleteDataById(token, configTableDTO.getConfigTableId(), uid);
    }

    @Override
    public String saveDataById(String token, String configTableId, Map<String, Object> param) {
        ConfigTableDTO configTableDTO = iConfigTableService.get(configTableId);
        if(configTableDTO == null) {
            throw new SaveException("该动态表单不存在");
        }
        if(!"1".equals(configTableDTO.getConfigTableActivation())){
            throw new SaveException("该动态表单未激活");
        }
        String configTableCode = configTableDTO.getConfigTableCode();
        Integer tableCount = getTableExist(configTableCode);
        if(tableCount <= 0) {
            throw new SaveException("该表在数据库不存在");
        }
        /**
         * 遍历字段, 对不允许为空的字段做判断, 对字段长度做判断
         */
        List<ConfigTableFieldDTO> fieldDTOList = iConfigTableFieldService.getByConfigTableId(configTableDTO.getConfigTableId());
        List<ConfigTableOperationDTO> configList = getTableFieldConfig(configTableCode);
        a:for (ConfigTableFieldDTO fieldDTO : fieldDTOList) {
            String code = fieldDTO.getConfigTableFieldCode();
            String must = fieldDTO.getConfigTableFieldMust();
            String value = param.get(code) == null ? "" : param.get(code).toString();
            if ("1".equals(must) && StringUtils.isEmpty(value)) {
                throw new SaveException(fieldDTO.getConfigTableFieldName() + "不能为空");
            }
            /**
             * 判断字段长度是否超出数据库限制
             */
            b:for (ConfigTableOperationDTO operationDTO : configList) {
                if(operationDTO.getName().equals(code)) {
                    if(value.length() > operationDTO.getMaxLength()) {
                        throw new SaveException(fieldDTO.getConfigTableFieldName() + " 超出限定长度");
                    }else {
                        /**
                         * 将传入的字段值封装到对象中
                         */
                        operationDTO.setValue(value);
                        break b;
                    }
                }
            }
        }
        /**
         * 重新整理表单数据, 进行保存准备操作
         */
        String userId = getUserId(token);
        String mode = configTableDTO.getConfigTableMode();
        // 如果该表单只允许每个用户存储一条, 则需要查询确认是否已经存在该用户的数据
        if("1".equals(mode)) {
            if(StringUtils.isEmpty(userId)) {
                throw new SaveException("未找到您的登陆信息");
            }
            Map<String, Object> query = new HashMap<String, Object>();
            query.put("userId", userId);
            List<Map<String, Object>> tableFieldDataList = getTableFieldData(configTableCode, query);
            if(tableFieldDataList.size() >= 1) {
                /**
                 * 执行修改操作并返回
                 */
                String uid = tableFieldDataList.get(0).get("uid").toString();
                buiderUpdateData(uid, userId, configList);
                updateTableFieldData(configTableCode, configList);
                return uid;
            }
        }
        if(param.get("uid") != null) {
            /**
             * 执行修改操作并返回
             */
            String uid = param.get("uid").toString();
            buiderUpdateData(uid, userId, configList);
            updateTableFieldData(configTableCode, configList);
            return uid;
        }
        /**
         * 执行保存操作并返回
         */
        String uid = UUIDUtil.getUUID();
        buiderSaveData(uid, userId, configList);
        saveTableFieldData(configTableCode, configList);
        return uid;
    }

    @Override
    public String saveDataByNumber(String token, String configTableNumber, Map<String, Object> param) {
        ConfigTableDTO configTableDTO = iConfigTableService.getByNumber(configTableNumber);
        if(configTableDTO == null) {
            throw new SaveException("该动态表单不存在");
        }
        return saveDataById(token, configTableDTO.getConfigTableId(), param);
    }

    @Override
    public ConfigTableOperationGroupDTO getData(String token, String configTableId, String uid) {
        ConfigTableDTO configTableDTO = iConfigTableService.get(configTableId);
        if(configTableDTO == null) {
            throw new SaveException("该动态表单不存在");
        }
        if(!"1".equals(configTableDTO.getConfigTableActivation())){
            throw new SaveException("该动态表单未激活");
        }
        String configTableCode = configTableDTO.getConfigTableCode();
        Integer tableCount = getTableExist(configTableCode);
        if(tableCount <= 0) {
            throw new SaveException("该表在数据库不存在");
        }
        Map<String, Object> query = new HashMap<String, Object>();
        query.put("uid", uid);
        List<Map<String, Object>> tableFieldDataList = getTableFieldData(configTableCode, query);
        if(tableFieldDataList.size() <= 0) {
            throw new SaveException("该数据不存在");
        }
        Map<String, Object> map = tableFieldDataList.get(0);
        /**
         * 查询出表单配置
         */
        List<ConfigTableOperationDTO> operationConfigList = getTableFieldConfigNotBase(configTableDTO.getConfigTableCode());
        /**
         * 遍历查询到的数据, 进行填充
         */
        for(ConfigTableOperationDTO dto : operationConfigList) {
            dto.setValue( map.get(dto.getName()) == null ? "" : map.get(dto.getName()).toString() );
        }
        ConfigTableOperationGroupDTO groupDTO = new ConfigTableOperationGroupDTO();
        groupDTO.setUid(map.get("uid").toString());
        groupDTO.setCreator(map.get("creator").toString());
        groupDTO.setGmtCreate(map.get("gmt_create").toString());
        groupDTO.setModifier(map.get("modifier").toString());
        groupDTO.setGmtModified(map.get("gmt_modified").toString());
        groupDTO.setList(operationConfigList);
        return groupDTO;
    }

    @Override
    public List<ConfigTableOperationGroupDTO> listMyData(String token, String configTableId, Map<String, Object> params) {
        ConfigTableDTO configTableDTO = iConfigTableService.get(configTableId);
        if(configTableDTO == null) {
            throw new SaveException("该动态表单不存在");
        }
        if(!"1".equals(configTableDTO.getConfigTableActivation())){
            throw new SaveException("该动态表单未激活");
        }
        String configTableCode = configTableDTO.getConfigTableCode();
        Integer tableCount = getTableExist(configTableCode);
        if(tableCount <= 0) {
            throw new SaveException("该表在数据库不存在");
        }
        // 如果传入了userId, 则按传入的userId查询
        // 如果没有传入userId, 则按传入的token中的userId查询
        if(params.get("userId") == null) {
            params.put("userId", getUserId(token));
        }
        params.put("configTableCode", configTableDTO.getConfigTableCode());
        List<ConfigTableOperationDTO> list = getTableFieldConfigNotBase(configTableDTO.getConfigTableCode());
        List<Map<String, Object>>  listMap = iConfigTableOperationDao.list(params);
        List<ConfigTableOperationGroupDTO> resultList = new ArrayList<ConfigTableOperationGroupDTO>();
        for(Map<String, Object> map : listMap) {
            ConfigTableOperationGroupDTO groupDTO = new ConfigTableOperationGroupDTO();
            List<ConfigTableOperationDTO> resultListData = new ArrayList<ConfigTableOperationDTO>();
            for(ConfigTableOperationDTO configTableOperationDTO : list) {
                if(map.get(configTableOperationDTO.getName()) == null) {
                    map.put(configTableOperationDTO.getName(), "");
                }
                ConfigTableOperationDTO newOperation = new ConfigTableOperationDTO();
                newOperation.setDataType(configTableOperationDTO.getDataType());
                newOperation.setMaxLength(configTableOperationDTO.getMaxLength());
                newOperation.setComment(configTableOperationDTO.getComment());
                newOperation.setColumnType(configTableOperationDTO.getColumnType());
                newOperation.setName(configTableOperationDTO.getName());
                newOperation.setValue(map.get(configTableOperationDTO.getName()));
                newOperation.setMust(configTableOperationDTO.getMust());
                newOperation.setOrder(configTableOperationDTO.getOrder());
                newOperation.setMaxCount(configTableOperationDTO.getMaxCount());
                newOperation.setDictionaries(configTableOperationDTO.getDictionaries());
                newOperation.setDictionariesList(configTableOperationDTO.getDictionariesList());
                newOperation.setDisplayList(configTableOperationDTO.getDisplayList());
                newOperation.setDataMode(configTableOperationDTO.getDataMode());

                newOperation.setDefaultValue(configTableOperationDTO.getDefaultValue());
                newOperation.setPlaceholder(configTableOperationDTO.getPlaceholder());
                newOperation.setRowCol(configTableOperationDTO.getRowCol());
                newOperation.setRow(configTableOperationDTO.getRow());
                newOperation.setConfigJson(configTableOperationDTO.getConfigJson());

                resultListData.add(newOperation);
            }
            groupDTO.setUid(map.get("uid").toString());
            groupDTO.setCreator(map.get("creator").toString());
            groupDTO.setGmtCreate(map.get("gmt_create").toString());
            groupDTO.setModifier(map.get("modifier").toString());
            groupDTO.setGmtModified(map.get("gmt_modified").toString());
            groupDTO.setList(resultListData);
            resultList.add(groupDTO);
        }
        return resultList;
    }

    @Override
    public List<ConfigTableOperationDTO> listFieldConfig(String token, String configTableId) {
        ConfigTableDTO configTableDTO = iConfigTableService.get(configTableId);
        if(configTableDTO == null) {
            throw new SaveException("该动态表单不存在");
        }
        if(!"1".equals(configTableDTO.getConfigTableActivation())){
            throw new SaveException("该动态表单未激活");
        }
        String configTableCode = configTableDTO.getConfigTableCode();
        Integer tableCount = getTableExist(configTableCode);
        if(tableCount <= 0) {
            throw new SaveException("该表在数据库不存在");
        }
        return getTableFieldConfigNotBase(configTableDTO.getConfigTableCode());
    }

    @Override
    public ConfigTableDTO getTable(String configTableId) {
        return iConfigTableService.get(configTableId);
    }

    private String getUserId(String token) {
        String userId = "notUserId";
        if (StringUtils.isBlank(token)) {
            UserInfoBO userInfoBO = this.securityComponent.getCurrentUser();
            userId = userInfoBO.getUserId();
        } else {
            AppTokenUser appTokenUser = this.getAppTokenUser(token);
            userId = appTokenUser.getId();
        }
        return userId;
    }

    private void buiderUpdateData(String uid, String userId, List<ConfigTableOperationDTO> configList) {
        for (ConfigTableOperationDTO operationDTO : configList) {
            if(operationDTO.getName().equals("uid")) {
                operationDTO.setValue(uid);
            }else if(operationDTO.getName().equals("modifier")) {
                operationDTO.setValue(userId);
            }else if(operationDTO.getName().equals("gmt_modified")) {
                operationDTO.setValue(DateUtil.getTime());
            }
        }
    }

    private void buiderSaveData(String uid, String userId, List<ConfigTableOperationDTO> configList) {
        for (ConfigTableOperationDTO operationDTO : configList) {
            if(operationDTO.getName().equals("creator")) {
                operationDTO.setValue(userId);
            }else if(operationDTO.getName().equals("gmt_create")) {
                operationDTO.setValue(DateUtil.getTime());
            }else if(operationDTO.getName().equals("is_delete")) {
                String currentDate = DateUtil.getTime();
                operationDTO.setValue(0);
            }else if(operationDTO.getName().equals("uid")) {
                operationDTO.setValue(uid);
            }else if(operationDTO.getName().equals("modifier")) {
                operationDTO.setValue("");
            }else if(operationDTO.getName().equals("gmt_modified")) {
                operationDTO.setValue("");
            }
        }
    }


    @Override
    public Integer getTableExist(String configTableCode) {
        Integer tableCount = iConfigTableOperationDao.getTableExist(configTableCode);
        return tableCount;
    }

    @Override
    public List<ConfigTableOperationDTO> getTableFieldConfig(String configTableCode) {
        List<ConfigTableOperationDTO> list = iConfigTableOperationDao.getTableFieldConfig(configTableCode);
        ConfigTableDTO configTableDTO = iConfigTableService.getTableCode(configTableCode);
        List<ConfigTableFieldDTO> fieldDTOList = iConfigTableFieldService.getByConfigTableId(configTableDTO.getConfigTableId());
        a:for (ConfigTableOperationDTO operationDTO: list) {
            b:for (ConfigTableFieldDTO fieldDTO: fieldDTOList) {
                if(operationDTO.getName().equals(fieldDTO.getConfigTableFieldCode())) {
                    operationDTO.setComment(fieldDTO.getConfigTableFieldName());
                    operationDTO.setDataType(fieldDTO.getConfigTableFieldType());
                    operationDTO.setOrder(fieldDTO.getConfigTableFieldOrder());
                    operationDTO.setMust("1".equals(fieldDTO.getConfigTableFieldMust()) ? true : false);
                    operationDTO.setMaxCount(fieldDTO.getConfigTableFieldNumber());
                    operationDTO.setDataMode(fieldDTO.getConfigTableFieldMode());

                    operationDTO.setDefaultValue(fieldDTO.getConfigTableFieldDefault());
                    operationDTO.setPlaceholder(fieldDTO.getConfigTableFieldPlaceholder());
                    operationDTO.setRowCol(fieldDTO.getConfigTableFieldRowCol());
                    operationDTO.setRow(fieldDTO.getConfigTableFieldRow() > 0 ? true : false);
                    operationDTO.setConfigJson(fieldDTO.getConfigTableFieldConfig());

                    operationDTO.setDictionaries(fieldDTO.getConfigTableFieldDictionaries());
                    if(!StringUtils.isEmpty(operationDTO.getDictionaries())) {
                        // 数据字典
                        List<DataDTO> dataDTOS = iDataService.listAllByParentId(operationDTO.getDictionaries());
                        operationDTO.setDictionariesList(dataDTOS);
                    }
                    operationDTO.setDisplayList("1".equals(fieldDTO.getConfigTableFieldDisplay()) ? true : false);
                    break b;
                }
            }
            if(operationDTO.getName().equals("id")) {
                operationDTO.setMaxLength(20);
            }
        }
        /**
         * 按配置的字段排序进行排序
         */
        Collections.sort(list, new Comparator<ConfigTableOperationDTO>() {
            @Override
            public int compare(ConfigTableOperationDTO o1, ConfigTableOperationDTO o2) {
                int o1Order = o1.getOrder();
                int o2Order = o2.getOrder();
                return o1Order - o2Order;
            }
        });
        return list;
    }

    @Override
    public List<ConfigTableOperationDTO> getTableFieldConfigNotBase(String configTableCode) {
        List<ConfigTableOperationDTO> list = getTableFieldConfig(configTableCode);
        /**
         * 剔除通用字段
         */
        Iterator<ConfigTableOperationDTO> configTableOperationDTOIterator = list.iterator();
        while(configTableOperationDTOIterator.hasNext()) {
            ConfigTableOperationDTO dto = configTableOperationDTOIterator.next();
            switch(dto.getName()) {
                case "id" :
                    configTableOperationDTOIterator.remove();
                    break;
                case "uid":
                    configTableOperationDTOIterator.remove();
                    break;
                case "creator":
                    configTableOperationDTOIterator.remove();
                    break;
                case "gmt_create":
                    configTableOperationDTOIterator.remove();
                    break;
                case "modifier":
                    configTableOperationDTOIterator.remove();
                    break;
                case "gmt_modified":
                    configTableOperationDTOIterator.remove();
                    break;
                case "is_delete":
                    configTableOperationDTOIterator.remove();
                    break;
            }
        }
        return list;
    }

    @Override
    public List<Map<String, Object>> getTableFieldData(String configTableCode, Map<String, Object> query) {
        query.put("configTableCode", configTableCode);
        return iConfigTableOperationDao.getTableFieldData(query);
    }

    @Override
    public void updateTableFieldData(String configTableCode, List<ConfigTableOperationDTO> updateList) {
        Map<String, Object> update = new HashMap<String, Object>();
        update.put("configTableCode", configTableCode);
        update.put("updateList", updateList);
        iConfigTableOperationDao.updateTableFieldData(update);
    }

    @Override
    public void saveTableFieldData(String configTableCode, List<ConfigTableOperationDTO> saveList) {
        Map<String, Object> update = new HashMap<String, Object>();
        update.put("configTableCode", configTableCode);
        update.put("saveList", saveList);
        iConfigTableOperationDao.saveTableFieldData(update);
    }

    @Override
    public void deleteTableFieldData(String configTableCode, String uid) {
        Map<String, Object> delete = new HashMap<String, Object>();
        delete.put("configTableCode", configTableCode);
        delete.put("uid", uid);
        iConfigTableOperationDao.deleteTableFieldData(delete);
    }

    @Override
    public List<Map<String, Object>> list(Map<String, Object> params) {
        List<ConfigTableOperationDTO> list = getTableFieldConfig(params.get("configTableCode").toString());
        List<Map<String, Object>>  listMap = iConfigTableOperationDao.list(params);
        for(Map<String, Object> map : listMap) {
            for(ConfigTableOperationDTO configTableOperationDTO : list) {
                if(map.get(configTableOperationDTO.getName()) == null) {
                    map.put(configTableOperationDTO.getName(), "");
                }
            }
        }
        return listMap;
    }

    @Override
    public SuccessResultList<List<Map<String, Object>>> listPage(ListPage page) {
        PageHelper.startPage(page.getPage(), page.getRows());
        List<Map<String, Object>> configTableOperationDTOs = list(page.getParams());
        PageInfo<Map<String, Object>> pageInfo = new PageInfo<>(configTableOperationDTOs);
        return new SuccessResultList<>(configTableOperationDTOs, pageInfo.getPageNum(), pageInfo.getTotal());
    }

    @Override
    public void saveTable(Map<String, Object> params) {
        iConfigTableOperationDao.saveTable(params);
    }

    @Override
    public void deleteTable(String configTableCode) {
        iConfigTableOperationDao.deleteTable(configTableCode);
    }

}