package dev.lions.unionflow.server.client;

import io.quarkus.oidc.runtime.OidcJwtCallerPrincipal;
import io.quarkus.security.identity.SecurityIdentity;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.inject.Instance;
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;

/**
 * Factory pour propager automatiquement le token JWT OIDC
 * vers les appels REST Client (compatible Quarkus REST).
 *
 * Stratégie : copier le header Authorization de la requête entrante
 * ou récupérer le token depuis SecurityIdentity si disponible.
 */
@ApplicationScoped
public class OidcTokenPropagationHeadersFactory implements ClientHeadersFactory {

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

    @Inject
    Instance<SecurityIdentity> securityIdentity;

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

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

        // STRATÉGIE 1 : Copier directement le header Authorization de la requête entrante
        if (incomingHeaders != null && incomingHeaders.containsKey("Authorization")) {
            String authHeader = incomingHeaders.getFirst("Authorization");
            if (authHeader != null && !authHeader.isBlank()) {
                result.add("Authorization", authHeader);
                LOG.infof("✅ Token JWT propagé depuis incomingHeaders (longueur: %d)", authHeader.length());
                return result;
            }
        }

        // STRATÉGIE 2 : Récupérer depuis SecurityIdentity
        // En contexte CDI, securityIdentity.isResolvable() est toujours true.
        SecurityIdentity identity = securityIdentity.get();

        if (identity != null && !identity.isAnonymous()) {
            if (identity.getPrincipal() instanceof OidcJwtCallerPrincipal) {
                OidcJwtCallerPrincipal principal = (OidcJwtCallerPrincipal) identity.getPrincipal();
                String token = principal.getRawToken();

                if (token != null && !token.isBlank()) {
                    result.add("Authorization", "Bearer " + token);
                    LOG.infof("✅ Token JWT propagé depuis SecurityIdentity (longueur: %d)", token.length());
                    return result;
                } else {
                    LOG.warnf("⚠️ Token JWT vide dans SecurityIdentity");
                }
            } else {
                LOG.warnf("⚠️ Principal n'est pas un OidcJwtCallerPrincipal (type: %s)",
                    identity.getPrincipal() != null ? identity.getPrincipal().getClass().getName() : "null");
            }
        } else {
            LOG.warnf("⚠️ SecurityIdentity null ou utilisateur anonyme");
        }

        LOG.errorf("❌ Impossible de propager le token JWT - aucune stratégie n'a fonctionné");
        return result;
    }
}
