package com.dji.sample.manage.service.password;

import com.dji.sample.manage.model.password.PasswordRule;
import com.dji.sample.manage.model.password.PasswordRuleContext;
import com.dji.sample.manage.model.password.PasswordRuleResult;

/**
 * Rule 2 – Character-category combination.
 * Password must contain at least {@value #MIN_CATEGORIES} of the following 4 types:
 * uppercase letters (A-Z), lowercase letters (a-z), digits (0-9), special characters.
 */
public class CharacterCategoryPasswordRule implements PasswordRule {

    /** Minimum number of distinct character categories required. */
    public static final int MIN_CATEGORIES = 3;

    @Override
    public PasswordRuleResult validate(String password, PasswordRuleContext context) {
        boolean hasUpper   = password.chars().anyMatch(Character::isUpperCase);
        boolean hasLower   = password.chars().anyMatch(Character::isLowerCase);
        boolean hasDigit   = password.chars().anyMatch(Character::isDigit);
        boolean hasSpecial = password.chars().anyMatch(c -> !Character.isLetterOrDigit(c));

        int count = (hasUpper ? 1 : 0) + (hasLower ? 1 : 0)
                  + (hasDigit ? 1 : 0) + (hasSpecial ? 1 : 0);

        if (count < MIN_CATEGORIES) {
            return PasswordRuleResult.fail(
                    "Password must contain at least " + MIN_CATEGORIES + " of the following 4 types: "
                  + "uppercase letters (A-Z), lowercase letters (a-z), digits (0-9), special characters (!@#$%...)");
        }
        return PasswordRuleResult.ok();
    }

    @Override
    public String getRuleName() {
        return "CharacterCategory";
    }

}
