package ru.nbch.credit_tracker.service.scoring;

import jakarta.xml.bind.DatatypeConverter;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.stereotype.Service;
import ru.nbch.credit_tracker.config.settings.CreditTrackerSettings;
import ru.nbch.credit_tracker.enums.SignalError;
import ru.nbch.credit_tracker.mapper.scoring.ModelUsersMapper;

import java.security.MessageDigest;
import java.util.List;

@Service
public class AuthorizationService {
    private static final String SGNL_CODE = "SGNL";
    private static final String SALT = "-*-XUSER_";

    private final ModelUsersMapper mapper;
    private final String encoding;

    public AuthorizationService(ModelUsersMapper mapper,
                                CreditTrackerSettings settings) {
        this.mapper = mapper;
        this.encoding = settings.getEncoding();
    }

    public AuthResult findAuthInfo(String userId, String password) throws Exception {
        if (userId.length() > 12) {
            return new AuthResult(false, SignalError.ERROR_005);
        }
        String hashedPassword = hashPassword(password);
        List<String> productCodes = mapper.findUserProductCodes(userId, hashedPassword);
        if (productCodes.isEmpty()) {
            return new AuthResult(false, SignalError.ERROR_005);
        }
        if (productCodes.stream().noneMatch(productCode -> productCode.equals(SGNL_CODE))) {
            return new AuthResult(false, SignalError.ERROR_006);
        }
        return new AuthResult(true, null);
    }

    private String hashPassword(String password) throws Exception {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] messageDigest = md.digest((SALT + password).getBytes(encoding));
            return DatatypeConverter.printHexBinary(messageDigest).toLowerCase();
        } catch (Exception e) {
            throw new Exception("Unable to hash password", e);
        }
    }

    @AllArgsConstructor
    @Getter
    public static class AuthResult {
        private boolean success;
        private SignalError error;
    }
}
