package dev.lions.unionflow.server.client;

import io.quarkus.oidc.client.NamedOidcClient;
import io.quarkus.oidc.client.OidcClient;
import io.quarkus.oidc.client.Tokens;
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.rest.client.ext.ClientHeadersFactory;
import org.jboss.logging.Logger;

/**
 * Injecte le token du service account "admin-service" (client credentials grant)
 * dans tous les appels faits via {@link AdminUserServiceClient} et {@link AdminRoleServiceClient}.
 *
 * <p>Utilise directement l'API {@link OidcClient} pour récupérer/rafraîchir le token.
 * Cette approche explicite évite toute ambiguïté avec {@code @OidcClientFilter} quand
 * plusieurs interfaces REST partagent le même configKey.
 */
@ApplicationScoped
public class AdminServiceTokenHeadersFactory implements ClientHeadersFactory {

    private static final Logger LOG = Logger.getLogger(AdminServiceTokenHeadersFactory.class);

    @Inject
    @NamedOidcClient("admin-service")
    OidcClient adminOidcClient;

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

        MultivaluedMap<String, String> result = new MultivaluedHashMap<>();
        try {
            Tokens tokens = adminOidcClient.getTokens().await().indefinitely();
            result.add("Authorization", "Bearer " + tokens.getAccessToken());
            LOG.debugf("Token service account injecté pour admin-service (longueur: %d)",
                    tokens.getAccessToken().length());
        } catch (Exception e) {
            LOG.errorf("Impossible d'obtenir le token service account 'admin-service': %s", e.getMessage());
            throw new jakarta.ws.rs.ServiceUnavailableException(
                    "Service d'authentification interne indisponible: " + e.getMessage());
        }
        return result;
    }
}
