package cn.novalon.gym.manage.sys.primitive;

import cn.novalon.gym.manage.common.exception.ErrorCode;
import cn.novalon.gym.manage.common.exception.ValidationException;
import org.apache.commons.lang3.StringUtils;

import java.util.regex.Pattern;

/**
 * 用户名值对象
 * 
 * @author 张翔
 * @date 2026-03-13
 */
public final class Username {

    private static final int MIN_LENGTH = 3;
    private static final int MAX_LENGTH = 50;
    private static final Pattern USERNAME_PATTERN = Pattern.compile("^[a-zA-Z0-9_]+$");

    private final String value;

    public String getValue() {
        return value;
    }

    private Username(String value) {
        this.value = value;
    }

    public static Username of(String value) {
        if (StringUtils.isBlank(value)) {
            throw new ValidationException(ErrorCode.VALIDATION_REQUIRED, "Username is required");
        }
        validate(value);
        return new Username(value);
    }

    private static void validate(String value) {
        String trimmed = value.trim();
        
        if (trimmed.length() < MIN_LENGTH) {
            throw new ValidationException(ErrorCode.VALIDATION_INVALID_LENGTH, 
                    "Username must be at least " + MIN_LENGTH + " characters long");
        }
        
        if (trimmed.length() > MAX_LENGTH) {
            throw new ValidationException(ErrorCode.VALIDATION_INVALID_LENGTH, 
                    "Username must be at most " + MAX_LENGTH + " characters long");
        }
        
        if (!USERNAME_PATTERN.matcher(trimmed).matches()) {
            throw new ValidationException(ErrorCode.VALIDATION_INVALID_FORMAT, 
                    "Username can only contain letters, numbers, and underscores");
        }
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Username username = (Username) o;
        return value.equals(username.value);
    }

    @Override
    public int hashCode() {
        return value.hashCode();
    }

    @Override
    public String toString() {
        return value;
    }
}
