import { NextRequest, NextResponse } from 'next/server'
import { prisma } from '@/lib/prisma'

interface RouteContext {
  params: Promise<{ id: string }>
}

// Threshold for considering a server offline (5 minutes without heartbeat)
const OFFLINE_THRESHOLD_MS = 5 * 60 * 1000
// Threshold for degraded status (2 minutes without heartbeat)
const DEGRADED_THRESHOLD_MS = 2 * 60 * 1000

type HealthStatus = 'unknown' | 'pending' | 'online' | 'degraded' | 'offline'

function calculateHealthStatus(
  connectionStatus: string,
  lastHeartbeat: Date | null
): HealthStatus {
  if (connectionStatus === 'PENDING') {
    return 'pending'
  }

  if (!lastHeartbeat) {
    return 'unknown'
  }

  const timeSinceHeartbeat = Date.now() - lastHeartbeat.getTime()

  if (timeSinceHeartbeat > OFFLINE_THRESHOLD_MS) {
    return 'offline'
  }

  if (timeSinceHeartbeat > DEGRADED_THRESHOLD_MS) {
    return 'degraded'
  }

  return 'online'
}

/**
 * GET /api/v1/admin/servers/[id]/health
 * Get health status for a server
 */
export async function GET(_request: NextRequest, context: RouteContext) {
  try {
    const { id: orderId } = await context.params

    // Find order with server connection
    const order = await prisma.order.findUnique({
      where: { id: orderId },
      include: {
        serverConnection: true,
        user: {
          select: { email: true, name: true },
        },
      },
    })

    if (!order) {
      return NextResponse.json(
        { error: 'Order not found' },
        { status: 404 }
      )
    }

    const serverConnection = order.serverConnection

    // If no server connection exists yet
    if (!serverConnection) {
      return NextResponse.json({
        orderId: order.id,
        domain: order.domain,
        serverIp: order.serverIp,
        health: {
          status: 'not_provisioned' as const,
          message: 'Server has not been provisioned yet',
        },
        connection: null,
      })
    }

    // Calculate health status
    const healthStatus = calculateHealthStatus(
      serverConnection.status,
      serverConnection.lastHeartbeat
    )

    // Get recent command stats
    const [pendingCommands, recentFailedCommands] = await Promise.all([
      prisma.remoteCommand.count({
        where: {
          serverConnectionId: serverConnection.id,
          status: { in: ['PENDING', 'SENT', 'EXECUTING'] },
        },
      }),
      prisma.remoteCommand.count({
        where: {
          serverConnectionId: serverConnection.id,
          status: 'FAILED',
          completedAt: {
            gte: new Date(Date.now() - 24 * 60 * 60 * 1000), // Last 24 hours
          },
        },
      }),
    ])

    const timeSinceHeartbeat = serverConnection.lastHeartbeat
      ? Date.now() - serverConnection.lastHeartbeat.getTime()
      : null

    return NextResponse.json({
      orderId: order.id,
      domain: order.domain,
      serverIp: order.serverIp,
      orderStatus: order.status,
      health: {
        status: healthStatus,
        message: getHealthMessage(healthStatus, timeSinceHeartbeat),
      },
      connection: {
        id: serverConnection.id,
        status: serverConnection.status,
        registeredAt: serverConnection.registeredAt,
        lastHeartbeat: serverConnection.lastHeartbeat,
        timeSinceHeartbeat,
        orchestratorUrl: serverConnection.orchestratorUrl,
        agentVersion: serverConnection.agentVersion,
      },
      commands: {
        pending: pendingCommands,
        recentFailures: recentFailedCommands,
      },
    })
  } catch (error) {
    console.error('Health check error:', error)
    return NextResponse.json(
      { error: 'Internal server error' },
      { status: 500 }
    )
  }
}

function getHealthMessage(status: HealthStatus, timeSinceHeartbeat: number | null): string {
  switch (status) {
    case 'online':
      return 'Server is healthy and responding'
    case 'degraded':
      return `Last heartbeat ${Math.round((timeSinceHeartbeat || 0) / 1000)}s ago - may be experiencing issues`
    case 'offline':
      return `No heartbeat for ${Math.round((timeSinceHeartbeat || 0) / 60000)} minutes - server appears offline`
    case 'pending':
      return 'Waiting for orchestrator to register with Hub'
    case 'unknown':
      return 'Server status unknown - no heartbeat data available'
    default:
      return 'Unable to determine server status'
  }
}
