/**
 * Next.js Instrumentation Hook
 *
 * This file runs once when the Next.js server starts, before any requests are processed.
 * Perfect for environment validation, database connectivity checks, and other startup tasks.
 *
 * Documentation: https://nextjs.org/docs/app/building-your-application/optimizing/instrumentation
 *
 * @module instrumentation
 */

import { validateEnvironmentOrThrow, isProduction } from "./lib/env-validation";
import { logger } from "./lib/logger";
import {
  measureStartupMetrics,
  PERFORMANCE_BUDGETS,
} from "./lib/startup-warmup";
import { sendTelemetryEvent } from "./lib/services/telemetry.service";

/**
 * Register function - runs once on server startup
 * This is called before the application starts handling requests
 */
export async function register() {
  // Only run on the server
  if (typeof window !== "undefined") {
    return;
  }

  const startTime = Date.now();

  try {
    logger.info("🚀 Starting Mawidi application initialization...");

    // =====================================================================
    // PHASE 0: SENTRY INITIALIZATION (via dedicated config files)
    // =====================================================================
    // Sentry configs are in sentry.server.config.ts and sentry.edge.config.ts
    // They self-guard on DSN presence and NODE_ENV === 'production'
    if (
      process.env.SENTRY_DSN ||
      process.env.NEXT_PUBLIC_SENTRY_DSN
    ) {
      try {
        if (process.env.NEXT_RUNTIME === "nodejs") {
          await import("./sentry.server.config");
          logger.info("Sentry server config loaded");
        } else if (process.env.NEXT_RUNTIME === "edge") {
          await import("./sentry.edge.config");
          logger.info("Sentry edge config loaded");
        }
      } catch (sentryError) {
        logger.warn("Failed to initialize Sentry:", {
          error: String(sentryError),
        });
      }
    }

    // =====================================================================
    // PHASE 1: ENVIRONMENT VALIDATION (CRITICAL)
    // =====================================================================
    // Validate all required environment variables before starting
    // This will throw an error if critical variables are missing or invalid
    validateEnvironmentOrThrow();

    // =====================================================================
    // PHASE 2: WARM PATHS (Pre-warm connections to reduce cold-start latency)
    // =====================================================================
    // Warm database and cache connections before handling requests
    // This reduces first-request latency significantly
    try {
      // Dynamic import to allow the file to be tree-shaken if not used
      const { initializeWarmPaths } = await import("./lib/startup-warmup");
      await initializeWarmPaths();
      logger.info("✅ Warm paths initialized");
    } catch (warmupError) {
      // Log but don't fail - warmup issues shouldn't prevent startup
      logger.warn("⚠️ Warm path initialization had issues:", {
        error: String(warmupError),
      });
    }

    try {
      const startupMetrics = await measureStartupMetrics();
      logger.info("📊 Startup latency baselines recorded", {
        ttfbMs: startupMetrics.ttfbBaseline,
        redisMs: startupMetrics.redisConnectionMs,
        totalMs: startupMetrics.totalStartupMs,
        withinBudget: startupMetrics.withinBudget,
        budget: PERFORMANCE_BUDGETS,
      });

      void sendTelemetryEvent({
        type: "performance",
        name: "startup_warm_paths",
        value: startupMetrics.totalStartupMs,
        tags: {
          withinBudget: String(startupMetrics.withinBudget),
        },
        extra: {
          ...startupMetrics,
          budgets: PERFORMANCE_BUDGETS,
        },
        timestamp: new Date().toISOString(),
      });
    } catch (metricsError) {
      logger.warn("⚠️ Failed to record startup metrics", {
        error:
          metricsError instanceof Error
            ? metricsError.message
            : String(metricsError),
      });
    }

    const duration = Date.now() - startTime;

    logger.info("✅ Application initialization complete", {
      duration: `${duration}ms`,
      environment: process.env.NODE_ENV,
      isProduction: isProduction(),
    });
  } catch (error) {
    const duration = Date.now() - startTime;

    logger.error("❌ Application initialization failed", {
      duration: `${duration}ms`,
      error: error instanceof Error ? error.message : "Unknown error",
    });

    // In production, we want to fail fast and prevent the app from starting
    // In development, we log the error but allow the app to start for debugging
    if (isProduction()) {
      logger.error(
        "FATAL: Cannot start application with invalid configuration",
      );
      throw error;
    } else {
      logger.warn(
        "WARNING: Application started with configuration warnings (development mode)",
      );
    }
  }
}
