package com.hchyun.generator.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.hchyun.common.constant.ReturnConstants;
import com.hchyun.common.core.entity.entity.SysMenu;
import com.hchyun.common.utils.SecurityUtils;
import com.hchyun.common.utils.ServerResult;
import com.hchyun.generator.dao.QueryDao;
import com.hchyun.generator.dao.UniQueryDao;
import com.hchyun.generator.entity.UniCon;
import com.hchyun.generator.entity.UniQuery;
import com.hchyun.generator.service.QueryService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Author 18209
 * Date 2021/1/30 18:54
 * Version 1.0
 */
@Service
public class QueryServiceImpl implements QueryService {
    private final Logger logger = LoggerFactory.getLogger(QueryServiceImpl.class);

    @Autowired
    private QueryDao queryDao;

    @Autowired
    private UniQueryDao uniQueryDao;


    /**
     * 查询万能查询的基本信息和条件信息
     */
    @Override
    public ServerResult<UniQuery> selectQueryById(Long id) {
        try {
            UniQuery uniQuery = queryDao.selectQueryInfo(id);
            if (uniQuery != null) {
                return new ServerResult<>(true, uniQuery);
            } else {
                return new ServerResult<>(false, ReturnConstants.RESULT_EMPTY);
            }
        } catch (RuntimeException e) {
            logger.error(e.getMessage());
            return new ServerResult<>(false, ReturnConstants.SYS_FAILL);
        }
    }

    @Override
    @Transactional
    public ServerResult<Integer> Release(UniQuery uniQuery) {
        try {
            Integer isRelease = queryDao.Release(uniQuery.getId());
            if ((isRelease == 1 && uniQuery.getIsRelease() == 2) || (isRelease == 2 && uniQuery.getIsRelease() == 1)) {
                if (uniQuery.getIsRelease() == 1) {
                    UniQuery query = uniQueryDao.selectUniQueryById(uniQuery.getId());
                    SysMenu sysMenu = new SysMenu(query.getId(), query.getUqName(), SecurityUtils.getUserId());
                    Integer insermenu = queryDao.insertMenu(sysMenu);
                    if (insermenu == 0) {
                        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                        return new ServerResult<>(false, ReturnConstants.OP_ERROR);
                    }
                } else {
                    Integer deleteMenu = queryDao.deleteMenu("data/" + uniQuery.getId());
                    if (deleteMenu == 0) {
                        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                        return new ServerResult<>(false, ReturnConstants.OP_ERROR);
                    }
                }
                Integer release = queryDao.changeRelease(uniQuery);
                if (release > 0) {
                    return new ServerResult<>(true);
                } else {
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    return new ServerResult<>(false, ReturnConstants.OP_ERROR);
                }
            } else {
                return new ServerResult<>(false, ReturnConstants.STATE_ERROR);
            }
        } catch (RuntimeException e) {
            logger.error(e.getMessage());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return new ServerResult<>(false, ReturnConstants.SYS_FAILL);
        }
    }

    @Override
    public ServerResult<List<Map<String, Object>>> RealData(UniQuery uniQuery, Integer type) {
        try {
            List<UniCon> uniCons = uniQuery.getUniCons();
            Integer pageNum = null,pageSize = null;
            if (type == 2) {
                pageNum = uniQuery.getPageNum();
                pageSize = uniQuery.getPageSize();
            }
            uniQuery = uniQueryDao.selectUniQueryById(uniQuery.getId());
            StringBuilder sql = new StringBuilder(uniQuery.getUqSql().toLowerCase());
            if (uniQuery.getIsRelease() == 0) {
                return new ServerResult<>(false, ReturnConstants.STATE_ERROR);
            } else {
                if (uniCons.size() > 0) {
                    sql.append(" where 1 = 1 ");
                    for (UniCon uniCon : uniCons) {
                        sql.append(conversionReal(uniCon));
                    }
                }
                if (type == 2) {
                    PageHelper.startPage(pageNum, pageSize, "");
                }
                List<Map<String, Object>> dataMap = queryDao.UniQuery(sql.toString());
                return new ServerResult<>(true, dataMap,uniQuery.getUqName());
            }
        } catch (RuntimeException e) {
            logger.error(e.getMessage());
            return new ServerResult<>(false, ReturnConstants.SYS_FAILL);
        }
    }

    /**
     * 更新万能查询基本信息和条件
     */
    @Override
    @Transactional
    public ServerResult<Integer> updateQueryInfo(UniQuery uniQuery) {
        try {
            int uqrenewal = uniQueryDao.updateUniQuery(uniQuery);
            if (uqrenewal > 0) {
                if (uniQuery.getUniCons() != null) {
                    queryDao.deleteUniCon(uniQuery.getId());
                    Integer ucrenewal = queryDao.insertUniCon(uniQuery.getUniCons());
                    if (ucrenewal == 0) {
                        return new ServerResult<>(false, ReturnConstants.OP_ERROR);
                    }
                }
                return new ServerResult<>(true);
            }
            return new ServerResult<>(false, ReturnConstants.OP_ERROR);
        } catch (RuntimeException e) {
            logger.error(e.getMessage());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return new ServerResult<>(false, ReturnConstants.SYS_FAILL);
        }
    }

    @Override
    public ServerResult<List<Map<String, Object>>> previewQuery(UniQuery uniQuery) {
        try {
            StringBuilder sql = new StringBuilder(uniQuery.getUqSql().toLowerCase());
            List<UniCon> uniConList = uniQuery.getUniCons();
            if (sql.toString().contains("insert") || sql.toString().contains("delete ") || sql.toString().contains("update ") || sql.toString().contains("drop ") || sql.toString().contains("database ") || sql.toString().contains("create ") || sql.toString().contains("view ") || sql.toString().contains("alter ")) {
                return new ServerResult<>(false, "sql语句含有insert,delete,update,drop,database,view,alter等特殊字符!");
            }

            if (uniConList.size() > 0) {
                sql.append(" where 1 = 1");
                for (UniCon uniCon : uniConList) {
                    sql.append(conversionPreview(uniCon));
                }
            }
            List<Map<String, Object>> dataMap = queryDao.UniQuery(sql.toString());
            return new ServerResult<>(true, dataMap);
        } catch (RuntimeException e) {
            logger.error(e.getMessage());
            return new ServerResult<>(false, e.getMessage());
        }
    }

    @Override
    public ServerResult<List<UniCon>> RealInfo(Long id) {
        try {
            List<UniCon> uniCons = queryDao.queryRealInfo(id);
            return new ServerResult<>(true, uniCons);
        } catch (RuntimeException e) {
            logger.error(e.getMessage());
            return new ServerResult<>(false, ReturnConstants.DB_EX);
        }
    }


    public String conversionReal(UniCon uniCon) {
        if (uniCon.getUcReal() == null) {
            return "";
        } else {
            String sql = " and ";
            switch (uniCon.getUcCon()) {
                case "EQ":
                    sql += uniCon.getUcKey() + " = '" + uniCon.getUcReal() + "'";
                    break;
                case "NE":
                    sql += uniCon.getUcKey() + " != '" + uniCon.getUcReal() + "'";
                    break;
                case "GT":
                    sql += uniCon.getUcKey() + " > '" + uniCon.getUcReal() + "'";
                    break;
                case "GTE":
                    sql += uniCon.getUcKey() + " >= '" + uniCon.getUcReal() + "'";
                    break;
                case "LT":
                    sql += uniCon.getUcKey() + " < '" + uniCon.getUcReal() + "'";
                    break;
                case "LTE":
                    sql += uniCon.getUcKey() + " <= '" + uniCon.getUcReal() + "'";
                    break;
                case "LIKE":
                    sql += uniCon.getUcKey() + " like '%" + uniCon.getUcReal() + "%'";
                    break;
                case "BETWEEN":
                    if (uniCon.getUcType().equals("input")) {
                        JSONObject jsonObject = (JSONObject) JSONObject.toJSON(uniCon.getUcReal());
                        Object begin = jsonObject.get("begin");
                        Object end = jsonObject.get("end");
                        if (begin != null && end != null) {
                            sql += uniCon.getUcKey() + " between '" + begin + "' AND '" + end + "'";
                        } else {
                            sql = "";
                        }
                    } else if (uniCon.getUcType().equals("datetime")) {
                        List<String> list = (ArrayList<String>) uniCon.getUcReal();
                        if (list.size() == 2) {
                            String startTime = list.get(0);
                            String endTime = list.get(1);
                            sql += uniCon.getUcKey() + " between '" + startTime + "' AND '" + endTime + "'";
                        } else {
                            sql = "";
                        }
                    }
                    break;
            }
            return sql;
        }
    }

    public String conversionPreview(UniCon uniCon) {
        String sql = " and ";
        switch (uniCon.getUcCon()) {
            case "EQ":
                sql += uniCon.getUcKey() + " = '" + uniCon.getUcMock() + "'";
                break;
            case "NE":
                sql += uniCon.getUcKey() + " != '" + uniCon.getUcMock() + "'";
                break;
            case "GT":
                sql += uniCon.getUcKey() + " > '" + uniCon.getUcMock() + "'";
                break;
            case "GTE":
                sql += uniCon.getUcKey() + " >= '" + uniCon.getUcMock() + "'";
                break;
            case "LT":
                sql += uniCon.getUcKey() + " < '" + uniCon.getUcMock() + "'";
                break;
            case "LTE":
                sql += uniCon.getUcKey() + " <= '" + uniCon.getUcMock() + "'";
                break;
            case "LIKE":
                sql += uniCon.getUcKey() + " like '%" + uniCon.getUcMock() + "%'";
                break;
            case "BETWEEN":
                JSONObject jsonObject = JSONObject.parseObject(uniCon.getUcMock());
                if (uniCon.getUcType().equals("input")) {
                    Object begin = jsonObject.get("begin");
                    Object end = jsonObject.get("end");
                    sql += uniCon.getUcKey() + " between '" + begin + "' AND '" + end + "'";
                } else if (uniCon.getUcType().equals("datetime")) {
                    Object startTime = jsonObject.get("startTime");
                    Object endTime = jsonObject.get("endTime");
                    sql += uniCon.getUcKey() + " between '" + startTime + "' AND '" + endTime + "'";
                }
                break;
        }
        return sql;
    }
}
