package com.qmth.boot.data.upgrade.config;

import com.qmth.boot.data.upgrade.model.RunMode;
import com.qmth.boot.data.upgrade.utils.VersionComparator;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.jdbc.DatabaseDriver;
import org.springframework.core.env.ConfigurableEnvironment;

public class DataUpgradeProperties implements DataUpgradeConstants {

    /**
     * 运行模式，值范围：start(默认)、install、upgrade。
     */
    private RunMode runMode;

    /**
     * 数据升级服务实现类所在位置的包名，默认扫描包名为：com.qmth
     */
    private String basePackage;

    /**
     * “应用信息表”不存在时，是否指定基线数据，默认值为false
     */
    private Boolean baseline;

    /**
     * 指定基线数据时，基线-应用码
     */
    private String baselineAppCode;

    /**
     * 指定基线数据时，基线-应用版本号
     */
    private String baselineAppVersion;

    /**
     * DB用户名
     */
    private String dbUsername;

    /**
     * DB用户密码
     */
    private String dbPassword;

    /**
     * DB链接地址
     */
    private String dbUrl;

    /**
     * DB驱动名称
     */
    private String driverClassName;

    /**
     * 待升级应用码
     */
    private String appCode;

    /**
     * 待升级应用版本号
     */
    private String appVersion;

    public DataUpgradeProperties(ConfigurableEnvironment environment) {
        String runModeStr = environment.getProperty(RUN_MODE, String.class, RunMode.START.name());
        this.runMode = RunMode.getRunMode(runModeStr);
        if (this.runMode == null) {
            throw new RuntimeException(RUN_MODE + " 配置值有误！值范围：start、install、upgrade");
        }

        this.basePackage = environment.getProperty(BASE_PACKAGE, String.class);
        if (StringUtils.isBlank(basePackage)) {
            this.basePackage = "com.qmth";
        }

        this.baseline = environment.getProperty(BASELINE, Boolean.class, false);
        this.baselineAppCode = environment.getProperty(BASELINE_APP_CODE, String.class);
        this.baselineAppVersion = environment.getProperty(BASELINE_APP_VERSION, String.class);

        if (baseline) {
            if (StringUtils.isBlank(baselineAppCode)) {
                throw new RuntimeException(BASELINE_APP_CODE + " 配置值不能为空！");
            }

            if (!VersionComparator.isValidVersion(baselineAppVersion)) {
                throw new RuntimeException(BASELINE_APP_VERSION + "=" + baselineAppVersion + " 配置格式不正确！要求格式如：数字.数字.数字");
            }
        }

        this.appCode = environment.getProperty(APP_CODE, String.class);
        if (StringUtils.isBlank(appCode)) {
            throw new RuntimeException(APP_CODE + " 配置值不能为空！");
        }

        this.appVersion = environment.getProperty(APP_VERSION, String.class);
        if (!VersionComparator.isValidVersion(appVersion)) {
            throw new RuntimeException(APP_VERSION + "=" + appVersion + " 配置格式不正确！要求格式如：数字.数字.数字");
        }

        this.dbUsername = environment.getProperty(DB_USERNAME, String.class);
        if (StringUtils.isBlank(dbUsername)) {
            throw new RuntimeException(DB_USERNAME + " 配置值不能为空！");
        }

        this.dbPassword = environment.getProperty(DB_PASSWORD, String.class);
        if (StringUtils.isBlank(dbPassword)) {
            throw new RuntimeException(DB_PASSWORD + " 配置值不能为空！");
        }

        this.dbUrl = environment.getProperty(DB_URL, String.class);
        if (StringUtils.isBlank(dbUrl)) {
            throw new RuntimeException(DB_URL + " 配置值不能为空！");
        }

        String superDbUsername = environment.getProperty(SUPER_DB_USERNAME, String.class);
        if (StringUtils.isNotBlank(superDbUsername)) {
            // 若配置了更高权限的DB账号，则优先使用
            this.dbUsername = superDbUsername;
        }

        String superDbPassword = environment.getProperty(SUPER_DB_PASSWORD, String.class);
        if (StringUtils.isNotBlank(superDbPassword)) {
            // 若配置了更高权限的DB账号，则优先使用
            this.dbPassword = superDbPassword;
        }

        DatabaseDriver databaseDriver = DatabaseDriver.fromJdbcUrl(dbUrl);
        if (DatabaseDriver.UNKNOWN == databaseDriver) {
            throw new RuntimeException(DB_URL + " 配置值有误，不能有效识别出DriverClassName！");
        }
        this.driverClassName = databaseDriver.getDriverClassName();
    }

    public RunMode getRunMode() {
        return runMode;
    }

    public String getBasePackage() {
        return basePackage;
    }

    public Boolean getBaseline() {
        return baseline;
    }

    public String getBaselineAppCode() {
        return baselineAppCode;
    }

    public String getBaselineAppVersion() {
        return baselineAppVersion;
    }

    public String getDbUsername() {
        return dbUsername;
    }

    public String getDbPassword() {
        return dbPassword;
    }

    public String getDbUrl() {
        return dbUrl;
    }

    public String getDriverClassName() {
        return driverClassName;
    }

    public String getAppCode() {
        return appCode;
    }

    public String getAppVersion() {
        return appVersion;
    }

}
