/**
 * Centralized configuration management for the application.
 * This file provides a type-safe way to access environment variables.
 */
import { envSchema, getRawEnv } from "./env";

let memoizedConfig: ReturnType<typeof createConfig> | undefined;

/**
 * Creates and validates the configuration object.
 * Throws if validation fails.
 */
function createConfig() {
  const env = envSchema.parse(getRawEnv());

  const target = env.NEXT_PUBLIC_TARGET || env.TARGET;

  return {
    env: env.NODE_ENV,
    target,
    isProduction: target === "production" || !target,
    isStaging: target === "staging",
    isTesting: target === "testing",
    isDevelopment: target === "development",

    baseUrl: env.NEXT_PUBLIC_BASE_URL,

    analytics: {
      umami: {
        websiteId: env.NEXT_PUBLIC_UMAMI_WEBSITE_ID || env.UMAMI_WEBSITE_ID,
        apiEndpoint: env.UMAMI_API_ENDPOINT,
        enabled: Boolean(
          env.NEXT_PUBLIC_UMAMI_WEBSITE_ID || env.UMAMI_WEBSITE_ID,
        ),
      },
    },

    errors: {
      glitchtip: {
        // Use NEXT_PUBLIC_SENTRY_DSN if available (required for browser-side SDK)
        dsn: env.NEXT_PUBLIC_SENTRY_DSN || env.SENTRY_DSN,
        // The proxied origin used in the frontend
        proxyPath: "/errors",
        enabled: Boolean(env.SENTRY_DSN),
      },
    },

    cache: {
      enabled: false,
    },

    logging: {
      level: env.LOG_LEVEL,
    },

    mail: {
      host: env.MAIL_HOST,
      port: env.MAIL_PORT,
      user: env.MAIL_USERNAME,
      pass: env.MAIL_PASSWORD,
      from: env.MAIL_FROM,
      recipients: env.MAIL_RECIPIENTS,
    },
    notifications: {
      gotify: {
        url: env.GOTIFY_URL,
        token: env.GOTIFY_TOKEN,
        enabled: Boolean(env.GOTIFY_URL && env.GOTIFY_TOKEN),
      },
    },
  } as const;
}

/**
 * Returns the validated configuration.
 * Memoizes the result after the first call.
 */
export function getConfig() {
  if (!memoizedConfig) {
    memoizedConfig = createConfig();
  }
  return memoizedConfig;
}

/**
 * Exported config object for convenience.
 * Uses getters to ensure it's only initialized when accessed.
 */
export const config = {
  get env() {
    return getConfig().env;
  },
  get target() {
    return getConfig().target;
  },
  get isProduction() {
    return getConfig().isProduction;
  },
  get isStaging() {
    return getConfig().isStaging;
  },
  get isTesting() {
    return getConfig().isTesting;
  },
  get isDevelopment() {
    return getConfig().isDevelopment;
  },
  get baseUrl() {
    return getConfig().baseUrl;
  },
  get analytics() {
    return getConfig().analytics;
  },
  get errors() {
    return getConfig().errors;
  },
  get cache() {
    return getConfig().cache;
  },
  get logging() {
    return getConfig().logging;
  },
  get mail() {
    return getConfig().mail;
  },
  get notifications() {
    return getConfig().notifications;
  },
};

/**
 * Helper to get a masked version of the config for logging.
 */
export function getMaskedConfig() {
  const c = getConfig();
  const mask = (val: string | undefined) =>
    val ? `***${val.slice(-4)}` : "not set";

  return {
    env: c.env,
    baseUrl: c.baseUrl,
    analytics: {
      umami: {
        websiteId: mask(c.analytics.umami.websiteId),
        apiEndpoint: c.analytics.umami.apiEndpoint,
        enabled: c.analytics.umami.enabled,
      },
    },
    errors: {
      glitchtip: {
        dsn: mask(c.errors.glitchtip.dsn),
        enabled: c.errors.glitchtip.enabled,
      },
    },
    cache: {
      enabled: c.cache.enabled,
    },
    logging: {
      level: c.logging.level,
    },
    mail: {
      host: c.mail.host,
      port: c.mail.port,
      user: mask(c.mail.user),
      from: c.mail.from,
      recipients: c.mail.recipients,
    },
    notifications: {
      gotify: {
        url: c.notifications.gotify.url,
        token: mask(c.notifications.gotify.token),
        enabled: c.notifications.gotify.enabled,
      },
    },
  };
}
