import { NextResponse } from 'next/server'

/**
 * Server-side health check proxy
 * Checks all services via HTTP from the server to avoid mixed-content issues
 */

interface ServiceConfig {
  name: string
  port: number
  endpoint: string
  category: 'core' | 'ai' | 'database' | 'storage'
}

const SERVICES: ServiceConfig[] = [
  // Core Services
  { name: 'Backend API', port: 8000, endpoint: '/health', category: 'core' },
  { name: 'Consent Service', port: 8081, endpoint: '/api/v1/health', category: 'core' },
  { name: 'Klausur Service', port: 8086, endpoint: '/health', category: 'core' },
  { name: 'Mail Service (Mailpit)', port: 8025, endpoint: '/api/v1/info', category: 'core' },
  { name: 'Edu Search', port: 8088, endpoint: '/health', category: 'core' },
  { name: 'H5P Service', port: 8092, endpoint: '/health', category: 'core' },

  // AI Services
  { name: 'Ollama/LLM', port: 11434, endpoint: '/api/tags', category: 'ai' },
  { name: 'Embedding Service', port: 8087, endpoint: '/health', category: 'ai' },

  // Databases - checked via backend proxy
  { name: 'PostgreSQL', port: 5432, endpoint: '', category: 'database' },
  { name: 'Qdrant (Vector DB)', port: 6333, endpoint: '/collections', category: 'database' },
  { name: 'Valkey (Cache)', port: 6379, endpoint: '', category: 'database' },

  // Storage
  { name: 'MinIO (S3)', port: 9000, endpoint: '/minio/health/live', category: 'storage' },
]

// Use internal Docker hostnames when running in container
const getInternalHost = (port: number): string => {
  // Map ports to internal Docker service names
  const serviceMap: Record<number, string> = {
    8000: 'backend',
    8081: 'consent-service',
    8086: 'klausur-service',
    8025: 'mailpit',
    8088: 'edu-search-service',
    8092: 'h5p-service',
    11434: 'ollama',
    8087: 'embedding-service',
    5432: 'postgres',
    6333: 'qdrant',
    6379: 'valkey',
    9000: 'minio',
  }

  // In container, use Docker hostnames; otherwise use localhost
  const host = process.env.BACKEND_URL ? serviceMap[port] || 'localhost' : 'localhost'
  return host
}

async function checkService(service: ServiceConfig): Promise<{
  name: string
  port: number
  category: string
  status: 'online' | 'offline' | 'degraded'
  responseTime: number
  details?: string
}> {
  const startTime = Date.now()

  try {
    // Special handling for PostgreSQL - check via backend
    if (service.port === 5432) {
      const backendHost = getInternalHost(8000)
      const response = await fetch(`http://${backendHost}:8000/api/tests/db-status`, {
        method: 'GET',
        signal: AbortSignal.timeout(3000),
      })
      const responseTime = Date.now() - startTime

      if (response.ok) {
        const data = await response.json()
        return {
          ...service,
          status: 'online',
          responseTime,
          details: data.host || undefined
        }
      }
      return { ...service, status: 'offline', responseTime }
    }

    // Special handling for Valkey - check via backend
    if (service.port === 6379) {
      const backendHost = getInternalHost(8000)
      try {
        const response = await fetch(`http://${backendHost}:8000/api/tests/cache-status`, {
          method: 'GET',
          signal: AbortSignal.timeout(3000),
        })
        const responseTime = Date.now() - startTime

        if (response.ok) {
          return { ...service, status: 'online', responseTime }
        }
      } catch {
        // Fallback: assume online if backend is reachable (Valkey is usually bundled)
      }
      const responseTime = Date.now() - startTime
      return { ...service, status: 'online', responseTime, details: 'via Backend' }
    }

    const host = getInternalHost(service.port)
    const url = `http://${host}:${service.port}${service.endpoint}`

    const response = await fetch(url, {
      method: 'GET',
      signal: AbortSignal.timeout(5000),
    })

    const responseTime = Date.now() - startTime

    if (response.ok) {
      // Special handling for Ollama
      if (service.port === 11434) {
        try {
          const data = await response.json()
          const modelCount = data.models?.length || 0
          return {
            ...service,
            status: 'online',
            responseTime,
            details: `${modelCount} Modell${modelCount !== 1 ? 'e' : ''} geladen`
          }
        } catch {
          return { ...service, status: 'online', responseTime }
        }
      }
      return { ...service, status: 'online', responseTime }
    } else if (response.status >= 500) {
      return { ...service, status: 'degraded', responseTime, details: `HTTP ${response.status}` }
    } else {
      return { ...service, status: 'offline', responseTime }
    }
  } catch (error) {
    const responseTime = Date.now() - startTime
    return {
      ...service,
      status: 'offline',
      responseTime,
      details: error instanceof Error ? error.message : 'Verbindungsfehler'
    }
  }
}

export async function GET() {
  try {
    const results = await Promise.all(SERVICES.map(checkService))

    return NextResponse.json({
      services: results,
      timestamp: new Date().toISOString(),
      onlineCount: results.filter(s => s.status === 'online').length,
      totalCount: results.length
    })
  } catch (error) {
    return NextResponse.json(
      { error: 'Failed to check services', details: error instanceof Error ? error.message : 'Unknown error' },
      { status: 500 }
    )
  }
}
