import { NextRequest, NextResponse } from 'next/server'

/**
 * Mac Mini System Monitoring API
 *
 * Provides system stats and Docker container management
 * Requires Docker socket mounted at /var/run/docker.sock
 */

interface ContainerInfo {
  id: string
  name: string
  image: string
  status: string
  state: string
  created: string
  ports: string[]
  cpu_percent: number
  memory_usage: string
  memory_limit: string
  memory_percent: number
  network_rx: string
  network_tx: string
}

interface SystemStats {
  hostname: string
  platform: string
  arch: string
  uptime: number
  cpu: {
    model: string
    cores: number
    usage_percent: number
  }
  memory: {
    total: string
    used: string
    free: string
    usage_percent: number
  }
  disk: {
    total: string
    used: string
    free: string
    usage_percent: number
  }
  timestamp: string
}

interface DockerStats {
  containers: ContainerInfo[]
  total_containers: number
  running_containers: number
  stopped_containers: number
}

// Helper to format bytes
function formatBytes(bytes: number): string {
  if (bytes === 0) return '0 B'
  const k = 1024
  const sizes = ['B', 'KB', 'MB', 'GB', 'TB']
  const i = Math.floor(Math.log(bytes) / Math.log(k))
  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
}

// Helper to format uptime
function formatUptime(seconds: number): string {
  const days = Math.floor(seconds / 86400)
  const hours = Math.floor((seconds % 86400) / 3600)
  const minutes = Math.floor((seconds % 3600) / 60)
  if (days > 0) return `${days}d ${hours}h ${minutes}m`
  if (hours > 0) return `${hours}h ${minutes}m`
  return `${minutes}m`
}

// Get Docker stats via socket
async function getDockerStats(): Promise<DockerStats> {
  const DOCKER_SOCKET = process.env.DOCKER_HOST || 'unix:///var/run/docker.sock'

  try {
    // Fetch container list
    const containersResponse = await fetch(`${DOCKER_SOCKET.replace('unix://', 'http://localhost')}/containers/json?all=true`, {
      // @ts-expect-error - Node.js fetch supports unix sockets via socketPath
      socketPath: '/var/run/docker.sock',
    })

    if (!containersResponse.ok) {
      throw new Error('Failed to fetch containers')
    }

    const containers = await containersResponse.json()

    // Get stats for running containers
    const containerInfos: ContainerInfo[] = await Promise.all(
      containers.map(async (container: Record<string, unknown>) => {
        const names = container.Names as string[]
        const name = names?.[0]?.replace(/^\//, '') || 'unknown'
        const state = container.State as string
        const status = container.Status as string
        const image = container.Image as string
        const created = container.Created as number
        const ports = container.Ports as Array<{ PrivatePort: number; PublicPort?: number; Type: string }>

        let cpu_percent = 0
        let memory_usage = '0 B'
        let memory_limit = '0 B'
        let memory_percent = 0
        let network_rx = '0 B'
        let network_tx = '0 B'

        // Get live stats for running containers
        if (state === 'running') {
          try {
            const statsResponse = await fetch(
              `http://localhost/containers/${container.Id}/stats?stream=false`,
              {
                // @ts-expect-error - Node.js fetch supports unix sockets
                socketPath: '/var/run/docker.sock',
              }
            )

            if (statsResponse.ok) {
              const stats = await statsResponse.json()

              // Calculate CPU usage
              const cpuDelta = stats.cpu_stats.cpu_usage.total_usage -
                (stats.precpu_stats?.cpu_usage?.total_usage || 0)
              const systemDelta = stats.cpu_stats.system_cpu_usage -
                (stats.precpu_stats?.system_cpu_usage || 0)
              const cpuCount = stats.cpu_stats.online_cpus || 1

              if (systemDelta > 0 && cpuDelta > 0) {
                cpu_percent = (cpuDelta / systemDelta) * cpuCount * 100
              }

              // Memory usage
              const memUsage = stats.memory_stats?.usage || 0
              const memLimit = stats.memory_stats?.limit || 0
              memory_usage = formatBytes(memUsage)
              memory_limit = formatBytes(memLimit)
              memory_percent = memLimit > 0 ? (memUsage / memLimit) * 100 : 0

              // Network stats
              const networks = stats.networks || {}
              let rxBytes = 0
              let txBytes = 0
              Object.values(networks).forEach((net: unknown) => {
                const network = net as { rx_bytes?: number; tx_bytes?: number }
                rxBytes += network.rx_bytes || 0
                txBytes += network.tx_bytes || 0
              })
              network_rx = formatBytes(rxBytes)
              network_tx = formatBytes(txBytes)
            }
          } catch {
            // Stats not available, use defaults
          }
        }

        return {
          id: (container.Id as string).substring(0, 12),
          name,
          image: (image as string).split(':')[0].split('/').pop() || image,
          status,
          state,
          created: new Date(created * 1000).toISOString(),
          ports: ports?.map(p =>
            p.PublicPort ? `${p.PublicPort}:${p.PrivatePort}/${p.Type}` : `${p.PrivatePort}/${p.Type}`
          ) || [],
          cpu_percent: Math.round(cpu_percent * 100) / 100,
          memory_usage,
          memory_limit,
          memory_percent: Math.round(memory_percent * 100) / 100,
          network_rx,
          network_tx,
        }
      })
    )

    // Sort by name
    containerInfos.sort((a, b) => a.name.localeCompare(b.name))

    return {
      containers: containerInfos,
      total_containers: containerInfos.length,
      running_containers: containerInfos.filter(c => c.state === 'running').length,
      stopped_containers: containerInfos.filter(c => c.state !== 'running').length,
    }
  } catch (error) {
    console.error('Docker stats error:', error)
    // Return empty stats if Docker socket not available
    return {
      containers: [],
      total_containers: 0,
      running_containers: 0,
      stopped_containers: 0,
    }
  }
}

// Get system stats
async function getSystemStats(): Promise<SystemStats> {
  const os = await import('os')

  const cpus = os.cpus()
  const totalMem = os.totalmem()
  const freeMem = os.freemem()
  const usedMem = totalMem - freeMem

  // Calculate CPU usage from cpus
  let totalIdle = 0
  let totalTick = 0
  cpus.forEach(cpu => {
    for (const type in cpu.times) {
      totalTick += cpu.times[type as keyof typeof cpu.times]
    }
    totalIdle += cpu.times.idle
  })
  const cpuUsage = 100 - (totalIdle / totalTick * 100)

  // Disk stats (root partition)
  let diskTotal = 0
  let diskUsed = 0
  let diskFree = 0

  try {
    const { execSync } = await import('child_process')
    const dfOutput = execSync('df -k / | tail -1').toString()
    const parts = dfOutput.split(/\s+/)
    diskTotal = parseInt(parts[1]) * 1024
    diskUsed = parseInt(parts[2]) * 1024
    diskFree = parseInt(parts[3]) * 1024
  } catch {
    // Disk stats not available
  }

  return {
    hostname: os.hostname(),
    platform: os.platform(),
    arch: os.arch(),
    uptime: os.uptime(),
    cpu: {
      model: cpus[0]?.model || 'Unknown',
      cores: cpus.length,
      usage_percent: Math.round(cpuUsage * 100) / 100,
    },
    memory: {
      total: formatBytes(totalMem),
      used: formatBytes(usedMem),
      free: formatBytes(freeMem),
      usage_percent: Math.round((usedMem / totalMem) * 100 * 100) / 100,
    },
    disk: {
      total: formatBytes(diskTotal),
      used: formatBytes(diskUsed),
      free: formatBytes(diskFree),
      usage_percent: diskTotal > 0 ? Math.round((diskUsed / diskTotal) * 100 * 100) / 100 : 0,
    },
    timestamp: new Date().toISOString(),
  }
}

// Container action (start/stop/restart)
async function containerAction(containerId: string, action: 'start' | 'stop' | 'restart'): Promise<void> {
  const response = await fetch(
    `http://localhost/containers/${containerId}/${action}`,
    {
      method: 'POST',
      // @ts-expect-error - Node.js fetch supports unix sockets
      socketPath: '/var/run/docker.sock',
    }
  )

  if (!response.ok && response.status !== 304) {
    const error = await response.text()
    throw new Error(`Failed to ${action} container: ${error}`)
  }
}

// GET - Fetch system and Docker stats
export async function GET() {
  try {
    const [system, docker] = await Promise.all([
      getSystemStats(),
      getDockerStats(),
    ])

    return NextResponse.json({
      system,
      docker,
      timestamp: new Date().toISOString(),
    })
  } catch (error) {
    console.error('Mac Mini stats error:', error)
    return NextResponse.json(
      { error: error instanceof Error ? error.message : 'Unknown error' },
      { status: 500 }
    )
  }
}

// POST - Container actions (start/stop/restart)
export async function POST(request: NextRequest) {
  try {
    const body = await request.json()
    const { container_id, action } = body

    if (!container_id || !action) {
      return NextResponse.json(
        { error: 'container_id and action required' },
        { status: 400 }
      )
    }

    if (!['start', 'stop', 'restart'].includes(action)) {
      return NextResponse.json(
        { error: 'Invalid action. Use: start, stop, restart' },
        { status: 400 }
      )
    }

    await containerAction(container_id, action)

    return NextResponse.json({
      success: true,
      message: `Container ${action} successful`,
      container_id,
      action,
    })
  } catch (error) {
    console.error('Container action error:', error)
    return NextResponse.json(
      { error: error instanceof Error ? error.message : 'Action failed' },
      { status: 500 }
    )
  }
}
