package org.greenstone.gsdl3.auth.oidc;

import java.util.*;
import java.util.Properties;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;

import org.greenstone.util.GlobalProperties;


public class OidcConfig {
  public final String issuer;
  public final List<String> scopes;

  public final String keystorePath;
  public final String keystoreType;
  public final String keystorePassword;
  public final String keyAlias;
  public final String keyPassword;
  public final String kid;

  public OidcConfig(String issuer,
                    String scopes_unparsed,
                    String keystorePath, String keystoreType, String keystorePassword,
                    String keyAlias, String keyPassword, String kid) {

    List<String> scopes_parsed = parseScopes(scopes_unparsed);

    this.issuer = Objects.requireNonNull(issuer, "issuer");
    this.scopes = (scopes_parsed == null || scopes_parsed.isEmpty())
        ? Arrays.asList("openid","email","profile")
        : Collections.unmodifiableList(new ArrayList<>(scopes_parsed));
    this.keystorePath = keystorePath;
    this.keystoreType = kenullToDefault(keystoreType, "PKCS12");
    this.keystorePassword = keystorePassword;
    this.keyAlias = keyAlias;
    this.keyPassword = keyPassword;
    this.kid = kid == null ? "oidc-key-1" : kid;
  }

  private static String kenullToDefault(String v, String d) { return v == null ? d : v; }

  /* A more generalk version of this would mave a 'properties' argument that it uses */
  /* Given how Greenstone3 is structured, we instead make use of GlobalProperties */
  public static OidcConfig from() {
    return new OidcConfig(
        req("auth.oidc.issuer"),
	opt("auth.oidc.scopes"),
        opt("auth.oidc.keystore.path"),
        opt("auth.oidc.keystore.type"),
        opt("auth.oidc.keystore.password"),
        opt("auth.oidc.key.alias"),
        opt("auth.oidc.key.password"),
        opt("auth.oidc.kid")
    );
  }

  private static List<String> parseScopes(String json) {
    if (json == null || json.trim().isEmpty()) return null;
    try {
      ObjectMapper om = new ObjectMapper();
      List<String> list = om.readValue(json, new TypeReference<List<String>>(){});
      LinkedHashSet<String> norm = new LinkedHashSet<String>();
      for (String s : list) {
        if (s != null) {
          String t = s.trim();
          if (!t.isEmpty()) norm.add(t);
        }
      }
      return new ArrayList<String>(norm);
    } catch (Exception e) {
      throw new IllegalArgumentException("Invalid JSON for auth.oidc.scopes: " + e.getMessage(), e);
    }
  }

  private static String req(String k) {
    String v = GlobalProperties.getProperty(k);
    if (v == null || v.trim().isEmpty()) {
      throw new IllegalArgumentException("Missing required property: " + k);
    }
    return v.trim();
  }

  private static String opt(String k) {
    String v = GlobalProperties.getProperty(k);
    return v == null ? null : v.trim();
  }

  public boolean useKeystore() {
    return keystorePath != null && !keystorePath.isEmpty();
  }
}
