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

import cn.com.tenlion.configtable.dao.configtable.IConfigTableDao;
import cn.com.tenlion.configtable.pojo.bos.configtable.ConfigTableBO;
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.pos.configtable.ConfigTablePO;
import cn.com.tenlion.configtable.pojo.vos.configtable.ConfigTableVO;
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.RemoveException;
import ink.wgink.exceptions.SaveException;
import ink.wgink.pojo.ListPage;
import ink.wgink.pojo.result.SuccessResultList;
import ink.wgink.util.UUIDUtil;
import ink.wgink.util.date.DateUtil;
import ink.wgink.util.map.HashMapUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @ClassName: ConfigTableServiceImpl
 * @Description: 
 * @Author: CodeFactory
 * @Date: 2021-06-24 10:59:30
 * @Version: 3.0
 **/
@Service
public class ConfigTableServiceImpl extends DefaultBaseService implements IConfigTableService {

    @Autowired
    private IConfigTableDao configTableDao;
    @Autowired
    private IConfigTableFieldService iConfigTableFieldService;
    @Autowired
    private IConfigTableOperationSubService iConfigTableOperationSubService;

    @Override
    public void save(ConfigTableVO configTableVO) {
        saveReturnId(configTableVO);
    }

    @Override
    public void save(String token, ConfigTableVO configTableVO) {
        saveReturnId(token, configTableVO);
    }

    @Override
    public String saveReturnId(ConfigTableVO configTableVO) {
        return saveReturnId(null, configTableVO);
    }

    @Override
    public String saveReturnId(String token, ConfigTableVO configTableVO) {
        String configTableId = UUIDUtil.getUUID();
        /**
         * 查询编号是否存在
         */
        String configTableNumber = configTableVO.getConfigTableNumber().trim();
        ConfigTableDTO tableNumberDTO = configTableDao.getTableNumber(configTableNumber);
        if(tableNumberDTO != null) {
            throw new SaveException("该编码已经存在");
        }
        // 去除左右的空格
        configTableVO.setConfigTableNumber(configTableNumber);
        String configTableCode = configTableVO.getConfigTableCode().trim();
        /**
         * 判断表名的命名规范是否合法
         */
        char beginCode = configTableCode.charAt(0);
        if( !( beginCode >= 65 && beginCode <= 90 ) && !( beginCode >= 97 && beginCode <= 122 ) ) {
            throw new SaveException("表名首位必须为英文");
        }
        Pattern pattern1 = Pattern.compile("\\w+$");
        Matcher matcher1 = pattern1.matcher(configTableCode);
        if(!matcher1.find()) {
            throw new SaveException("表名的命名不符合规范");
        }
        /**
         * 查询数据库表明是否存在
         */
        Integer tableCount = iConfigTableOperationSubService.getTableExist(configTableCode);
        if(tableCount > 0) {
            throw new SaveException("该表在数据库已经存在");
        }
        /**
         * 查询数据库表名明是否存在
         */
        ConfigTableDTO tableCodeDTO1 = configTableDao.getTableCode(configTableCode);
        if(tableCodeDTO1 != null) {
            throw new SaveException("该数据库表名已经存在");
        }
        ConfigTableDTO tableCodeDTO2 = configTableDao.getTableCode(configTableCode.toLowerCase());
        if(tableCodeDTO2 != null) {
            throw new SaveException("该数据库表名已经存在");
        }
        ConfigTableDTO tableCodeDTO3 = configTableDao.getTableCode(configTableCode.toUpperCase());
        if(tableCodeDTO3 != null) {
            throw new SaveException("该数据库表名已经存在");
        }
        // 去除左右的空格
        configTableVO.setConfigTableCode(configTableCode);
        Map<String, Object> params = HashMapUtil.beanToMap(configTableVO);
        params.put("configTableId", configTableId);
        if (StringUtils.isBlank(token)) {
            setSaveInfo(params);
        } else {
            setAppSaveInfo(token, params);
        }
        configTableDao.save(params);
        return configTableId;
    }

    @Override
    public void remove(List<String> ids) {
        remove(null, ids);
    }

    @Override
    public void remove(String token, List<String> ids) {
        /**
         * 已激活的不允许删除
         */
        for(String id : ids) {
             ConfigTableDTO dto = get(id);
            if("1".equals(dto.getConfigTableActivation())) {
               throw new RemoveException("不能删除已激活的表单");
            }
        }
        Map<String, Object> params = getHashMap(2);
        params.put("configTableIds", ids);
        if (StringUtils.isBlank(token)) {
            setUpdateInfo(params);
        } else {
            setAppUpdateInfo(token, params);
        }
        configTableDao.remove(params);
    }

    @Override
    public void delete(List<String> ids) {
        Map<String, Object> params = getHashMap(2);
        params.put("configTableIds", ids);
        configTableDao.delete(params);
    }

    @Override
    public void update(String configTableId, ConfigTableVO configTableVO) {
        update(null, configTableId, configTableVO);
    }

    @Override
    public void update(String token, String configTableId, ConfigTableVO configTableVO) {
        ConfigTableDTO configTableDTO = get(configTableId);
        /**
         * 查询编号是否存在
         */
        String configTableNumber = configTableVO.getConfigTableNumber().trim();
        ConfigTableDTO tableNumberDTO = configTableDao.getTableNumber(configTableNumber);
        if(tableNumberDTO != null && !tableNumberDTO.getConfigTableId().equals(configTableId)) {
            throw new SaveException("该编码已经存在");
        }
        // 去除左右的空格
        configTableVO.setConfigTableNumber(configTableNumber);
        String configTableCode = configTableVO.getConfigTableCode().trim();
        /**
         * 判断表名的命名规范是否合法
         */
        char beginCode = configTableCode.charAt(0);
        if( !( beginCode >= 65 && beginCode <= 90 ) && !( beginCode >= 97 && beginCode <= 122 ) ) {
            throw new SaveException("表名首位必须为英文");
        }
        Pattern pattern1 = Pattern.compile("\\w+$");
        Matcher matcher1 = pattern1.matcher(configTableCode);
        if(!matcher1.find()) {
            throw new SaveException("表名的命名不符合规范");
        }
        /**
         * 未激活的时候, 查询数据库表明是否存在, 已激活的时候不会修改可以不做校验
         */
        if("0".equals(configTableDTO.getConfigTableActivation())) {
            Integer tableCount = iConfigTableOperationSubService.getTableExist(configTableCode);
            if(tableCount > 0) {
                throw new SaveException("该表在数据库已经存在");
            }
        }
        /**
         * 查询数据库表名明是否存在
         */
        ConfigTableDTO tableCodeDTO1 = configTableDao.getTableCode(configTableCode);
        if(tableCodeDTO1 != null && !tableNumberDTO.getConfigTableId().equals(configTableId)) {
            throw new SaveException("该数据库表名已经存在");
        }
        ConfigTableDTO tableCodeDTO2 = configTableDao.getTableCode(configTableCode.toLowerCase());
        if(tableCodeDTO2 != null && !tableNumberDTO.getConfigTableId().equals(configTableId)) {
            throw new SaveException("该数据库表名已经存在");
        }
        ConfigTableDTO tableCodeDTO3 = configTableDao.getTableCode(configTableCode.toUpperCase());
        if(tableCodeDTO3 != null && !tableNumberDTO.getConfigTableId().equals(configTableId)) {
            throw new SaveException("该数据库表名已经存在");
        }
        // 去除左右的空格
        configTableVO.setConfigTableCode(configTableCode);

        /**
         * 已激活的表单只允许修改 备注内容 / 表单描述
         * 不允许修改表单编号 / 数据库表名 / 数据形式
         */
        if("1".equals(configTableDTO.getConfigTableActivation())) {
            configTableVO.setConfigTableCode(null);
            configTableVO.setConfigTableNumber(null);
            configTableVO.setConfigTableMode(null);
        }
        Map<String, Object> params = HashMapUtil.beanToMap(configTableVO);
        params.put("configTableId", configTableId);
        if (StringUtils.isBlank(token)) {
            setUpdateInfo(params);
        } else {
            setAppUpdateInfo(token, params);
        }
        configTableDao.update(params);
    }

    @Override
    public ConfigTableDTO get(Map<String, Object> params) {
        return configTableDao.get(params);
    }

    @Override
    public ConfigTableDTO get(String configTableId) {
        Map<String, Object> params = super.getHashMap(2);
        params.put("configTableId", configTableId);
        return get(params);
    }

    @Override
    public ConfigTableDTO getByNumber(String configTableNumber) {
        ConfigTableDTO tableNumberDTO = configTableDao.getTableNumber(configTableNumber);
        return tableNumberDTO;
    }

    @Override
    public ConfigTableBO getBO(Map<String, Object> params) {
        return configTableDao.getBO(params);
    }

    @Override
    public ConfigTableBO getBO(String configTableId) {
        Map<String, Object> params = super.getHashMap(2);
        params.put("configTableId", configTableId);
        return getBO(params);
    }

    @Override
    public ConfigTablePO getPO(Map<String, Object> params) {
        return configTableDao.getPO(params);
    }

    @Override
    public ConfigTablePO getPO(String configTableId) {
        Map<String, Object> params = super.getHashMap(2);
        params.put("configTableId", configTableId);
        return getPO(params);
    }

    @Override
    public List<ConfigTableDTO> list(Map<String, Object> params) {
        List<ConfigTableDTO> list = configTableDao.list(params);
        for (ConfigTableDTO dto : list) {
            List<ConfigTableFieldDTO> fieldDTOList = iConfigTableFieldService.getByConfigTableId(dto.getConfigTableId());
            dto.setConfigTableFieldList(fieldDTOList);
        }
        return list;
    }

    @Override
    public List<ConfigTableBO> listBO(Map<String, Object> params) {
        return configTableDao.listBO(params);
    }

    @Override
    public List<ConfigTablePO> listPO(Map<String, Object> params) {
        return configTableDao.listPO(params);
    }

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

    @Override
    public Integer count(Map<String, Object> params) {
        Integer count = configTableDao.count(params);
        return count == null ? 0 : count;
    }

    @Override
    public void saveAction(String configTableId) {
        ConfigTableDTO configTableDTO = get(configTableId);
        /**
         * 再次校验命名是否合法
         */
        String configTableCode = configTableDTO.getConfigTableCode().trim();
        char beginCode = configTableCode.charAt(0);
        if( !( beginCode >= 65 && beginCode <= 90 ) && !( beginCode >= 97 && beginCode <= 122 ) ) {
            throw new SaveException("表名首位必须为英文");
        }
        Pattern pattern1 = Pattern.compile("\\w+$");
        Matcher matcher1 = pattern1.matcher(configTableCode);
        if(!matcher1.find()) {
            throw new SaveException("表名的命名不符合规范");
        }
        /**
         * 已激活的不允许再次提交
         */
        if("1".equals(configTableDTO.getConfigTableActivation())) {
            throw new SaveException("该数据已经是激活状态");
        }
        Integer tableCount = iConfigTableOperationSubService.getTableExist(configTableCode);
        if(tableCount > 0) {
            throw new SaveException("该表在数据库已经存在");
        }
        /**
         * 更新激活状态
         */
        Map<String, Object> updateActivation = new HashMap<String, Object>();
        updateActivation.put("configTableId", configTableId);
        updateActivation.put("configTableActivation", "1");
        updateActivation.put("configTableActivationTime", DateUtil.getTime());
        configTableDao.updateActivation(updateActivation);
        /**
         * 封装字段信息创建表单
         */
        List<ConfigTableFieldDTO> fieldList = iConfigTableFieldService.getByConfigTableId(configTableId);
        if (fieldList.size() < 1) {
            throw new SaveException("该表单尚未配置字段");
        }
        configTableDTO.setConfigTableFieldList(fieldList);
        /**
         * 将数据库表名以及字段名全部改为小写
         */
        configTableDTO.setConfigTableCode(configTableDTO.getConfigTableCode().toLowerCase());
        for (ConfigTableFieldDTO dto : fieldList) {
            dto.setConfigTableFieldCode(dto.getConfigTableFieldCode().toLowerCase());
        }
        Map<String, Object> params = HashMapUtil.beanToMap(configTableDTO);
        iConfigTableOperationSubService.saveTable(params);
        /**
         * 确认是否创建成功
         */
        Integer tableCount1 = iConfigTableOperationSubService.getTableExist(configTableCode);
        if(tableCount1 <= 0) {
            throw new SaveException("表单激活失败");
        }
    }

    @Override
    public ConfigTableDTO getTableCode(String configTableCode) {
        ConfigTableDTO tableCodeDTO = configTableDao.getTableCode(configTableCode);
        return tableCodeDTO;
    }

    @Override
    public void removeTable(List<String> asList) {
        List<String> removeList;
        for(String id : asList) {
            removeList = new ArrayList<String>();
            ConfigTableDTO configTableDTO = get(id);
            removeList.add(id);

            Map<String, Object> params = getHashMap(2);
            params.put("configTableIds", removeList);
            setUpdateInfo(params);
            configTableDao.remove(params);

            Integer tableCount = iConfigTableOperationSubService.getTableExist(configTableDTO.getConfigTableCode());
            if(tableCount > 0) {
                iConfigTableOperationSubService.deleteTable(configTableDTO.getConfigTableCode());
            }
        }
    }

}