/**
 * Health Check Utilities
 * Monitors critical system components and services
 *
 * Migrated from Prisma/Redis/Supabase to Convex (T17)
 */

import { convexQuery, isConvexConfigured } from './convex-client';
import type { HealthStatus, HealthCheckResult, SystemHealth } from './types/health';

// Re-export types for backward compatibility
export type { HealthStatus, HealthCheckResult, SystemHealth };

/**
 * Sanitize error messages to prevent information disclosure
 */
function sanitizeErrorMessage(error: unknown, componentType: string): string {
  if (process.env.NODE_ENV === 'production') {
    return 'Service temporarily unavailable';
  }

  return `${componentType} check failed`;
}


/**
 * Check Convex connectivity and response time
 */
export async function checkConvex(): Promise<HealthCheckResult> {
  const startTime = Date.now();

  try {
    if (!isConvexConfigured()) {
      return {
        name: 'Convex',
        status: 'down',
        responseTime: 0,
        message: 'Convex not configured',
        lastChecked: new Date().toISOString(),
      };
    }

    // Simple query to test connectivity — getUserByEmail returns null for non-existent, confirming connectivity
    await convexQuery("auth/queries:getUserByEmail", { email: '__health_check__@mawidi.com' });

    const responseTime = Date.now() - startTime;

    return {
      name: 'Convex',
      status: responseTime < 1000 ? 'operational' : 'degraded',
      responseTime,
      message: responseTime < 1000 ? 'Connected' : 'Slow response',
      lastChecked: new Date().toISOString(),
    };
  } catch (error) {
    return {
      name: 'Convex',
      status: 'down',
      responseTime: Date.now() - startTime,
      message: sanitizeErrorMessage(error, 'Convex'),
      lastChecked: new Date().toISOString(),
    };
  }
}

/**
 * Check database connectivity (alias for checkConvex)
 * Kept for backward compatibility with health check routes
 */
export async function checkDatabase(): Promise<HealthCheckResult> {
  const result = await checkConvex();
  return { ...result, name: 'Database' };
}

/**
 * Check API endpoint availability
 */
export async function checkAPIEndpoint(
  endpoint: string,
  name: string
): Promise<HealthCheckResult> {
  const startTime = Date.now();
  const baseUrl = process.env.NEXT_PUBLIC_BASE_URL || 'http://localhost:9000';

  try {
    const response = await fetch(`${baseUrl}${endpoint}`, {
      method: 'GET',
      headers: { 'User-Agent': 'HealthCheck/1.0' },
      signal: AbortSignal.timeout(5000) // 5 second timeout
    });

    const responseTime = Date.now() - startTime;

    return {
      name,
      status: response.ok
        ? (responseTime < 1000 ? 'operational' : 'degraded')
        : 'down',
      responseTime,
      message: response.ok
        ? (responseTime < 1000 ? 'Available' : 'Slow response')
        : 'Service unavailable',
      lastChecked: new Date().toISOString()
    };
  } catch (error) {
    return {
      name,
      status: 'down',
      responseTime: Date.now() - startTime,
      message: sanitizeErrorMessage(error, 'API'),
      lastChecked: new Date().toISOString()
    };
  }
}

/**
 * Check critical page accessibility
 */
export async function checkPage(
  path: string,
  name: string
): Promise<HealthCheckResult> {
  const startTime = Date.now();
  const baseUrl = process.env.NEXT_PUBLIC_BASE_URL || 'http://localhost:9000';

  try {
    const response = await fetch(`${baseUrl}${path}`, {
      method: 'GET',
      headers: { 'User-Agent': 'HealthCheck/1.0' },
      signal: AbortSignal.timeout(5000)
    });

    const responseTime = Date.now() - startTime;

    return {
      name,
      status: response.ok
        ? (responseTime < 2000 ? 'operational' : 'degraded')
        : 'down',
      responseTime,
      message: response.ok
        ? (responseTime < 2000 ? 'Accessible' : 'Slow loading')
        : 'Page unavailable',
      lastChecked: new Date().toISOString()
    };
  } catch (error) {
    return {
      name,
      status: 'down',
      responseTime: Date.now() - startTime,
      message: sanitizeErrorMessage(error, 'Page'),
      lastChecked: new Date().toISOString()
    };
  }
}

/**
 * Run all health checks and return aggregated results
 *
 * IMPORTANT: Only checks actual infrastructure components.
 * Does NOT make HTTP requests to localhost (prevents self-referential calls and timeouts).
 */
export async function runAllHealthChecks(): Promise<SystemHealth> {
  const checks = await Promise.allSettled([
    // Core infrastructure only - Convex is the primary datastore
    checkConvex(),
  ]);

  const components: HealthCheckResult[] = checks.map((result, index) => {
    if (result.status === 'fulfilled') {
      return result.value;
    } else {
      return {
        name: `Check ${index + 1}`,
        status: 'down' as HealthStatus,
        responseTime: 0,
        message: 'Check failed',
        lastChecked: new Date().toISOString()
      };
    }
  });

  // Determine overall status
  const downCount = components.filter(c => c.status === 'down').length;
  const degradedCount = components.filter(c => c.status === 'degraded').length;

  let overall: HealthStatus;
  if (downCount > 0) {
    overall = 'down';
  } else if (degradedCount > 0) {
    overall = 'degraded';
  } else {
    overall = 'operational';
  }

  return {
    overall,
    components,
    timestamp: new Date().toISOString()
  };
}

/**
 * Get cached health check results (with 30-second cache)
 */
let cachedHealth: SystemHealth | null = null;
let cacheTime: number = 0;
const CACHE_DURATION = 30 * 1000; // 30 seconds

export async function getCachedHealthChecks(): Promise<SystemHealth> {
  const now = Date.now();

  if (cachedHealth && (now - cacheTime) < CACHE_DURATION) {
    return cachedHealth;
  }

  cachedHealth = await runAllHealthChecks();
  cacheTime = now;

  return cachedHealth;
}

// =====================================================
// Health Check Functions for CI/CD Implementation
// =====================================================

interface HealthCheckResponse {
  healthy: boolean;
  responseTime: number;
  timestamp: string;
  details?: Record<string, unknown>;
  error?: string;
}

/**
 * Check database health (simplified for endpoint use)
 * Now checks Convex connectivity
 */
export async function checkDatabaseHealth(): Promise<HealthCheckResponse> {
  const startTime = Date.now();

  try {
    if (!isConvexConfigured()) {
      return {
        healthy: false,
        responseTime: 0,
        timestamp: new Date().toISOString(),
        error: 'Convex not configured',
      };
    }

    // Simple connectivity test via Convex query
    await convexQuery("auth/queries:getUserByEmail", { email: '__health_check__@mawidi.com' });

    const responseTime = Date.now() - startTime;

    return {
      healthy: true,
      responseTime,
      timestamp: new Date().toISOString(),
      details: {
        status: responseTime < 1000 ? 'optimal' : 'slow',
        threshold: '1000ms',
        provider: 'convex',
      },
    };
  } catch (error) {
    return {
      healthy: false,
      responseTime: Date.now() - startTime,
      timestamp: new Date().toISOString(),
      error: sanitizeErrorMessage(error, 'Database'),
    };
  }
}

/**
 * Check Redis health (simplified for endpoint use)
 * Returns not-configured since Redis is no longer a primary dependency.
 */
export async function checkRedisHealth(): Promise<HealthCheckResponse & { configured: boolean }> {
  return {
    healthy: true,
    configured: false,
    responseTime: 0,
    timestamp: new Date().toISOString(),
    details: {
      message: 'Redis replaced by Convex for primary storage; Upstash used only for rate limiting',
    },
  };
}

/**
 * Check email service health
 */
export async function checkEmailHealth(): Promise<HealthCheckResponse> {
  const startTime = Date.now();

  try {
    const smtpConfigured = !!(
      process.env.SMTP_HOST &&
      process.env.SMTP_PORT &&
      process.env.SMTP_FROM
    );

    if (!smtpConfigured) {
      return {
        healthy: false,
        responseTime: 0,
        timestamp: new Date().toISOString(),
        error: 'SMTP not configured',
      };
    }

    const responseTime = Date.now() - startTime;

    return {
      healthy: true,
      responseTime,
      timestamp: new Date().toISOString(),
      details: {
        configured: true,
        host: process.env.SMTP_HOST,
        port: process.env.SMTP_PORT,
      },
    };
  } catch (error) {
    return {
      healthy: false,
      responseTime: Date.now() - startTime,
      timestamp: new Date().toISOString(),
      error: sanitizeErrorMessage(error, 'Email'),
    };
  }
}

/**
 * Get system metrics (CPU, memory, etc.)
 */
export function getSystemMetrics() {
  const mem = process.memoryUsage();

  return {
    uptime: process.uptime(),
    memory: {
      heapUsed: Math.round(mem.heapUsed / 1024 / 1024),
      heapTotal: Math.round(mem.heapTotal / 1024 / 1024),
      rss: Math.round(mem.rss / 1024 / 1024),
      external: Math.round(mem.external / 1024 / 1024),
      unit: 'MB',
    },
    cpu: {
      user: process.cpuUsage().user,
      system: process.cpuUsage().system,
    },
    node: {
      version: process.version,
      platform: process.platform,
      arch: process.arch,
    },
  };
}
