package vn.azteam.tpf.security.apiKey;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.springframework.stereotype.Component;
import vn.azteam.tpf.service.TBCustomerService;
import org.springframework.util.StringUtils;
import vn.azteam.tpf.web.rest.errors.ForbiddenException;

import javax.annotation.PostConstruct;

import java.nio.charset.StandardCharsets;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.*;

@Component
public class ApiKeyProvider {
    private final Logger log = LoggerFactory.getLogger(ApiKeyProvider.class);

    private final TBCustomerService customerService;

    public ApiKeyProvider(TBCustomerService customerService) {
        this.customerService = customerService;
    }

    @PostConstruct
    public void init() {}

    public String createToken(Long customerId, String timestamp)
        throws NoSuchAlgorithmException, InvalidKeyException {

        List<String> keyArr = new ArrayList<>();
        String apiKeyByCustomerId = this.getApiKeyByCustomerId(customerId) != null && StringUtils.hasText(this.getApiKeyByCustomerId(customerId)) ? this.getApiKeyByCustomerId(customerId) : "";
        if(!StringUtils.hasText(apiKeyByCustomerId)){
            throw new ForbiddenException();
        }
        keyArr.add(apiKeyByCustomerId);
        keyArr.add(customerId.toString());
        keyArr.add(timestamp);
        return this.generateHMAC(String.join(":", keyArr), apiKeyByCustomerId != null ? apiKeyByCustomerId : "");
    }

    private String generateHMAC( String passwordToHash, String secret) throws NoSuchAlgorithmException, InvalidKeyException {
        byte[] byteKey = secret.getBytes(StandardCharsets.UTF_8);
        Mac sha512Hmac = Mac.getInstance("HmacSHA512");
        SecretKeySpec keySpec = new SecretKeySpec(byteKey, "HmacSHA512");
        sha512Hmac.init(keySpec);
        byte[] macData = sha512Hmac.doFinal(passwordToHash.getBytes(StandardCharsets.UTF_8));

        return toHexString(macData);
    }
    private static String toHexString(byte[] bytes) {
        Formatter formatter = new Formatter();
        for (byte b : bytes) {
            formatter.format("%02x", b);
        }
        return formatter.toString();
    }

    private String getApiKeyByCustomerId(Long customerId){
        String apiKey = this.customerService.findOne(customerId).get().getApiKey();
//        String apiKey = "8799a8af-8722-403a-81c2-dbbcadda4beb";
        if(StringUtils.hasText(apiKey)){
            return apiKey;
        }
        return null;
    }

    public boolean validateToken(Long customerId, String timestamp, String apiKeyToken)
        throws NoSuchAlgorithmException, InvalidKeyException {

        String token = this.createToken(customerId, timestamp);
        if(token.equals(apiKeyToken)){
            return true;
        }
        return false;
    }
}
