package com.cameleer.server.app.security;

import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.jwk.source.JWKSource;
import com.nimbusds.jose.jwk.source.JWKSourceBuilder;
import com.nimbusds.jose.jwk.source.RemoteJWKSet;
import com.nimbusds.jose.proc.SecurityContext;
import com.nimbusds.jose.util.DefaultResourceRetriever;
import com.nimbusds.openid.connect.sdk.op.OIDCProviderMetadata;
import net.minidev.json.JSONObject;
import net.minidev.json.parser.JSONParser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.InputStream;
import java.net.URI;
import java.net.URL;
import java.util.Set;

/**
 * Shared helpers for OIDC provider discovery and JWK source construction.
 * Used by both {@link SecurityConfig} (resource server decoder) and
 * {@link OidcTokenExchanger} (login token exchange).
 */
final class OidcProviderHelper {

    private static final Logger log = LoggerFactory.getLogger(OidcProviderHelper.class);

    static final Set<JWSAlgorithm> SUPPORTED_ALGORITHMS =
            Set.of(JWSAlgorithm.ES384, JWSAlgorithm.ES256, JWSAlgorithm.RS256);

    private OidcProviderHelper() {}

    /**
     * Fetches OIDC provider metadata from the well-known discovery endpoint.
     */
    static OIDCProviderMetadata fetchMetadata(String issuerUri, boolean tlsSkipVerify) throws Exception {
        String discoveryUrl = issuerUri.endsWith("/")
                ? issuerUri + ".well-known/openid-configuration"
                : issuerUri + "/.well-known/openid-configuration";
        URL url = new URI(discoveryUrl).toURL();
        try (InputStream in = InsecureTlsHelper.openStream(url, tlsSkipVerify)) {
            JSONObject json = (JSONObject) new JSONParser(JSONParser.DEFAULT_PERMISSIVE_MODE).parse(in);
            return OIDCProviderMetadata.parse(json);
        }
    }

    /**
     * Builds a JWK source for the given JWKS URI, optionally skipping TLS verification.
     */
    static JWKSource<SecurityContext> buildJwkSource(URL jwksUri, boolean tlsSkipVerify) throws Exception {
        if (tlsSkipVerify) {
            var retriever = new DefaultResourceRetriever(5000, 5000, 0, true,
                    InsecureTlsHelper.socketFactory());
            return new RemoteJWKSet<>(jwksUri, retriever);
        }
        return JWKSourceBuilder.create(jwksUri).build();
    }
}
