package de.oaa.xxx.config;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.security.Key;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.Base64;
import java.util.Date;
import java.util.UUID;

@Service
public class JwtService {

    private static final Logger LOGGER = LoggerFactory.getLogger(JwtService.class);

    @Value("${jwt.keystore.password}")
    private String keyPass;

    @Value("${jwt.keystore.alias}")
    private String alias;

    private KeyStore getKeystore() throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
        KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
        keystore.load(getClass().getClassLoader().getResourceAsStream("xxx.jks"), keyPass.toCharArray());
        return keystore;
    }

    public String createToken(String email, UUID userId, String clientIp) {
        try {
            KeyStore keystore = getKeystore();
            Key key = keystore.getKey(alias, keyPass.toCharArray());
            String token = Jwts.builder()
                    .issuer("OAA Games")
                    .issuedAt(new Date())
                    .claim("email", email)
                    .claim("client", clientIp)
                    .claim("userId", userId.toString())
                    .signWith(key)
                    .compact();
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("Erstellter token: {}", token);
            }
            return token;
        } catch (Exception e) {
            LOGGER.error("Fehler beim Erstellen des Tokens", e);
            throw new RuntimeException("Token-Erstellung fehlgeschlagen", e);
        }
    }

    public Claims validateToken(String token, String clientIp) {
        try {
            KeyStore keystore = getKeystore();
            Key key = keystore.getKey(alias, keyPass.toCharArray());
            Jws<Claims> claimsJws = Jwts.parser().verifyWith((java.security.PublicKey) keystore.getCertificate(alias).getPublicKey()).build().parseSignedClaims(token);
            Claims claims = claimsJws.getPayload();
            String tokenClient = claims.get("client", String.class);
            if (!clientIp.equals(tokenClient)) {
                LOGGER.warn("IP-Adresse stimmt nicht überein: Token={}, Request={}", tokenClient, clientIp);
                return null;
            }
            return claims;
        } catch (Exception e) {
            LOGGER.debug("Token-Validierung fehlgeschlagen: {}", e.getMessage());
            return null;
        }
    }

    public String getPublicKeyBase64() {
        try {
            KeyStore keystore = getKeystore();
            PublicKey publicKey = keystore.getCertificate(alias).getPublicKey();
            return Base64.getEncoder().encodeToString(publicKey.getEncoded());
        } catch (Exception e) {
            LOGGER.error("Fehler beim Laden des Public Keys", e);
            throw new RuntimeException("Public-Key-Laden fehlgeschlagen", e);
        }
    }
}
