package com.yanzuoguang.util.helper;

import com.yanzuoguang.util.contants.ResultConstants;
import com.yanzuoguang.util.exception.CodeException;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 参数业务逻辑校验
 * @author 颜佐光
 */
public final class CheckerHelper {
    public static final String PARAM_NOT_NULL_TIPS = "param [%s] is null";
    public static final String PARAM_NOT_EMPTY_TIPS = "param [%s] is empty";
    public static final String PARAM_NOT_NUMBER = "param [%s] must be number";
    public static final String PARAM_OVER_MAX_LENGTH = "param [%s] maxlength is ";

    public static final String PARAM_NOT_DATE_MONTH = "param [%s] must be yyyyMM";
    public static final String PARAM_NOT_DATE_DAY = "param [%s] must be yyyyMMdd ";

    public static final String PARAM_NOT_DATE = "param [%s] must be [%s]";

    public static final String PARAM_NOT_PHONE = "param [%s] must be phone no";
    public static final String PARAM_NOT_ID_CARD = "param [%s] must be id card";
    public static final String PARAM_NOT_MIN = "param [%s] must be big %d";
    public static final String PARAM_NOT_MAX = "param [%s] must be max %d";
    public static final String PARAM_NOT_RANGE = "param [%s] must be range %d and %d";
    public static final String DATE_CHECK_TYPE_DAY = "day";
    public static final String DATE_CHECK_TYPE_MONTH = "month";

    private boolean isValid = true;
    private String checkResult;

    public static CheckerHelper newInstance() {
        return new CheckerHelper();
    }

    public boolean isValid() {
        return this.isValid;
    }

    public boolean isNotValid() {
        return !isValid();
    }

    public void setValid(boolean valid) {
        this.isValid = valid;
    }

    /**
     * 非空检查
     *
     * @param paramName
     * @param paramVal
     * @return
     */
    public CheckerHelper notNull(String paramName, Object paramVal) {
        if (!isValid()) {
            return this;
        }
        if (paramVal == null) {
            this.checkResult = String.format(PARAM_NOT_NULL_TIPS, paramName);
            this.setValid(false);
        }
        return this;
    }

    /**
     * 非空检查,包括空字符串
     *
     * @param paramName
     * @param paramVal
     * @return
     */
    public CheckerHelper notBlankCheck(String paramName, Object paramVal) {
        if (!isValid()) {
            return this;
        }
        if (StringHelper.isEmpty(paramVal)) {
            this.checkResult = String.format(PARAM_NOT_EMPTY_TIPS, paramName);
            this.setValid(false);
        }
        return this;
    }

    /**
     * 非空检查
     *
     * @param paramName
     * @param list
     * @return
     */
    public CheckerHelper notBlankListCheck(String paramName, List list) {
        if (!isValid()) {
            return this;
        }

        if (null == list || list.isEmpty()) {
            this.checkResult = String.format(PARAM_NOT_NULL_TIPS, paramName);
            this.setValid(false);
        }
        return this;
    }

    /**
     * 数字类型检查
     *
     * @param paramName
     * @param paramVal
     * @return
     */
    public CheckerHelper notNumberCheck(String paramName, String paramVal) {
        if (!isValid()) {
            return this;
        }
        if (!StringHelper.isNumber(paramVal)) {
            this.checkResult = String.format(PARAM_NOT_NUMBER, paramName, paramVal);
            this.setValid(false);
        }
        return this;
    }

    /**
     * 非空时数字类型检查
     *
     * @param paramName
     * @param paramVal
     * @return
     */
    public CheckerHelper notNullNumberCheck(String paramName, String paramVal) {
        if (!isValid()) {
            return this;
        }
        if (!StringHelper.isEmpty(paramVal) && !StringHelper.isNumber(paramVal)) {
            this.checkResult = String.format(PARAM_NOT_NUMBER, paramName, paramVal);
            this.setValid(false);
        }
        return this;
    }

    /**
     * 检验IP是否合法
     *
     * @param paramName 需要检测的名称
     * @param paramVal
     * @return
     */
    public CheckerHelper notIpCheck(String paramName, String paramVal) {
        if (!isValid()) {
            return this;
        }
        String rexp = "([1-9]|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}";
        if (!StringHelper.isEmpty(paramVal) && !paramVal.matches(rexp)) {
            this.checkResult = String.format(PARAM_NOT_NUMBER, paramName, paramVal);
            this.setValid(false);
        }
        return this;
    }

    /**
     * 检测是否符合时间类型
     *
     * @param paramName
     * @param paramVal
     * @param queryType
     * @return
     */
    public CheckerHelper notDateCheck(String paramName, String paramVal, String queryType) {
        if (!isValid()) {
            return this;
        }
        String eL = "";
        String msg = "";
        if (StringHelper.isEmpty(paramVal)) {
            msg = PARAM_NOT_NULL_TIPS;
            this.checkResult = String.format(msg, paramName, paramVal);
            this.setValid(false);
            return this;
        }
        if (DATE_CHECK_TYPE_DAY.equals(queryType)) {
            eL = "[0-9]{4}[0-9]{2}[0-9]{2}";
            msg = PARAM_NOT_DATE_DAY;
        } else if (DATE_CHECK_TYPE_MONTH.equals(queryType)) {
            eL = "[0-9]{4}[0-9]{2}";
            msg = PARAM_NOT_DATE_MONTH;
        }

        Pattern p = Pattern.compile(eL);
        Matcher m = p.matcher(paramVal);
        boolean dateFlag = m.matches();
        if (!StringHelper.isEmpty(paramVal) && !dateFlag) {
            this.checkResult = String.format(msg, paramName, paramVal);
            this.setValid(false);
        }
        return this;
    }

    /**
     * 手机号校验
     * 仅支持大陆手机号码校验
     *
     * @param paramVal
     * @return
     */
    public CheckerHelper checkPhoneNo(String paramName, String paramVal) {
        if (!isValid()) {
            return this;
        }
        if (paramVal == null || paramVal.length() < 1) {
            return this;
        }
        String regExp = "^1\\d{10}$";
        Pattern p = Pattern.compile(regExp);
        if (!p.matcher(paramVal).matches()) {
            this.checkResult = String.format(PARAM_NOT_PHONE, paramName);
            this.setValid(false);
        }
        return this;
    }

    /**
     * 长度检查
     *
     * @param paramName
     * @param paramVal
     * @param length
     * @return
     */
    public CheckerHelper checkLength(String paramName, String paramVal, int length) {
        if (!isValid()) {
            return this;
        }
        if (!StringHelper.isEmpty(paramVal) && length < paramVal.length()) {
            this.checkResult = String.format(PARAM_OVER_MAX_LENGTH, paramName) + length;
            this.setValid(false);
        }
        return this;
    }

    /**
     * 日期字符串
     *
     * @param paramName 参数名称
     * @param paramVal  参数值
     * @return
     */
    public CheckerHelper checkDate(String paramName, String paramVal) {
        return checkDate(paramName, paramVal, StringHelper.EMPTY);
    }

    /**
     * 日期字符串
     *
     * @param paramName 参数名称
     * @param paramVal  参数值
     * @param formatStr 日期格式
     * @return
     */
    public CheckerHelper checkDate(String paramName, String paramVal, String formatStr) {
        if (!isValid()) {
            return this;
        }
        if (StringHelper.isEmpty(paramVal)) {
            return this;
        }
        try {
            if (!StringHelper.isEmpty(formatStr)) {
                SimpleDateFormat format = new SimpleDateFormat(formatStr);
                format.parse(paramVal);
            } else {
                DateAutoHelper.getAutoDate(formatStr);
            }
        } catch (ParseException e) {
            this.checkResult = String.format(PARAM_NOT_DATE, paramName, formatStr);
            this.setValid(false);
        }
        return this;
    }

    /**
     * 检测身份证
     *
     * @param paramName 参数名称
     * @param paramVal  参数值
     * @return
     */
    public CheckerHelper checkIdCard(String paramName, String paramVal) {
        if (!isValid()) {
            return this;
        }
        if (StringHelper.isEmpty(paramVal)) {
            return this;
        }
        String regExp = "^\\d{6}(18|19|20)?\\d{2}(0[1-9]|1[012])(0[1-9]|[12]\\d|3[01])\\d{3}(\\d|X)$";
        Pattern p = Pattern.compile(regExp);
        if (!p.matcher(paramVal.toUpperCase()).matches()) {
            this.checkResult = String.format(PARAM_NOT_ID_CARD, paramName);
            this.setValid(false);
        }
        return this;
    }

    /**
     * 检测最小值是否大于等于0,默认为0
     *
     * @param paramName 参数名称
     * @param paramVal  参数值
     * @return
     */
    public CheckerHelper checkMin(String paramName, int paramVal) {
        return checkMin(paramName, 0, paramVal);
    }

    /**
     * 检测最小值是否大于等于0,默认为0
     *
     * @param paramName 参数名称
     * @param paramVal  参数值
     * @param min       最小值
     * @return
     */
    public CheckerHelper checkMin(String paramName, int min, int paramVal) {
        if (!isValid()) {
            return this;
        }
        if (paramVal < min) {
            this.checkResult = String.format(PARAM_NOT_MIN, min, paramName);
            this.setValid(false);
        }
        return this;
    }

    /**
     * 检测最大值
     *
     * @param paramName 参数名称
     * @param paramVal  参数值
     * @param max       最大值
     * @return
     */
    public CheckerHelper checkMax(String paramName, int max, int paramVal) {
        if (!isValid()) {
            return this;
        }
        if (paramVal > max) {
            this.checkResult = String.format(PARAM_NOT_MAX, max, paramName);
            this.setValid(false);
        }
        return this;
    }

    /**
     * 检测最大值
     *
     * @param paramName 参数名称
     * @param paramVal  参数值
     * @param min       最小值
     * @param max       最大值
     * @return
     */
    public CheckerHelper checkRange(String paramName, int min, int max, int paramVal) {
        if (!isValid()) {
            return this;
        }
        if (paramVal > max || paramVal < min) {
            this.checkResult = String.format(PARAM_NOT_RANGE, min, max, paramName);
            this.setValid(false);
        }
        return this;
    }

    /**
     * 检测结果是否异常
     */
    public CheckerHelper checkException() {
        return checkException(null);
    }

    /**
     * 检测结果是否异常
     *
     * @param target 目标数据类
     */
    public CheckerHelper checkException(Object target) {
        if (!StringHelper.isEmpty(this.checkResult)) {
            throw new CodeException(ResultConstants.PARAM_INVALID, this.checkResult, target);
        }
        return this;
    }

    /**
     * 获取检测结果的错误信息
     *
     * @return
     */
    public String getCheckResult() {
        return this.checkResult;
    }
}