const PACKAGE_NAME = "com.makecdev.coderemotemanager";
const PRODUCT_ID = "pro_multi_account";
const SERVICE_ACCOUNT = /^[a-z0-9][a-z0-9._-]{0,62}@[a-z0-9-]+\.iam\.gserviceaccount\.com$/;
const KEY_VERSION = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;

export function loadVerifierConfig(env = process.env) {
  try {
    if (env.GOOGLE_APPLICATION_CREDENTIALS !== undefined) throw new Error();
    const port = integer(env.PORT, 8080, 1, 65_535);
    if (env.GOOGLE_PLAY_PACKAGE_NAME !== PACKAGE_NAME) throw new Error();
    if (env.GOOGLE_PLAY_PRODUCT_ID !== PRODUCT_ID) throw new Error();
    const publicBaseUrl = httpsUrl(env.PUBLIC_BASE_URL, { originOnly: true });
    if (!KEY_VERSION.test(env.ENTITLEMENT_SIGNING_KEY_VERSION ?? "")) throw new Error();
    if (!absolutePath(env.ENTITLEMENT_SIGNING_KEY_FILE)) throw new Error();
    return {
      port,
      packageName: PACKAGE_NAME,
      productId: PRODUCT_ID,
      publicBaseUrl,
      signingKeyVersion: env.ENTITLEMENT_SIGNING_KEY_VERSION,
      signingKeyFile: env.ENTITLEMENT_SIGNING_KEY_FILE,
      requestTimeoutMs: integer(env.REQUEST_TIMEOUT_MS, 10_000, 100, 30_000),
      pubsubOidc: oidcConfig(
        env.PUBSUB_OIDC_AUDIENCE,
        env.PUBSUB_OIDC_SERVICE_ACCOUNTS,
        `${publicBaseUrl}/internal/google-play/rtdn`
      ),
      schedulerOidc: oidcConfig(
        env.SCHEDULER_OIDC_AUDIENCE,
        env.SCHEDULER_OIDC_SERVICE_ACCOUNTS,
        `${publicBaseUrl}/internal/google-play/voided-purchases/sync`
      ),
    };
  } catch {
    const error = new Error("Verifier configuration is invalid.");
    error.code = "invalid_verifier_config";
    throw error;
  }
}

function absolutePath(value) {
  return typeof value === "string" && value.length > 1 && (isAbsolute(value) || posix.isAbsolute(value));
}

function oidcConfig(audience, serviceAccounts, expectedAudience) {
  const normalizedAudience = httpsUrl(audience);
  if (normalizedAudience !== expectedAudience) throw new Error();
  return {
    audience: normalizedAudience,
    serviceAccounts: commaList(serviceAccounts),
  };
}

function commaList(value) {
  if (typeof value !== "string") throw new Error();
  const items = value.split(",").map((item) => item.trim());
  if (items.length === 0 || items.length > 16 || items.some((item) => !SERVICE_ACCOUNT.test(item))) throw new Error();
  if (new Set(items).size !== items.length) throw new Error();
  return items;
}

function httpsUrl(value, { originOnly = false } = {}) {
  if (typeof value !== "string") throw new Error();
  const parsed = new URL(value);
  if (parsed.protocol !== "https:" || parsed.username || parsed.password || parsed.search || parsed.hash) throw new Error();
  if (originOnly && (parsed.pathname !== "/" || parsed.origin !== value)) throw new Error();
  return originOnly ? parsed.origin : parsed.href;
}

function integer(value, fallback, minimum, maximum) {
  const candidate = value === undefined ? fallback : Number(value);
  if (!Number.isSafeInteger(candidate) || candidate < minimum || candidate > maximum) throw new Error();
  return candidate;
}
import { isAbsolute, posix } from "node:path";
