package dev.lions.unionflow.client.security;

import dev.lions.unionflow.client.view.UserSession;
import io.quarkus.oidc.AccessTokenCredential;
import io.quarkus.oidc.IdToken;
import io.quarkus.security.identity.SecurityIdentity;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.ws.rs.core.MultivaluedHashMap;
import jakarta.ws.rs.core.MultivaluedMap;
import org.eclipse.microprofile.jwt.JsonWebToken;
import org.eclipse.microprofile.rest.client.ext.ClientHeadersFactory;

import java.util.UUID;
import java.util.logging.Logger;

@ApplicationScoped
public class AuthHeaderFactory implements ClientHeadersFactory {

    private static final Logger LOGGER = Logger.getLogger(AuthHeaderFactory.class.getName());

    public static final String HEADER_ACTIVE_ORG = "X-Active-Organisation-Id";

    @Inject
    SecurityIdentity securityIdentity;

    @Inject
    @IdToken
    JsonWebToken idToken;

    @Inject
    UserSession userSession;

    @Override
    public MultivaluedMap<String, String> update(
            MultivaluedMap<String, String> incomingHeaders,
            MultivaluedMap<String, String> clientOutgoingHeaders) {

        MultivaluedMap<String, String> result = new MultivaluedHashMap<>();

        try {
            AccessTokenCredential credential = securityIdentity.getCredential(AccessTokenCredential.class);
            if (credential != null && credential.getToken() != null && !credential.getToken().isEmpty()) {
                result.add("Authorization", "Bearer " + credential.getToken());
                LOGGER.fine("Access token Bearer ajouté via AccessTokenCredential");
            } else {
                String rawIdToken = idToken.getRawToken();
                if (rawIdToken != null && !rawIdToken.isEmpty()) {
                    result.add("Authorization", "Bearer " + rawIdToken);
                    LOGGER.warning("Fallback sur l'ID token — l'access token n'était pas disponible");
                } else {
                    LOGGER.warning("Aucun token disponible pour la requête REST Client");
                }
            }
        } catch (Exception e) {
            LOGGER.severe("Erreur lors de l'ajout du token Bearer: " + e.getMessage());
        }

        // Injecter l'organisation active si définie en session.
        // Guard : ne pas résoudre le proxy CDI si UserSession est encore en cours d'initialisation
        // sur ce thread (évite StackOverflowError par réentrance CDI dans @PostConstruct).
        try {
            if (userSession != null && !Boolean.TRUE.equals(UserSession.INITIALIZING_ON_THREAD.get())) {
                UUID activeOrgId = userSession.getActiveOrganisationId();
                if (activeOrgId != null) {
                    result.add(HEADER_ACTIVE_ORG, activeOrgId.toString());
                    LOGGER.fine("Header " + HEADER_ACTIVE_ORG + " ajouté : " + activeOrgId);
                }
            }
        } catch (Exception e) {
            LOGGER.fine("Impossible d'ajouter le header org (contexte non disponible) : " + e.getMessage());
        }

        return result;
    }
}
