package validator

import (
	"errors"
	"fmt"
	"github.com/go-playground/validator/v10"
	"regexp"
	"strings"
)

var validate *validator.Validate

// 初始化自定义校验器
func init() {
	validate = validator.New()

	if err := validate.RegisterValidation("name", validName); err != nil {
		panic(fmt.Sprintf("注册 name 验证器时发生错误: %v", err))
	}

	// 注册自定义验证器 validmobile
	if err := validate.RegisterValidation("mobile", validmobile); err != nil {
		panic(fmt.Sprintf("注册 mobile 验证器时发生错误: %v", err))
	}

	// 注册自定义验证器 validDate
	if err := validate.RegisterValidation("date", validDate); err != nil {
		panic(fmt.Sprintf("注册 date 验证器时发生错误: %v", err))
	}

	// 注册自定义验证器 validIDCard
	if err := validate.RegisterValidation("idCard", validIDCard); err != nil {
		panic(fmt.Sprintf("注册 idCard 验证器时发生错误: %v", err))
	}

	if err := validate.RegisterValidation("bankCard", validBankCard); err != nil {
		panic(fmt.Sprintf("注册 bankCard 验证器时发生错误: %v", err))
	}

	if err := validate.RegisterValidation("USCI", validUSCI); err != nil {
		panic(fmt.Sprintf("注册 USCI 社会统一信用代码 验证器时发生错误: %v", err))
	}

	if err := validate.RegisterValidation("mobileType", validMobileType); err != nil {
		panic(fmt.Sprintf("注册 mobileType 验证器时发生错误: %v", err))
	}
	if err := validate.RegisterValidation("password", validatePassword); err != nil {
		panic(fmt.Sprintf("注册 password 验证器时发生错误: %v", err))
	}
	if err := validate.RegisterValidation("payMethod", validatePayMethod); err != nil {
		panic(fmt.Sprintf("注册 payMethod 验证器时发生错误: %v", err))
	}

}

// 弱口令列表
var weakPasswords = []string{
	"12345678", "password", "123456789", "qwerty", "123456", "letmein",
	"1234567", "welcome", "abc123", "password1", "1234", "111111", "admin",
}

// Validate 校验参数逻辑
func Validate(req interface{}) error {
	if err := validate.Struct(req); err != nil {
		// 检查 err 是否是 ValidationErrors 类型
		if validationErrors, ok := err.(validator.ValidationErrors); ok {
			for _, validationErr := range validationErrors {
				field := validationErr.StructField()
				tag := validationErr.Tag()
				return errors.New(GetErrorMessage(field, tag))
			}
		} else {
			// 其他错误处理
			return fmt.Errorf("验证时出现未知错误: %v", err)
		}
	}
	return nil
}

// 自定义的名称验证
func validName(fl validator.FieldLevel) bool {
	name := fl.Field().String()
	validNamePattern := `^[\p{Han}]+$`
	matched, _ := regexp.MatchString(validNamePattern, name)
	return matched
}

// 自定义的手机号验证
func validmobile(fl validator.FieldLevel) bool {
	phone := fl.Field().String()
	validmobilePattern := `^1[3-9]\d{9}$`
	matched, _ := regexp.MatchString(validmobilePattern, phone)
	return matched
}

// 自定义正则表达式校验 yyyyMMdd 格式
func validDate(fl validator.FieldLevel) bool {
	date := fl.Field().String()
	validDatePattern := `^\d{4}(0[1-9]|1[0-2])(0[1-9]|[12][0-9]|3[01])$`
	matched, _ := regexp.MatchString(validDatePattern, date)
	return matched
}

// 自定义身份证校验
func validIDCard(fl validator.FieldLevel) bool {
	id := fl.Field().String()
	validIDPattern := `^\d{17}(\d|X|x)$` // 匹配18位身份证号码
	matched, _ := regexp.MatchString(validIDPattern, id)
	return matched
}

func validBankCard(fl validator.FieldLevel) bool {
	bankCard := fl.Field().String()
	// 银行卡号一般是13到19位的数字
	validBankCardPattern := `^\d{13,19}$`
	matched, _ := regexp.MatchString(validBankCardPattern, bankCard)
	return matched
}

func validUSCI(fl validator.FieldLevel) bool {
	usci := fl.Field().String()
	// 社会信用代码为18位数字和大写字母的组合，最后一位为校验码
	validUSCIPattern := `^[1-9A-Z]{2}[0-9]{6}[0-9A-Z]{9}[0-9A-Z]$`
	matched, _ := regexp.MatchString(validUSCIPattern, usci)
	return matched
}

// 自定义的手机号类型验证（可以为空）
func validMobileType(fl validator.FieldLevel) bool {
	mobileType := fl.Field().String()
	if mobileType == "" {
		return true // 如果为空，认为是有效的
	}

	// 校验是否是 CTCC, CMCC, CUCC 之一
	validTypes := map[string]bool{
		"CTCC": true, // 中国电信
		"CMCC": true, // 中国移动
		"CUCC": true, // 中国联通
	}

	return validTypes[mobileType]
}

// 自定义密码强度校验函数
func validatePassword(fl validator.FieldLevel) bool {
	password := fl.Field().String()

	// 检查密码是否在弱口令列表中
	for _, weakPwd := range weakPasswords {
		if strings.ToLower(password) == weakPwd {
			return false
		}
	}

	return true
}

// 支付方式
func validatePayMethod(fl validator.FieldLevel) bool {
	payMethod := fl.Field().String()

	if payMethod == "" {
		return true // 如果为空，认为是有效的
	}

	validTypes := map[string]bool{
		"alipay":    true, // 中国电信
		"wechatpay": true, // 中国移动
	}

	return validTypes[payMethod]

}
