package com.cf.imes.module.system.validation.recharge;

import cn.hutool.core.util.ObjectUtil;
import org.apache.commons.lang3.StringUtils;

import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import java.math.BigDecimal;

/**
 * Double类型校验器
 */
public class MoneyValidator implements ConstraintValidator<MoneyValid, Number> {

    private static final String ZERO = "0";
    private static final String GREATER_THAN_ZERO_NOTIFICATION = "%s必须大于0";
    private static final String LENGTH_ERROR_NOTIFICATION = "%s长度不合法，总长度不超过%d位，小数点后不超过%d位";

    private String name;
    private int maxIntegerDigits;
    private int maxFractionDigits;

    @Override
    public void initialize(MoneyValid constraintAnnotation) {
        this.name = constraintAnnotation.name();
        this.maxIntegerDigits = constraintAnnotation.integer();
        this.maxFractionDigits = constraintAnnotation.fraction();
    }

    @Override
    public boolean isValid(Number value, ConstraintValidatorContext context) {
        if (ObjectUtil.isNull(value)) {
            return true;
        }

        String errorMessage = null;
        if (value instanceof Integer) {
            errorMessage = handleInteger((Integer) value);
        } else if (value instanceof Long) {
            errorMessage = handleLong((Long) value);
        } else if (value instanceof Double) {
            errorMessage = handleDouble((Double) value);
        } else if (value instanceof BigDecimal) {
            errorMessage = handleBigDecimal((BigDecimal) value);
        }

        if (StringUtils.isNotEmpty(errorMessage)) {
            context.disableDefaultConstraintViolation();
            context.buildConstraintViolationWithTemplate(errorMessage).addConstraintViolation();
            return false;
        }
        return true;
    }

    private String handleInteger(Integer value) {
        if (value <= 0) {
            return String.format(GREATER_THAN_ZERO_NOTIFICATION, name);
        }
        return null;
    }

    private String handleLong(Long value) {
        if (value <= 0) {
            return String.format(GREATER_THAN_ZERO_NOTIFICATION, name);
        }
        return null;
    }

    private String handleDouble(Double value) {
        return handleBigDecimal(new BigDecimal(value.toString()));
    }

    private String handleBigDecimal(BigDecimal value) {
        if (value.compareTo(BigDecimal.ZERO) <= 0) {
            return String.format(GREATER_THAN_ZERO_NOTIFICATION, name);
        }

        String[] parts = value.toPlainString().split("\\.");
        int integerPartLength = parts[0].length();
        int fractionalPartLength = parts.length > 1 ? parts[1].length() : 0;

        if (integerPartLength > maxIntegerDigits || fractionalPartLength > maxFractionDigits) {
            return String.format(LENGTH_ERROR_NOTIFICATION, name, maxIntegerDigits + maxFractionDigits, maxFractionDigits);
        }
        return null;
    }
}