import { AppServices } from './app-services';
import { NoopAnalyticsService } from './analytics/noop-analytics-service';
import { UmamiAnalyticsService } from './analytics/umami-analytics-service';
import { MemoryCacheService } from './cache/memory-cache-service';
import { GlitchtipErrorReportingService } from './errors/glitchtip-error-reporting-service';
import { NoopErrorReportingService } from './errors/noop-error-reporting-service';
import { NoopLoggerService } from './logging/noop-logger-service';
import { PinoLoggerService } from './logging/pino-logger-service';
import { NoopNotificationService } from './notifications/gotify-notification-service';
import { config, getMaskedConfig } from '../config';

declare global {
  var __appServices: AppServices | undefined;
}

let singleton: AppServices | undefined;

/**
 * Get the application services singleton.
 */
export function getAppServices(): AppServices {
  // Return cached instance if available
  if (typeof window === 'undefined' && globalThis.__appServices) return globalThis.__appServices;
  if (singleton) return singleton;

  // Create logger first to log initialization
  const logger =
    typeof window === 'undefined' ? new PinoLoggerService('server') : new NoopLoggerService();

  // Log initialization
  if (typeof window === 'undefined') {
    // Server-side
    logger.info('Initializing server application services', {
      environment: getMaskedConfig(),
      timestamp: new Date().toISOString(),
    });
  } else {
    // Client-side
    logger.info('Initializing client application services', {
      environment: getMaskedConfig(),
      timestamp: new Date().toISOString(),
    });
  }

  // Determine which services to enable based on environment variables
  const umamiEnabled = config.analytics.umami.enabled;
  const sentryEnabled = config.errors.glitchtip.enabled;

  logger.info('Service configuration', {
    umamiEnabled,
    sentryEnabled,
    isServer: typeof window === 'undefined',
  });

  // Create analytics service (Umami or no-op)
  const analytics = umamiEnabled
    ? new UmamiAnalyticsService({ enabled: true }, logger)
    : new NoopAnalyticsService();

  if (umamiEnabled) {
    logger.info('Umami analytics service initialized');
  } else {
    logger.info('Noop analytics service initialized (analytics disabled)');
  }

  // Create notification service
  const notifications = new NoopNotificationService();
  logger.info('Notification service initialized (noop)');

  // Create error reporting service (GlitchTip/Sentry or no-op)
  const errors = sentryEnabled
    ? new GlitchtipErrorReportingService(
        {
          enabled: true,
          dsn: config.errors.glitchtip.dsn,
          tracesSampleRate: 0.1, // Default to 10% sampling
        },
        logger,
        notifications,
      )
    : new NoopErrorReportingService();

  if (sentryEnabled) {
    logger.info(
      `GlitchTip error reporting service initialized (${typeof window === 'undefined' ? 'server' : 'client'})`,
    );
  } else {
    logger.info('Noop error reporting service initialized (error reporting disabled)');
  }

  const cache = new MemoryCacheService();
  logger.info('Memory cache service initialized');

  logger.info('Pino logger service initialized', {
    name: typeof window === 'undefined' ? 'server' : 'client',
    level: config.logging.level,
  });

  // Create and cache the singleton
  if (typeof window === 'undefined') {
    globalThis.__appServices = new AppServices(analytics, errors, cache, logger, notifications);
    return globalThis.__appServices;
  }

  singleton = new AppServices(analytics, errors, cache, logger, notifications);

  logger.info('All application services initialized successfully');

  return singleton;
}
