package org.acme.security.openid.connect.web.authentication;

import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;

import org.eclipse.microprofile.jwt.Claims;
import org.eclipse.microprofile.jwt.JsonWebToken;

import io.quarkus.oidc.IdToken;
import io.quarkus.oidc.RefreshToken;

import java.util.Base64;
import java.nio.charset.StandardCharsets;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import org.eclipse.microprofile.jwt.JsonWebToken;
import com.fasterxml.jackson.core.JsonProcessingException;
import java.util.List;

@Path("/tokens")
public class TokenResource {

    /**
     * Injection point for the ID Token issued by the OpenID Connect Provider
     */
    @Inject
    @IdToken
    JsonWebToken idToken;

    /**
     * Injection point for the Access Token issued by the OpenID Connect Provider
     */
    @Inject
    JsonWebToken accessToken;

    /**
     * Injection point for the Refresh Token issued by the OpenID Connect Provider
     */
    @Inject
    RefreshToken refreshToken;


    private ObjectMapper objectMapper;

    public TokenResource() {
        this.objectMapper = new ObjectMapper();
        this.objectMapper.enable(SerializationFeature.INDENT_OUTPUT);  // fÃ¼r schÃ¶n formatiertes JSON
    }

   // Methode zum Dekodieren und Formatieren eines Tokens
    public String decodeAndFormatToken(JsonWebToken token) {
        if (token != null) {
            String[] tokenParts = token.getRawToken().split("\\.");
            if (tokenParts.length == 3) {
                try {
                    String header = new String(Base64.getUrlDecoder().decode(tokenParts[0]), StandardCharsets.UTF_8);
                    String payload = new String(Base64.getUrlDecoder().decode(tokenParts[1]), StandardCharsets.UTF_8);

                    // JSON schÃ¶n formatieren
                    String formattedHeader = objectMapper.readTree(header).toPrettyString();
                    String formattedPayload = objectMapper.readTree(payload).toPrettyString();

                    // Formatierte Ausgabe zurÃ¼ckgeben
                    return "<h3>Decoded Header:</h3><pre>" + formattedHeader + "</pre>"
                         + "<h3>Decoded Payload:</h3><pre>" + formattedPayload + "</pre>";
                } catch (JsonProcessingException e) {
                    return "Error processing JSON: " + e.getMessage();
                } catch (IllegalArgumentException e) {
                    return "Error decoding Base64: " + e.getMessage();
                }
            } else {
                return "Invalid JWT token format.";
            }
        } else {
            return "Token is null.";
        }
    }

    // Methode zur ÃœberprÃ¼fung der "user-role01"-Rolle im ID-Token
    public boolean hasUserRole(JsonWebToken idToken, String claim, String roleName) {
        if (idToken != null) {
            String[] tokenParts = idToken.getRawToken().split("\\.");
            if (tokenParts.length == 3) {
                try {
                    String payload = new String(Base64.getUrlDecoder().decode(tokenParts[1]), StandardCharsets.UTF_8);
                    // JSON in eine Map umwandeln
                    var jsonNode = objectMapper.readTree(payload);
                    if (jsonNode.has(claim)) {
                        List<String> roles = objectMapper.convertValue(jsonNode.get(claim), List.class);
                        return roles.contains(roleName);
                    }
                } catch (JsonProcessingException e) {
                    System.out.println("Error processing JSON: " + e.getMessage());
                }
            }
        }
        return false;
    }

@GET
@Produces("text/html")
public String getTokens() {

    StringBuilder response = new StringBuilder().append("<html>")
        .append("<head>")
        .append("<title>Test-App</title>")
        .append("<style>")
        .append("body { font-family: Arial, sans-serif; padding: 20px; position: relative; }")
        .append("h1 { color: #2c3e50; }")
        .append(".token-output { font-size: 10px; color: #555; background-color: #f4f4f4; padding: 10px; border-radius: 5px; }")
        .append(".logo-top-right { position: absolute; top: 20px; right: 20px; max-width: 150px; height: auto; }")
        .append("</style>")
        .append("</head>")
        .append("<body>");

    // Logo oben rechts einblenden
    response.append("<img src=\"/logo.png\" alt=\"Logo\" class=\"logo-top-right\" />");

    // Begrüßung und Beschreibung
    response.append("<h1>Willkommen zur Testapp!</h1>");
    response.append("<p>Dies ist eine Test-Anwendung, die das Authentifizierungs-Token (ID-Token) des angemeldeten Nutzers ausgibt.</p>");

/*
    // Rollen prüfen
    if (hasUserRole(idToken, "realm-roles", "user-role01")) {
        response.append("<p style='color:green;font-size:20px;'>user-access: true</p>");
    } else {
        response.append("<p style='color:red;font-size:20px;'>user-access: false</p>");
    }

    if (hasUserRole(idToken, "realm-roles", "admin-role01")) {
        response.append("<p style='color:green;font-size:20px;'>admin-access: true</p>");
    } else {
        response.append("<p style='color:red;font-size:20px;'>admin-access: false</p>");
    }
*/

    // ID Token anzeigen (klein formatiert)
    response.append("<h2>ID Token:</h2>");
    response.append("<div class='token-output'>").append(decodeAndFormatToken(idToken)).append("</div>");

    // Access Token anzeigen (ebenfalls klein)
    response.append("<h2>Access Token:</h2>");
    response.append("<div class='token-output'>").append(decodeAndFormatToken(accessToken)).append("</div>");

    response.append("</body>").append("</html>");

    return response.toString();
}
}
