package kr.co.accura.wbx.spring.auth;

import kr.co.accura.wbx.spring.common.BusinessException;
import kr.co.accura.wbx.spring.config.WbxSpringProperties;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Component
@RequiredArgsConstructor
public class PasswordPolicy {

    private final WbxSpringProperties props;

    public void validate(String password) {
        var cfg = props.getPassword();
        List<String> errors = new ArrayList<>();

        if (password.length() < cfg.getMinLength()) {
            errors.add("비밀번호는 " + cfg.getMinLength() + "자 이상이어야 합니다.");
        }
        if (cfg.isRequireUppercase() && !password.matches(".*[A-Z].*")) {
            errors.add("대문자를 포함해야 합니다.");
        }
        if (cfg.isRequireDigit() && !password.matches(".*[0-9].*")) {
            errors.add("숫자를 포함해야 합니다.");
        }
        if (cfg.isRequireSpecial() && !password.matches(".*[!@#$%^&*()_+\\-=\\[\\]{};':\",./<>?].*")) {
            errors.add("특수문자를 포함해야 합니다.");
        }

        if (!errors.isEmpty()) {
            throw new BusinessException(String.join(" ", errors), "PASSWORD_POLICY");
        }
    }

    public boolean isExpired(WbxUser user) {
        if (user.getPasswordChangedAt() == null) return true;
        return user.getPasswordChangedAt()
                .plusDays(props.getPassword().getExpiryDays())
                .isBefore(LocalDateTime.now());
    }

    public boolean isLocked(WbxUser user) {
        return user.getFailedLoginAttempts() >= props.getPassword().getMaxFailedAttempts()
                && user.isLocked();
    }
}
