const PRODUCTION_API_ORIGIN = 'https://api.press.zone';
const SECRET_NAME_PATTERN = /(secret|password|private|token|database_url|stripe_key)/i;

export interface PublicRuntimeConfig {
  readonly apiBaseUrl: string;
}

export class PublicConfigError extends Error {
  override readonly name = 'PublicConfigError';
}

function normalizeApiBaseUrl(rawValue: string): string {
  let url: URL;
  try {
    url = new URL(rawValue);
  } catch {
    throw new PublicConfigError('PUBLIC_API_BASE_URL must be an absolute URL');
  }

  if (url.username || url.password) {
    throw new PublicConfigError('PUBLIC_API_BASE_URL must not contain credentials');
  }
  if (url.search || url.hash) {
    throw new PublicConfigError('PUBLIC_API_BASE_URL must not contain a query or fragment');
  }
  if (url.protocol !== 'https:' && !['localhost', '127.0.0.1', '::1'].includes(url.hostname)) {
    throw new PublicConfigError('PUBLIC_API_BASE_URL must use HTTPS outside local development');
  }

  url.pathname = url.pathname.replace(/\/+$/, '');
  return url.toString().replace(/\/$/, '');
}

export function readPublicRuntimeConfig(
  env: Readonly<Record<string, string | undefined>> = import.meta.env,
): PublicRuntimeConfig {
  for (const [name, value] of Object.entries(env)) {
    if (name.startsWith('PUBLIC_') && SECRET_NAME_PATTERN.test(name) && value) {
      throw new PublicConfigError(`Secret-like variable ${name} must not be exposed to the frontend`);
    }
  }

  return {
    apiBaseUrl: normalizeApiBaseUrl(env.PUBLIC_API_BASE_URL ?? PRODUCTION_API_ORIGIN),
  };
}
