package com.syjy.calculate.repository.repositoryImpl;

import com.googlecode.aviator.AviatorEvaluator;
import com.syjy.calculate.config.StarterProperties;
import com.syjy.calculate.entity.CalculateResult;
import com.syjy.calculate.entity.CalculationFormula;
import com.syjy.calculate.repository.CalculationFormulaRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.ClassUtils;
import javax.annotation.Resource;
import java.io.*;
import java.net.URL;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

/**
 * 公式计算
 *
 * @author zcl
 * @version 1.0
 * @since 2022/9/9 10:34
 */
@Service
@Slf4j
public class CalculationFormulaRepositoryImpl implements CalculationFormulaRepository {
    @Autowired
    StarterProperties properties;
    @Resource
    public JdbcTemplate jdbcTemplate;

    /**
     * 创建公式表
     */
    @Override
    public void initTable() {
        log.info("初始化准确率计算公式表");
        // 获取数据库类型
        String dbType = properties.getDbType();
        // 如果是金仓数据库，直接初始化表
        if(CalculateResult.DB_KINGBASE.equals(dbType)){
            this.createTable();
            return;
        }

        // 从配置文件中获取版本
        String version = properties.getVersion();
        // 判断表是否存在
        String checkSql = "select count(1) from t_calculation_formula";
        int count = 0;
        try {
            // 获取表中数据
            count = jdbcTemplate.queryForObject(checkSql, Integer.class);
        } catch (DataAccessException e) {
            // 如果表不存在，则创建表
            log.error(e.toString());
            this.createTable();
        }

        // 再次查询表中数据
        try {
            count = jdbcTemplate.queryForObject(checkSql, Integer.class);
        } catch (DataAccessException e) {
            e.printStackTrace();
        }
        // 如果表存在
        if (count>0) {
            // 从表中获取旧版本
            String oldVersion = getVersion();
            // 如果版本没变化，不进行初始化表操作
            if (oldVersion.equals(version) || oldVersion.equals("null")) {
                log.info("版本没变化，不进行初始化表");
                return;
            }
            // 如果版本不同，则初始化表
            this.createTable();
        }
    }

    @Override
    public int selectCount(String province, String type) {

        String sql = "SELECT count(1) from t_calculation_formula where state = '1' ";

        List<Object> param = new LinkedList<>();
        // 判断省调是否为空
        if (province != null && !"".equals(province.trim())) {
            sql = sql + "and province LIKE ? ";
            province = "%" + province + "%";
            param.add(province);
            if (type != null && !"".equals(type.trim())) {
                type = "%" + type + "%";
                param.add(type);
                sql = sql + "and type LIKE ? ";
            }
        } else {
            // 判断公式类型是否为空
            if (type != null && !"".equals(type.trim())) {
                type = "%" + type + "%";
                param.add(type);
                sql = sql + "and type LIKE ? ";
            }
        }
        int count = 0;
        try {
            if (param != null && param.size() > 0) {
                count = jdbcTemplate.queryForObject(sql, Integer.class, param.toArray());
            } else {
                count = jdbcTemplate.queryForObject(sql, Integer.class);
            }

        } catch (DataAccessException e) {
            e.printStackTrace();
        }
        return count;
    }

    /**
     * 查询所有公式
     *
     * @param limit    每页显示数量
     * @param offset   起始索引
     * @param province 省调
     * @param type     公式类型
     * @return
     */
    @Override
    public List<CalculationFormula> select(int limit, int offset, String province, String type) {

        String sql = "SELECT * from t_calculation_formula where state = '1' ";
        List<Object> param = new LinkedList<>();
        // 判断省调是否为空
        if (province != null && !"".equals(province.trim())) {
            sql = sql + "and province LIKE ? ";
            province = "%" + province + "%";
            param.add(province);
            if (type != null && !"".equals(type.trim())) {
                sql = sql + "and LIKE = ? ";
                type = "%" + type + "%";
                param.add(type);
            }
        } else {
            // 判断公式类型是否为空
            if (type != null && !"".equals(type.trim())) {
                sql = sql + "and type LIKE ? ";
                type = "%" + type + "%";
                param.add(type);
            }
        }
        // 拼接分页范围
        sql = sql + " limit " + offset + "," + limit;
        List<CalculationFormula> calculationFormulaList = new ArrayList<>();

        try {
            if (param != null && param.size() > 0) {
                calculationFormulaList = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(CalculationFormula.class), param.toArray());
            } else {
                calculationFormulaList = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(CalculationFormula.class));
            }
        } catch (DataAccessException e) {
            e.printStackTrace();
        }
        return calculationFormulaList;
    }

    @Override
    public CalculationFormula getOne(int id) {
        String sql = "select * from t_calculation_formula where id = ? and state = '1' ";
        CalculationFormula calculationFormula;
        try {
            calculationFormula = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(CalculationFormula.class), id);
        } catch (EmptyResultDataAccessException e) {
            return null;
        }
        return calculationFormula;
    }

    /**
     * 更新公式
     *
     * @param calculationFormula
     * @return
     */
    @Override
    public int update(CalculationFormula calculationFormula) {
        Integer id = calculationFormula.getId();
        String type = calculationFormula.getType();
        String formula = calculationFormula.getFormula();
        String ruleFormula = calculationFormula.getRuleFormula();
        String province = calculationFormula.getProvince();
        String electricType = calculationFormula.getElectricType();
        String isRate = calculationFormula.getIsRate();
        int count = 0;
        try {
            count = jdbcTemplate.update("update t_calculation_formula set TYPE=?,FORMULA=?,PROVINCE=?,ELECTRIC_TYPE=?,RULE_FORMULA = ?,IS_RATE=? where id=?", type, formula, province, electricType, ruleFormula, isRate, id);
        } catch (DataAccessException e) {
            e.printStackTrace();
        }
        if (count > 0) {
            // 清除缓存公式
            AviatorEvaluator.clearExpressionCache();
        }
        return count;
    }

    /**
     * 新增公式
     *
     * @param calculationFormula
     * @return
     */
    @Override
    public int add(CalculationFormula calculationFormula) {
        String electricType = calculationFormula.getElectricType();
        String isRate = calculationFormula.getIsRate();
        String type = calculationFormula.getType();
        String formula = calculationFormula.getFormula();
        String ruleFormula = calculationFormula.getRuleFormula();
        String province = calculationFormula.getProvince();
        int count = 0;
        try {
            count = jdbcTemplate.update(
                    "INSERT INTO t_calculation_formula(TYPE,FORMULA,PROVINCE,ELECTRIC_TYPE,RULE_FORMULA,IS_RATE,STATE) VALUES (?, ?, ?, ?, ?, ?,'1')", type, formula, province, electricType, ruleFormula, isRate);
        } catch (DataAccessException e) {
            e.printStackTrace();
        }
        return count;
    }

    /**
     * 删除公式
     *
     * @param id
     * @return
     */
    @Override
    public int delete(int id) {
        int count = 0;
        try {
            count = jdbcTemplate.update("update t_calculation_formula set state = 0 where id =?", id);
        } catch (DataAccessException e) {
            e.printStackTrace();
        }
        return count;
    }

    /**
     * 查询公式数据
     *
     * @param type         类型
     * @param province     省调
     * @param formulaType  公式类型
     * @param electricType 场站类型
     * @return
     */
    @Override
    public CalculationFormula findByTypeAndProvince(String type, String formulaType, String province, String electricType,String stationCode) {
        String sql = "";
        electricType = "%" + electricType + "%";
        if(stationCode!=null && !"".equals(stationCode)){
            stationCode = "%" + stationCode + "%";
        }
        // 查询sql
        if (CalculateResult.FORMULA.equals(type)) {
            sql = "SELECT * from t_calculation_formula where state = '1' and ELECTRIC_TYPE like ? and PROVINCE = ? and TYPE = ? and STATION_CODE like ? limit 1 ";
        } else if (CalculateResult.RULES.equals(type)) {
            sql = "SELECT * from t_calculation_formula where state = '1' and TYPE = 'RULES' and ELECTRIC_TYPE like ? and PROVINCE = ? and RULE_FORMULA = ? and STATION_CODE like ? limit 1";
        }else{
            log.error(CalculateResult.MSG_FORMULA_TYPE_ERROR);
        }

        CalculationFormula calculationFormula = new CalculationFormula();
        // 根据类型和省调查询公式
        try {
            calculationFormula = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(CalculationFormula.class), electricType, province, formulaType,stationCode);
            return calculationFormula;
        } catch (EmptyResultDataAccessException e) {
            // 如果根据场站编码没查到，则在根据省调和场站类型是All的查
            if (CalculateResult.FORMULA.equals(type)) {
                sql = "SELECT * from t_calculation_formula where state = '1' and ELECTRIC_TYPE like ? and PROVINCE = ? and TYPE = ?  and STATION_CODE = 'ALL' limit 1";
            } else if (CalculateResult.RULES.equals(type)) {
                sql = "SELECT * from t_calculation_formula where state = '1' and TYPE = 'RULES' and ELECTRIC_TYPE like ? and PROVINCE = ? and RULE_FORMULA = ? and STATION_CODE = 'ALL' limit 1";
            }
            // 根据类型和省调查询公式
            try {
                calculationFormula = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(CalculationFormula.class), electricType, province, formulaType);
                return calculationFormula;
            } catch (EmptyResultDataAccessException ere) {
                // 如果根据场站编码没查到，则在根据省调和场站类型是All的查
                return null;
            }
        }
    }

    /**
     * 查询考核公式数据
     *
     * @param type         类型
     * @param province     省调
     * @param formulaType  公式类型
     * @param electricType 场站类型
     * @return
     */
    @Override
    public CalculationFormula findAssessmentByTypeAndProvince(String type, String formulaType, String province, String electricType,String stationCode) {

        electricType = "%" + electricType + "%";
        if(stationCode!=null && !"".equals(stationCode)){
            stationCode = "%" + stationCode + "%";
        }
        String sql = "";

        // 查询sql
        if (CalculateResult.FORMULA.equals(type)) {
            sql = "SELECT * from t_calculation_formula where state = '1' and ELECTRIC_TYPE like ? and PROVINCE = ? and TYPE = ?  and STATION_CODE like ? limit 1";
        } else if (CalculateResult.RULES.equals(type)) {
            sql = "SELECT * from t_calculation_formula where state = '1' and TYPE = 'RULES' and ELECTRIC_TYPE like ? and PROVINCE = ? and RULE_FORMULA = ? and STATION_CODE like ? limit 1";
        }else{
            log.error(CalculateResult.MSG_FORMULA_TYPE_ERROR);
            return null;
        }
        // 根据类型和省调查询公式
        try {
            CalculationFormula calculationFormula = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(CalculationFormula.class), electricType, province, formulaType,stationCode);
            return calculationFormula;
        } catch (EmptyResultDataAccessException e) {
            // 如果根据场站编码没查到，则在根据省调和场站类型是All的查
            // 查询sql
            if (CalculateResult.FORMULA.equals(type)) {
                sql = "SELECT * from t_calculation_formula where state = '1' and ELECTRIC_TYPE like ? and PROVINCE = ? and TYPE = ?  and STATION_CODE = 'ALL' limit 1";
            } else if (CalculateResult.RULES.equals(type)) {
                sql = "SELECT * from t_calculation_formula where state = '1' and TYPE = 'RULES' and ELECTRIC_TYPE like ? and PROVINCE = ? and RULE_FORMULA = ? and STATION_CODE = 'ALL' limit 1";
            }
            // 根据类型和省调查询公式
            try {
                CalculationFormula calculationFormula = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(CalculationFormula.class), electricType, province, formulaType);
                return calculationFormula;
            } catch (EmptyResultDataAccessException ere) {
                // 如果根据场站编码没查到，则在根据省调和场站类型是All的查
                return null;
            }
        }
    }

    /**
     * 创建表
     */
    private void createTable() {
        try {
            log.info("---------------开始创建准确率计算表---------------");
            // 从配置文件中获取版本
            String dbType = properties.getDbType();
            String path;
            // 获取初始化公式表sql
            // 如果是金仓数据库
            if(CalculateResult.DB_KINGBASE.equals(dbType)){
                path = "sql/t_calculation_formula_king_base.sql";
            // 如果是mysql
            }else {
                path = "sql/t_calculation_formula.sql";
            }

            // 用ClassLoader获取jar包中的文件，获取文件流
            ClassLoader defaultClassLoader = ClassUtils.getDefaultClassLoader();
            assert defaultClassLoader != null;
            URL resource = defaultClassLoader.getResource(path);
            assert resource != null;
            InputStream inputStream = resource.openStream();
            // 循环将流放到StringBuilder中
            StringBuilder builder = new StringBuilder();
            int len;
            byte[] buf = new byte[1024];
            while ((len = inputStream.read(buf)) != -1) {
                builder.append(new String(buf, 0, len));
            }
            // 关闭流
            inputStream.close();
            // 执行sql文件
            jdbcTemplate.execute(builder.toString());
            log.info("建表成功");
        } catch (IOException e) {
            e.printStackTrace();
        }
        log.info("---------------结束创建准确率计算表---------------");
        // 更新公式
        updateVersion();
    }

    /**
     * 获取版本
     */
    private String getVersion() {
        String version = "";
        String sql = " SELECT * FROM t_calculation_formula where type = 'VERSION' ";
        try {
            CalculationFormula calculationFormula = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(CalculationFormula.class));
            version = calculationFormula.getFormula();
        } catch (DataAccessException e) {
            e.printStackTrace();
        }
        return version;
    }

    /**
     * 更新版本
     */
    private void updateVersion() {
        String version = properties.getVersion();
        String sql = " UPDATE t_calculation_formula set FORMULA = '" + version + "' where type = 'VERSION' ";
        try {
            jdbcTemplate.update(sql);
        } catch (DataAccessException e) {
            e.printStackTrace();
        }
    }

}
