'use client'

/**
 * MonitoringPanel — 服務監控面板 (不含 AppLayout)
 * =================================================
 * Sprint 5: 從 /monitoring/page.tsx 抽取
 * 供原始頁面和整合頁面 (/observability) 共用
 * 零假數據: 串接真實 /api/v1/dashboard API
 *
 * 建立時間: 2026-04-09 (台北時區)
 */

import { useState, useEffect, useCallback, useRef } from 'react'
import { useSearchParams } from 'next/navigation'
import { useTranslations } from 'next-intl'
import { useGlobalPulseMetrics } from '@/hooks/useGlobalPulseMetrics'
import { useHosts } from '@/stores/dashboard.store'
import { GlobalPulseChart } from '@/components/charts/global-pulse-chart'
import { HostGrid } from '@/components/infra/host-grid'
import { cn } from '@/lib/utils'
import { Link } from '@/i18n/routing'
import {
  AwoooPStatusChainPanel,
  type AwoooPStatusChain,
} from '@/components/awooop/status-chain'
import type { IncidentTimelineResponse } from '@/lib/api-client'
import {
  Activity,
  BookOpenCheck,
  CheckCircle2,
  ExternalLink,
  GitBranch,
  Link2,
  ListChecks,
  Minus,
  Monitor,
  RadioTower,
  RefreshCw,
  ShieldCheck,
  TriangleAlert,
  Wrench,
  AlertCircle,
  XCircle,
} from 'lucide-react'

// =============================================================================
// Types
// =============================================================================

interface ServiceHealth {
  name: string
  status: 'healthy' | 'warning' | 'critical' | 'unknown'
  latency_ms: number | null
  uptime_pct: number | null
  last_checked: string
}

interface DashboardResponse {
  healthy_count: number
  warning_count: number
  critical_count: number
  total_count: number
  services: ServiceHealth[]
  timestamp: string
}

interface IncidentFocusState {
  chain: AwoooPStatusChain | null
  timeline: IncidentTimelineResponse | null
  loading: boolean
  error: string | null
}

type EvidenceTone = 'success' | 'warning' | 'blocked' | 'neutral'

// =============================================================================
// Helpers
// =============================================================================

const getApiBaseUrl = () => {
  if (typeof window === 'undefined') return ''
  return process.env.NEXT_PUBLIC_API_URL ?? ''
}

async function fetchJson<T>(url: string, signal?: AbortSignal): Promise<T> {
  const response = await fetch(url, { signal })
  if (!response.ok) throw new Error(`HTTP ${response.status}`)
  return response.json()
}

function valueOrEmpty(value: unknown, emptyLabel: string) {
  if (value === null || value === undefined || value === '') return emptyLabel
  return String(value)
}

function formatDateTime(value: string | null | undefined, emptyLabel: string) {
  if (!value) return emptyLabel
  const date = new Date(value)
  if (Number.isNaN(date.getTime())) return value
  return new Intl.DateTimeFormat('zh-TW', {
    month: '2-digit',
    day: '2-digit',
    hour: '2-digit',
    minute: '2-digit',
    hour12: false,
  }).format(date)
}

function compactPath(value: string | null | undefined, emptyLabel: string) {
  if (!value) return emptyLabel
  if (value.length <= 42) return value
  return `...${value.slice(-39)}`
}

function evidenceToneClass(tone: EvidenceTone) {
  if (tone === 'success') return 'border-[#9bc7a4] bg-[#f0faf2] text-[#17602a]'
  if (tone === 'blocked') return 'border-[#e2a29b] bg-[#fff0ef] text-[#9f2f25]'
  if (tone === 'warning') return 'border-[#d9b36f] bg-[#fff7e8] text-[#8a5a08]'
  return 'border-[#d8d3c7] bg-[#faf9f3] text-[#5f5b52]'
}

function providerLabel(provider: string) {
  const normalized = provider.toLowerCase()
  if (normalized === 'sentry') return 'Sentry'
  if (normalized === 'signoz') return 'SigNoz'
  return provider
}

const STATUS_ICON = {
  healthy: <CheckCircle2 className="w-4 h-4 text-status-healthy" />,
  warning: <AlertCircle className="w-4 h-4 text-status-warning" />,
  critical: <XCircle className="w-4 h-4 text-status-critical" />,
  unknown: <Minus className="w-4 h-4 text-nothing-gray-400" />,
}

const STATUS_BADGE = {
  healthy:  'bg-status-healthy/10 text-status-healthy border-status-healthy/20',
  warning:  'bg-status-warning/10 text-status-warning border-status-warning/20',
  critical: 'bg-status-critical/10 text-status-critical border-status-critical/20',
  unknown:  'bg-nothing-gray-100 text-nothing-gray-500 border-nothing-gray-200',
}

function HealthSummary({ data, t }: { data: DashboardResponse; t: (key: string) => string }) {
  const total = data.total_count || 0
  const pct = (count: number) => total > 0 ? `${Math.round(count / total * 100)}%` : '0%'

  return (
    <div className="grid grid-cols-3 gap-3 mb-6">
      {[
        { label: t('healthy'), count: data.healthy_count,  color: 'text-status-healthy', bg: 'bg-status-healthy/10' },
        { label: t('warning'), count: data.warning_count,  color: 'text-status-warning', bg: 'bg-status-warning/10' },
        { label: t('critical'), count: data.critical_count, color: 'text-status-critical', bg: 'bg-status-critical/10' },
      ].map(item => (
        <div key={item.label} className={cn('rounded-lg border p-4 text-center', item.bg, 'border-transparent')}>
          <div className={cn('text-3xl font-bold font-body tabular-nums', item.color)}>
            {item.count}
          </div>
          <div className="text-[11px] font-body text-nothing-gray-500 uppercase tracking-wider mt-1">
            {item.label} · {pct(item.count)}
          </div>
        </div>
      ))}
    </div>
  )
}

function EvidenceTile({
  icon: Icon,
  label,
  value,
  detail,
  tone = 'neutral',
}: {
  icon: typeof Monitor
  label: string
  value: string | number
  detail: string
  tone?: EvidenceTone
}) {
  return (
    <div className={cn('min-w-0 overflow-hidden border bg-white p-4', evidenceToneClass(tone))}>
      <div className="flex items-center gap-2">
        <Icon className="h-4 w-4 shrink-0" aria-hidden="true" />
        <p className="truncate text-xs font-semibold uppercase tracking-wider">{label}</p>
      </div>
      <p className="mt-3 truncate font-mono text-base font-semibold text-[#141413]" title={String(value)}>
        {value}
      </p>
      <p className="mt-2 line-clamp-2 text-xs leading-5 text-[#5f5b52]" title={detail}>
        {detail}
      </p>
    </div>
  )
}

function IncidentObservabilityFocus({
  incidentId,
  projectId,
  state,
}: {
  incidentId: string
  projectId: string
  state: IncidentFocusState
}) {
  const t = useTranslations('monitoring.incidentFocus')
  const chain = state.chain
  const timeline = state.timeline
  const emptyLabel = t('emptyValue')
  const encodedProjectId = encodeURIComponent(projectId)
  const encodedIncidentId = encodeURIComponent(incidentId)
  const sourceCorrelation = chain?.source_refs?.correlation
  const sourceStatus = String(sourceCorrelation?.status ?? 'missing')
  const sourceReason = String(sourceCorrelation?.missing_reason ?? '')
  const directRefTotal = sourceCorrelation?.direct_ref_total ?? 0
  const candidateTotal = sourceCorrelation?.candidate_total ?? 0
  const appliedLinkTotal = sourceCorrelation?.applied_link_total ?? 0
  const providerEventTotal = sourceCorrelation?.provider_event_total ?? 0
  const mcpGateway = chain?.mcp?.gateway
  const ansible = chain?.execution?.ansible
  const timelineStages = timeline?.timeline?.slice(0, 10) ?? []
  const approvalId = timeline?.approval_ids?.[0]
  const statusLabels: Record<string, string> = {
    linked: t('sourceStatuses.linked'),
    candidate_found: t('sourceStatuses.candidateFound'),
    provider_fresh_no_match: t('sourceStatuses.providerFreshNoMatch'),
    missing: t('sourceStatuses.missing'),
    no_incident_context: t('sourceStatuses.noIncidentContext'),
    fetch_failed: t('sourceStatuses.fetchFailed'),
  }
  const reasonLabels: Record<string, string> = {
    provider_heartbeat_present_but_no_incident_match: t('sourceReasons.providerHeartbeatNoMatch'),
    no_matching_provider_source_event: t('sourceReasons.noMatchingProviderSourceEvent'),
    no_incident_ids: t('sourceReasons.noIncidentIds'),
    incident_not_found: t('sourceReasons.incidentNotFound'),
    source_correlation_fetch_failed: t('sourceReasons.fetchFailed'),
  }
  const sourceStatusLabel = statusLabels[sourceStatus] ?? valueOrEmpty(sourceStatus, emptyLabel)
  const sourceReasonLabel = reasonLabels[sourceReason] ?? valueOrEmpty(sourceReason, emptyLabel)
  const providerEntries = Object.entries(sourceCorrelation?.providers ?? {})
  const sourceTone: EvidenceTone = appliedLinkTotal > 0
    ? 'success'
    : (directRefTotal > 0 || candidateTotal > 0 ? 'warning' : 'blocked')
  const mcpTone: EvidenceTone = (mcpGateway?.total ?? 0) > 0
    ? (((mcpGateway?.failed ?? 0) + (mcpGateway?.blocked ?? 0)) > 0 ? 'warning' : 'success')
    : 'neutral'
  const ansibleTone: EvidenceTone = ansible?.applied || (ansible?.apply_total ?? 0) > 0
    ? 'success'
    : (ansible?.considered || (ansible?.record_total ?? 0) > 0 ? 'warning' : 'neutral')
  const handoffTone: EvidenceTone = chain?.needs_human ? 'blocked' : (chain ? 'success' : 'neutral')

  const navItems = [
    {
      label: t('links.workItems'),
      href: `/awooop/work-items?project_id=${encodedProjectId}&incident_id=${encodedIncidentId}` as never,
      Icon: ListChecks,
    },
    {
      label: t('links.runs'),
      href: `/awooop/runs?project_id=${encodedProjectId}&incident_id=${encodedIncidentId}` as never,
      Icon: Activity,
    },
    {
      label: t('links.approvals'),
      href: `/awooop/approvals?project_id=${encodedProjectId}&incident_id=${encodedIncidentId}` as never,
      Icon: ShieldCheck,
    },
    {
      label: t('links.authorizations'),
      href: `/authorizations?project_id=${encodedProjectId}&incident_id=${encodedIncidentId}${approvalId ? `&approval_id=${encodeURIComponent(approvalId)}` : ''}` as never,
      Icon: CheckCircle2,
    },
    {
      label: t('links.tickets'),
      href: `/tickets?project_id=${encodedProjectId}&incident_id=${encodedIncidentId}` as never,
      Icon: GitBranch,
    },
  ]

  return (
    <section
      data-testid="monitoring-incident-focus"
      className="mb-6 overflow-hidden border border-[#e0ddd4] bg-white"
    >
      <div className="flex flex-wrap items-start justify-between gap-3 border-b border-[#e0ddd4] bg-[#faf9f3] px-4 py-4">
        <div className="min-w-0">
          <div className="flex flex-wrap items-center gap-2">
            <span className={cn('inline-flex h-8 w-8 items-center justify-center border', evidenceToneClass(handoffTone))}>
              {chain?.needs_human ? (
                <TriangleAlert className="h-4 w-4" aria-hidden="true" />
              ) : (
                <Monitor className="h-4 w-4" aria-hidden="true" />
              )}
            </span>
            <div className="min-w-0">
              <h3 className="truncate text-base font-semibold text-[#141413]">
                {t('title')}
              </h3>
              <p className="mt-1 text-xs leading-5 text-[#77736a]">
                {t('subtitle', {
                  incidentId,
                  incidentTitle: timeline?.title ?? valueOrEmpty(chain?.source_id, emptyLabel),
                })}
              </p>
            </div>
          </div>
        </div>
        <div className="flex flex-wrap gap-2">
          {navItems.map(({ label, href, Icon }) => (
            <Link
              key={label}
              href={href}
              className="inline-flex items-center gap-1.5 border border-[#d8d3c7] bg-white px-2.5 py-1.5 text-xs font-semibold text-[#3f3a32] hover:bg-[#f5f1e8]"
            >
              <Icon className="h-3.5 w-3.5" aria-hidden="true" />
              {label}
              <ExternalLink className="h-3 w-3" aria-hidden="true" />
            </Link>
          ))}
        </div>
      </div>

      {state.error && (
        <div className="border-b border-[#e0ddd4] bg-[#fff0ef] px-4 py-3 text-xs font-semibold text-[#9f2f25]" role="alert">
          {t('loadFailed', { error: state.error })}
        </div>
      )}

      {state.loading && !chain && !timeline && (
        <div className="border-b border-[#e0ddd4] px-4 py-3 text-xs text-[#77736a]">
          {t('loading')}
        </div>
      )}

      <div className="grid min-w-0 gap-px bg-[#e0ddd4] md:grid-cols-3 xl:grid-cols-6">
        <EvidenceTile
          icon={Link2}
          label={t('tiles.sourceRefs')}
          value={t('tiles.sourceRefsValue', {
            inbound: chain?.source_refs?.inbound_total ?? 0,
            outbound: chain?.source_refs?.outbound_total ?? 0,
          })}
          detail={t('tiles.sourceRefsDetail', {
            direct: directRefTotal,
            candidate: candidateTotal,
            applied: appliedLinkTotal,
          })}
          tone={sourceTone}
        />
        <EvidenceTile
          icon={RadioTower}
          label={t('tiles.provider')}
          value={sourceStatusLabel}
          detail={t('tiles.providerDetail', {
            reason: sourceReasonLabel,
            providerEvents: providerEventTotal,
          })}
          tone={sourceTone}
        />
        <EvidenceTile
          icon={Activity}
          label={t('tiles.mcp')}
          value={t('tiles.mcpValue', {
            success: mcpGateway?.success ?? 0,
            total: mcpGateway?.total ?? 0,
          })}
          detail={t('tiles.mcpDetail', {
            failed: mcpGateway?.failed ?? 0,
            blocked: mcpGateway?.blocked ?? 0,
            policy: mcpGateway?.policy_enforced_total ?? 0,
          })}
          tone={mcpTone}
        />
        <EvidenceTile
          icon={Wrench}
          label={t('tiles.ansible')}
          value={valueOrEmpty(ansible?.latest_status ?? chain?.execution?.latest_status, emptyLabel)}
          detail={t('tiles.ansibleDetail', {
            mode: valueOrEmpty(ansible?.latest_execution_mode, emptyLabel),
            rc: valueOrEmpty(ansible?.latest_returncode, emptyLabel),
            apply: valueOrEmpty(ansible?.latest_apply_executed, emptyLabel),
          })}
          tone={ansibleTone}
        />
        <EvidenceTile
          icon={BookOpenCheck}
          label={t('tiles.km')}
          value={chain?.evidence?.knowledge_entries ?? 0}
          detail={t('tiles.kmDetail', {
            verification: valueOrEmpty(chain?.verification, emptyLabel),
            next: valueOrEmpty(chain?.next_step ?? chain?.operator_outcome?.next_action, emptyLabel),
          })}
          tone={(chain?.evidence?.knowledge_entries ?? 0) > 0 ? 'success' : 'neutral'}
        />
        <EvidenceTile
          icon={chain?.needs_human ? TriangleAlert : CheckCircle2}
          label={t('tiles.handoff')}
          value={chain?.needs_human ? t('human.yes') : t('human.no')}
          detail={valueOrEmpty(chain?.operator_outcome?.summary_zh ?? chain?.operator_outcome?.human_action_reason, emptyLabel)}
          tone={handoffTone}
        />
      </div>

      <div className="grid min-w-0 gap-px bg-[#e0ddd4] lg:grid-cols-2">
        <div className="min-w-0 bg-white px-4 py-4">
          <div className="flex items-center justify-between gap-3">
            <h4 className="text-sm font-semibold text-[#141413]">{t('providerEvidence.title')}</h4>
            <span className="text-xs font-semibold text-[#77736a]">
              {t('providerEvidence.rawIdsHidden')}
            </span>
          </div>
          <p className="mt-2 text-xs leading-5 text-[#5f5b52]">
            {t('providerEvidence.summary', {
              status: sourceStatusLabel,
              reason: sourceReasonLabel,
            })}
          </p>
          <div className="mt-3 grid gap-2 md:grid-cols-2">
            {(providerEntries.length > 0 ? providerEntries : [['sentry', null], ['signoz', null]] as const).map(([provider, stats]) => (
              <div key={provider} className="border border-[#e0ddd4] bg-[#faf9f3] p-3">
                <p className="text-xs font-semibold text-[#141413]">{providerLabel(provider)}</p>
                <p className="mt-2 font-mono text-xs text-[#3f3a32]">
                  {t('providerEvidence.counts', {
                    direct: stats?.direct_ref_total ?? 0,
                    candidate: stats?.candidate_total ?? 0,
                    applied: stats?.applied_link_total ?? 0,
                  })}
                </p>
                <p className="mt-2 text-xs leading-5 text-[#77736a]">
                  {t('providerEvidence.latest', {
                    event: formatDateTime(stats?.latest_event_at, emptyLabel),
                    heartbeat: formatDateTime(stats?.latest_heartbeat_at, emptyLabel),
                  })}
                </p>
              </div>
            ))}
          </div>
        </div>

        <div className="min-w-0 bg-white px-4 py-4">
          <h4 className="text-sm font-semibold text-[#141413]">{t('timeline.title')}</h4>
          <p className="mt-2 text-xs leading-5 text-[#5f5b52]">
            {t('timeline.summary', {
              status: valueOrEmpty(timeline?.status, emptyLabel),
              severity: valueOrEmpty(timeline?.severity, emptyLabel),
              stages: timeline?.timeline?.length ?? 0,
            })}
          </p>
          <div className="mt-3 grid gap-2 sm:grid-cols-2">
            {timelineStages.map((stage) => (
              <div key={`${stage.stage}-${stage.status}-${stage.timestamp ?? ''}`} className="border border-[#e0ddd4] bg-[#faf9f3] p-3">
                <div className="flex items-center justify-between gap-2">
                  <p className="truncate text-xs font-semibold text-[#141413]" title={stage.label || stage.stage}>
                    {stage.label || stage.stage}
                  </p>
                  <span className="shrink-0 font-mono text-[11px] text-[#77736a]">{stage.status}</span>
                </div>
                <p className="mt-2 truncate text-xs text-[#5f5b52]" title={valueOrEmpty(stage.source_table, emptyLabel)}>
                  {t('timeline.sourceTable', { table: valueOrEmpty(stage.source_table, emptyLabel) })}
                </p>
              </div>
            ))}
            {timelineStages.length === 0 && (
              <div className="border border-[#e0ddd4] bg-[#faf9f3] p-3 text-xs text-[#77736a]">
                {t('timeline.empty')}
              </div>
            )}
          </div>
        </div>
      </div>

      <div className="border-t border-[#e0ddd4] bg-[#faf9f3] px-4 py-3 text-xs leading-5 text-[#5f5b52]">
        {t('boundary', {
          playbook: compactPath(ansible?.latest_playbook_path, emptyLabel),
          executor: valueOrEmpty(chain?.execution?.latest_executor, emptyLabel),
        })}
      </div>

      <div className="overflow-hidden">
        <AwoooPStatusChainPanel chain={chain} compact className="border-x-0 border-b-0" />
      </div>
    </section>
  )
}

// =============================================================================
// Panel 元件 (不含 AppLayout)
// =============================================================================

export function MonitoringPanel() {
  const t = useTranslations('monitoring')
  const tNav = useTranslations('nav')
  const tCommon = useTranslations('common')
  const tAlerts = useTranslations('alerts')
  const searchParams = useSearchParams()
  const projectId = searchParams.get('project_id') ?? 'awoooi'
  const incidentId = searchParams.get('incident_id')
  const hosts = useHosts()

  const { metrics, isLoading: metricsLoading } = useGlobalPulseMetrics({
    pollInterval: 30000,
    enablePolling: true,
  })

  const [dashboard, setDashboard] = useState<DashboardResponse | null>(null)
  const [dashLoading, setDashLoading] = useState(true)
  const [dashError, setDashError] = useState<string | null>(null)
  const [incidentFocus, setIncidentFocus] = useState<IncidentFocusState>({
    chain: null,
    timeline: null,
    loading: false,
    error: null,
  })
  const abortRef = useRef<AbortController | null>(null)
  const focusAbortRef = useRef<AbortController | null>(null)

  const fetchDashboard = useCallback(async () => {
    const base = getApiBaseUrl()
    if (!base) return

    abortRef.current?.abort()
    const ctrl = new AbortController()
    abortRef.current = ctrl

    setDashLoading(true)
    setDashError(null)
    try {
      const res = await fetch(`${base}/api/v1/dashboard`, { signal: ctrl.signal })
      if (!res.ok) throw new Error(`HTTP ${res.status}`)
      setDashboard(await res.json())
    } catch (e) {
      if (e instanceof Error && e.name === 'AbortError') return
      setDashError(e instanceof Error ? e.message : 'Unknown error')
    } finally {
      setDashLoading(false)
    }
  }, [])

  const fetchIncidentFocus = useCallback(async () => {
    const base = getApiBaseUrl()
    if (!base || !incidentId) {
      focusAbortRef.current?.abort()
      setIncidentFocus({ chain: null, timeline: null, loading: false, error: null })
      return
    }

    focusAbortRef.current?.abort()
    const ctrl = new AbortController()
    focusAbortRef.current = ctrl

    setIncidentFocus((current) => ({ ...current, loading: true, error: null }))
    const encodedProjectId = encodeURIComponent(projectId)
    const encodedIncidentId = encodeURIComponent(incidentId)
    const [statusChainResult, timelineResult] = await Promise.allSettled([
      fetchJson<AwoooPStatusChain>(
        `${base}/api/v1/platform/status-chain?project_id=${encodedProjectId}&incident_id=${encodedIncidentId}`,
        ctrl.signal
      ),
      fetchJson<IncidentTimelineResponse>(
        `${base}/api/v1/incidents/${encodedIncidentId}/timeline`,
        ctrl.signal
      ),
    ])

    if (ctrl.signal.aborted) return

    const chain = statusChainResult.status === 'fulfilled' ? statusChainResult.value : null
    const timeline = timelineResult.status === 'fulfilled' ? timelineResult.value : null
    const errors = [statusChainResult, timelineResult]
      .filter((item): item is PromiseRejectedResult => item.status === 'rejected')
      .map((item) => item.reason instanceof Error ? item.reason.message : String(item.reason))

    setIncidentFocus({
      chain,
      timeline,
      loading: false,
      error: errors.length > 0 ? errors.join(' / ') : null,
    })
  }, [incidentId, projectId])

  useEffect(() => {
    fetchDashboard()
    const id = setInterval(fetchDashboard, 30000)
    return () => {
      clearInterval(id)
      abortRef.current?.abort()
    }
  }, [fetchDashboard])

  useEffect(() => {
    fetchIncidentFocus()
    if (!incidentId) return () => {
      focusAbortRef.current?.abort()
    }
    const id = setInterval(fetchIncidentFocus, 30000)
    return () => {
      clearInterval(id)
      focusAbortRef.current?.abort()
    }
  }, [fetchIncidentFocus, incidentId])

  const isLoading = metricsLoading || dashLoading || incidentFocus.loading

  const handleRefresh = useCallback(() => {
    fetchDashboard()
    fetchIncidentFocus()
  }, [fetchDashboard, fetchIncidentFocus])

  return (
    <>
      {/* Header */}
      <div className="flex items-center justify-between mb-6">
        <div>
          <h2 className="font-heading text-2xl font-bold text-nothing-black flex items-center gap-2">
            <Monitor className="w-6 h-6" />
            {tNav('monitoring')}
          </h2>
          <p className="mt-1 text-sm text-nothing-gray-500 font-body">
            {tAlerts('autoRefresh', { seconds: 30 })}
          </p>
        </div>
        <button
          onClick={handleRefresh}
          disabled={isLoading}
          className={cn(
            'flex items-center gap-1.5 px-3 py-1.5 rounded-lg',
            'text-xs font-body bg-nothing-gray-100 text-nothing-gray-600',
            'hover:bg-nothing-gray-200 transition-colors',
            'disabled:opacity-50 disabled:cursor-not-allowed'
          )}
        >
          <RefreshCw className={cn('w-3.5 h-3.5', isLoading && 'animate-spin')} />
          {tCommon('refresh')}
        </button>
      </div>

      {incidentId && (
        <IncidentObservabilityFocus
          incidentId={incidentId}
          projectId={projectId}
          state={incidentFocus}
        />
      )}

      {/* Gold Metrics */}
      {metrics && <GlobalPulseChart metrics={metrics} />}

      {/* Health Summary */}
      {dashboard && <HealthSummary data={dashboard} t={(key) => t(key)} />}

      {/* Host Grid */}
      {hosts.length > 0 && (
        <div className="mb-6">
          <h3 className="text-sm font-bold font-body text-nothing-gray-700 mb-3 uppercase tracking-wider">
            {t('hostStatus')}
          </h3>
          <HostGrid hosts={hosts as any} />
        </div>
      )}

      {/* Service Table */}
      {dashboard?.services && dashboard.services.length > 0 && (
        <div>
          <h3 className="text-sm font-bold font-body text-nothing-gray-700 mb-3 uppercase tracking-wider">
            {t('serviceHealth')}
          </h3>
          <div className="overflow-x-auto">
            <table className="w-full text-sm font-body">
              <thead>
                <tr className="border-b border-nothing-gray-200">
                  <th className="text-left py-2 text-nothing-gray-500 font-medium">{t('service')}</th>
                  <th className="text-left py-2 text-nothing-gray-500 font-medium">{t('status')}</th>
                  <th className="text-right py-2 text-nothing-gray-500 font-medium">{t('latency')}</th>
                  <th className="text-right py-2 text-nothing-gray-500 font-medium">{t('uptime')}</th>
                </tr>
              </thead>
              <tbody>
                {dashboard.services.map((svc) => (
                  <tr key={svc.name} className="border-b border-nothing-gray-100">
                    <td className="py-2 font-medium">{svc.name}</td>
                    <td className="py-2">
                      <span className={cn('inline-flex items-center gap-1 px-2 py-0.5 rounded-md text-xs border', STATUS_BADGE[svc.status])}>
                        {STATUS_ICON[svc.status]}
                        {t(svc.status)}
                      </span>
                    </td>
                    <td className="py-2 text-right tabular-nums">{svc.latency_ms != null ? `${svc.latency_ms}ms` : '--'}</td>
                    <td className="py-2 text-right tabular-nums">{svc.uptime_pct != null ? `${svc.uptime_pct}%` : '--'}</td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        </div>
      )}
    </>
  )
}

export default MonitoringPanel
