package com.tangguo.common.utils;

import lombok.AccessLevel;
import lombok.NoArgsConstructor;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import java.util.LinkedHashSet;
import java.util.Objects;
import java.util.Set;

/**
 * 实体类参数验证器操作类
 *
 * @author TanXiao
 *
 * @createTime 2022-07-28 14:51:58 星期四
 */
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class ValidateOperations {

	/**
	 * 校验器
	 */
	private static Validator validator;


	/**
	 * 非法参数消息提示类型枚举
	 */
	public enum PromptEnum {
		FIRST, ALL
	}


	/**
	 * 初始化参数校验器
	 *
	 * @return 默认校验器
	 */
	private static Validator getDefaultValidator() {
		if (Objects.isNull(validator)) {
			validator = Validation.buildDefaultValidatorFactory().getValidator();
		}
		return validator;
	}


	/**
	 * 非法参数提示信息
	 *
	 * @param illegalParams 错误参数
	 * @param prompt 提示类型
	 */
	private static void promptMessage(Set<ConstraintViolation<Object>> illegalParams, PromptEnum prompt) {
		if (illegalParams.isEmpty()) {
			return;
		}
		if (prompt == PromptEnum.ALL) {
			// 提示所有参数校验结果
			StringBuilder message = new StringBuilder();
			illegalParams.forEach(illegalParam -> message.append(illegalParam.getMessage()).append(";"));
			throw new RuntimeException(message.toString());
		} else {
			// 提示首个参数校验结果
			ConstraintViolation<Object> illegalParam = illegalParams.stream().findFirst().orElse(null);
			throw new RuntimeException(illegalParam.getMessage());
		}
	}


	/**
	 * 常规验证 (常规验证和分组验证选择校验)
	 *
	 * @param entity 实体类
	 * @param prompt 提示类型
	 * @param groups 校验分组
	 */
	public static void generalValidate(Object entity, PromptEnum prompt, Class<?> ...groups) {
		Set<ConstraintViolation<Object>> illegalParams = new LinkedHashSet<>(1);
		if (Objects.isNull(groups)) {
			// 普通校验
			illegalParams.addAll(getDefaultValidator().validate(entity));
		} else {
			// 分组校验
			illegalParams.addAll(getDefaultValidator().validate(entity, groups));
		}
		promptMessage(illegalParams, prompt);
	}


	/**
	 * 常规验证 (常规验证和分组验证选择校验)
	 *
	 * @param entity 实体类
	 * @param groups 校验分组
	 */
	public static void generalValidate(Object entity, Class<?> ...groups) {
		generalValidate(entity, PromptEnum.FIRST, groups);
	}


	/**
	 * 常规验证 (常规验证和分组验证选择校验)
	 *
	 * @param entity 实体类
	 */
	public static void generalValidate(Object entity) {
		generalValidate(entity, PromptEnum.FIRST);
	}


	/**
	 * 增强验证 (常规验证加分组验证一起校验)
	 *
	 * @param entity 实体类
	 * @param prompt 提示类型
	 * @param groups 校验分组
	 */
	public static void enhancedValidate(Object entity, PromptEnum prompt, Class<?> ...groups) {
		Set<ConstraintViolation<Object>> illegalParams = new LinkedHashSet<>(1);
		illegalParams.addAll(getDefaultValidator().validate(entity));
		if (Objects.nonNull(groups)) {
			illegalParams.addAll(getDefaultValidator().validate(entity, groups));
		}
		promptMessage(illegalParams, prompt);
	}


	/**
	 * 增强验证 (常规验证加分组验证一起校验)
	 *
	 * @param entity 实体类
	 * @param groups 校验分组
	 */
	public static void enhancedValidate(Object entity, Class<?> ...groups) {
		enhancedValidate(entity, PromptEnum.FIRST, groups);
	}


	/**
	 * 增强验证 (常规验证加分组验证一起校验)
	 *
	 * @param entity 实体类
	 */
	public static void enhancedValidate(Object entity) {
		enhancedValidate(entity, PromptEnum.FIRST);
	}

}
