"use client"

import { useCallback, useEffect, useMemo, useState } from "react"
import type { ReactNode } from "react"
import { useQuery } from "convex/react"
import { format, formatDistanceToNowStrict } from "date-fns"
import { ptBR } from "date-fns/locale"
import { toast } from "sonner"
import { ClipboardCopy, ServerCog, Cpu, MemoryStick, Monitor, HardDrive, Pencil, ShieldCheck, ShieldAlert, Apple, Terminal, Power, PlayCircle, Download } from "lucide-react"

import { api } from "@/convex/_generated/api"
import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
import { Checkbox } from "@/components/ui/checkbox"
import { Card, CardAction, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog"
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table"
import { Separator } from "@/components/ui/separator"
import { ChartContainer } from "@/components/ui/chart"
import { cn } from "@/lib/utils"
import { RadialBarChart, RadialBar, PolarAngleAxis } from "recharts"
import Link from "next/link"
import { useRouter } from "next/navigation"
import { useAuth } from "@/lib/auth-client"
import type { Id } from "@/convex/_generated/dataModel"

type MachineMetrics = Record<string, unknown> | null

type MachineLabel = {
  id?: number | string
  name?: string
}

type MachineSoftware = {
  name?: string
  version?: string
  source?: string
}

type NormalizedSoftwareEntry = {
  name: string
  version?: string
  publisher?: string
  installDate?: Date | null
  source?: string
}

type MachineAlertEntry = {
  id: string
  kind: string
  message: string
  severity: string
  createdAt: number
}

type DetailLineProps = { label: string; value?: string | number | null; classNameValue?: string }

type GpuAdapter = {
  name?: string
  vendor?: string
  driver?: string
  memoryBytes?: number
}

type LinuxLsblkEntry = {
  name?: string
  mountPoint?: string
  mountpoint?: string
  fs?: string
  fstype?: string
  sizeBytes?: number
  size?: number
}

type LinuxSmartEntry = {
  smart_status?: { passed?: boolean }
  model_name?: string
  model_family?: string
  serial_number?: string
  device?: { name?: string }
}

type LinuxExtended = {
  lsblk?: LinuxLsblkEntry[]
  lspci?: string
  lsusb?: string
  pciList?: Array<{ text: string }>
  usbList?: Array<{ text: string }>
  smart?: LinuxSmartEntry[]
}

type WindowsCpuInfo = {
  Name?: string
  Manufacturer?: string
  SocketDesignation?: string
  NumberOfCores?: number
  NumberOfLogicalProcessors?: number
  L2CacheSize?: number
  L3CacheSize?: number
  MaxClockSpeed?: number
}

type WindowsMemoryModule = {
  BankLabel?: string
  Capacity?: number
  Manufacturer?: string
  PartNumber?: string
  SerialNumber?: string
  ConfiguredClockSpeed?: number
  Speed?: number
  ConfiguredVoltage?: number
}

type WindowsVideoController = {
  Name?: string
  AdapterRAM?: number
  DriverVersion?: string
  PNPDeviceID?: string
}

type WindowsDiskEntry = {
  Model?: string
  SerialNumber?: string
  Size?: number
  InterfaceType?: string
  MediaType?: string
}

type WindowsExtended = {
  software?: MachineSoftware[]
  services?: Array<{ name?: string; status?: string; displayName?: string }>
  defender?: Record<string, unknown>
  hotfix?: Array<Record<string, unknown>>
  cpu?: WindowsCpuInfo | WindowsCpuInfo[]
  baseboard?: Record<string, unknown> | Array<Record<string, unknown>>
  bios?: Record<string, unknown> | Array<Record<string, unknown>>
  memoryModules?: WindowsMemoryModule[]
  videoControllers?: WindowsVideoController[]
  disks?: WindowsDiskEntry[]
  osInfo?: WindowsOsInfo
}

type MacExtended = {
  systemProfiler?: Record<string, unknown>
  packages?: string[]
  launchctl?: string
}

type NetworkInterface = { name?: string; mac?: string; ip?: string }

type MachineInventory = {
  hardware?: {
    vendor?: string
    model?: string
    serial?: string
    cpuType?: string
    physicalCores?: number
    logicalCores?: number
    memoryBytes?: number
    memory?: number
    primaryGpu?: GpuAdapter
    gpus?: GpuAdapter[]
  }
  network?: { primaryIp?: string; publicIp?: string; macAddresses?: string[] } | NetworkInterface[]
  software?: MachineSoftware[]
  labels?: MachineLabel[]
  fleet?: {
    id?: number | string
    teamId?: number | string
    detailUpdatedAt?: string
    osqueryVersion?: string
  }
  disks?: Array<{ name?: string; mountPoint?: string; fs?: string; interface?: string | null; serial?: string | null; totalBytes?: number; availableBytes?: number }>
  extended?: { linux?: LinuxExtended; windows?: WindowsExtended; macos?: MacExtended }
  services?: Array<{ name?: string; status?: string; displayName?: string }>
  collaborator?: { email?: string; name?: string; role?: string }
}

function collectInitials(name: string): string {
  const words = name.split(/\s+/).filter(Boolean)
  if (words.length === 0) return "?"
  if (words.length === 1) return words[0].slice(0, 2).toUpperCase()
  return (words[0][0] + words[1][0]).toUpperCase()
}

function toRecord(value: unknown): Record<string, unknown> | null {
  if (!value || typeof value !== "object") return null
  return value as Record<string, unknown>
}

function readString(record: Record<string, unknown>, ...keys: string[]): string | undefined {
  for (const key of keys) {
    const raw = record[key]
    if (typeof raw === "string" && raw.trim().length > 0) {
      return raw
    }
  }
  return undefined
}

function readNumber(record: Record<string, unknown>, ...keys: string[]): number | undefined {
  for (const key of keys) {
    const raw = record[key]
    if (typeof raw === "number" && Number.isFinite(raw)) {
      return raw
    }
    if (typeof raw === "string") {
      const trimmed = raw.trim()
      if (!trimmed) continue
      const parsed = Number(trimmed)
      if (!Number.isNaN(parsed)) return parsed
      const digits = trimmed.replace(/[^0-9.]/g, "")
      if (digits) {
        const fallback = Number(digits)
        if (!Number.isNaN(fallback)) return fallback
      }
    }
  }
  return undefined
}

function readText(record: Record<string, unknown>, ...keys: string[]): string | undefined {
  const stringValue = readString(record, ...keys)
  if (stringValue) return stringValue
  const numberValue = readNumber(record, ...keys)
  if (typeof numberValue === "number") return String(numberValue)
  return undefined
}

function parseWindowsInstallDate(value: unknown): Date | null {
  if (!value) return null
  if (value instanceof Date) return value
  if (typeof value === "number" && Number.isFinite(value)) {
    return new Date(value)
  }
  if (typeof value !== "string") return null
  const trimmed = value.trim()
  if (!trimmed) return null

  const wmiMatch = trimmed.match(/Date\((\d+)\)/)
  if (wmiMatch) {
    const timestamp = Number(wmiMatch[1])
    return Number.isFinite(timestamp) ? new Date(timestamp) : null
  }

  const isoValue = Date.parse(trimmed)
  if (!Number.isNaN(isoValue)) return new Date(isoValue)

  const digitsOnly = trimmed.replace(/[^0-9]/g, "")
  if (digitsOnly.length >= 8) {
    const yyyy = Number(digitsOnly.slice(0, 4))
    const mm = Number(digitsOnly.slice(4, 6))
    const dd = Number(digitsOnly.slice(6, 8))
    const hh = Number(digitsOnly.slice(8, 10) || "0")
    const mi = Number(digitsOnly.slice(10, 12) || "0")
    const ss = Number(digitsOnly.slice(12, 14) || "0")
    if (yyyy > 1900 && mm >= 1 && mm <= 12 && dd >= 1 && dd <= 31) {
      const parsed = new Date(Date.UTC(yyyy, mm - 1, dd, hh, mi, ss))
      if (!Number.isNaN(parsed.getTime())) return parsed
    }
    const dd2 = Number(digitsOnly.slice(0, 2))
    const mm2 = Number(digitsOnly.slice(2, 4))
    const yyyy2 = Number(digitsOnly.slice(4, 8))
    if (yyyy2 > 1900 && mm2 >= 1 && mm2 <= 12 && dd2 >= 1 && dd2 <= 31) {
      const parsed = new Date(Date.UTC(yyyy2, mm2 - 1, dd2))
      if (!Number.isNaN(parsed.getTime())) return parsed
    }
  }

  const localMatch = trimmed.match(
    /^(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})(?:\s+(\d{1,2}):(\d{2})(?::(\d{2}))?)?$/
  )
  if (localMatch) {
    const dd = Number(localMatch[1])
    const mm = Number(localMatch[2])
    const yyyy = Number(localMatch[3])
    const hh = Number(localMatch[4] || "0")
    const mi = Number(localMatch[5] || "0")
    const ss = Number(localMatch[6] || "0")
    if (yyyy > 1900 && mm >= 1 && mm <= 12 && dd >= 1 && dd <= 31) {
      const parsed = new Date(Date.UTC(yyyy, mm - 1, dd, hh, mi, ss))
      if (!Number.isNaN(parsed.getTime())) return parsed
    }
  }
  return null
}

type WindowsOsInfo = {
  productName?: string
  editionId?: string
  displayVersion?: string
  releaseId?: string
  version?: string
  currentBuild?: string
  currentBuildNumber?: string
  licenseStatus?: number
  isActivated?: boolean
  licenseStatusText?: string
  productId?: string
  partialProductKey?: string
  computerName?: string
  registeredOwner?: string
  installDate?: Date | null
  experience?: string
}

function parseWindowsOsInfo(raw: unknown): WindowsOsInfo | null {
  if (!raw) return null
  const parseRecord = (value: Record<string, unknown>) => {
    const read = (k: string, ...alts: string[]) => readString(value, k, ...alts)
    const readNum = (...keys: string[]) => readNumber(value, ...keys)
    const readFlexible = (...keys: string[]) => readText(value, ...keys)

    const family = read("Family")
    const edition = read("Edition")

    const productName =
      readFlexible("ProductName", "productName", "Name", "name", "Caption", "caption") ??
      (family && edition ? `${family} ${edition}` : family ?? edition ?? undefined)

    const editionId =
      readFlexible("EditionID", "editionId", "Edition", "edition", "SkuEdition", "skuEdition", "CompositionEditionID", "compositionEditionId") ??
      undefined

    const displayVersion = readFlexible("DisplayVersion", "displayVersion")
    const versionValue =
      readFlexible("Version", "version", "ReleaseId", "releaseId") ?? displayVersion

    const baseBuild =
      readFlexible("CurrentBuildNumber", "currentBuildNumber", "CurrentBuild", "currentBuild", "OSBuild", "osBuild", "BuildNumber", "buildNumber") ??
      undefined
    const ubrRaw = readFlexible("UBR")
    const licenseStatus = readNum("LicenseStatus", "licenseStatus")
    const licenseStatusTextRaw = readFlexible(
      "LicenseStatusDescription",
      "licenseStatusDescription",
      "StatusDescription",
      "statusDescription",
      "Status",
      "status"
    )
    const licenseStatusText = licenseStatusTextRaw ? licenseStatusTextRaw.trim() : undefined
    const currentBuildNumber =
      baseBuild && ubrRaw && /^\d+$/.test(ubrRaw) ? `${baseBuild}.${ubrRaw}` : baseBuild ?? readFlexible("BuildNumber", "buildNumber")
    const currentBuild = baseBuild

    const isActivatedRaw = value["IsActivated"] ?? value["isActivated"]
    const isLicensedRaw = value["IsLicensed"] ?? value["isLicensed"]
    const isActivated =
      typeof isActivatedRaw === "boolean"
        ? isActivatedRaw
        : typeof isActivatedRaw === "number"
          ? isActivatedRaw === 1
        : typeof isActivatedRaw === "string"
          ? isActivatedRaw.toLowerCase() === "true"
          : typeof isLicensedRaw === "boolean"
            ? isLicensedRaw
            : typeof isLicensedRaw === "number"
              ? isLicensedRaw === 1
              : typeof isLicensedRaw === "string"
                ? ["1", "true", "licensed", "license", "activated"].includes(isLicensedRaw.toLowerCase())
                : licenseStatus === 1 || Boolean(licenseStatusText && /licensed|activated|licenciado/i.test(licenseStatusText))

    const installDate =
      parseWindowsInstallDate(value["InstallDate"]) ??
      parseWindowsInstallDate(value["InstallationDate"]) ??
      parseWindowsInstallDate(value["InstallDateTime"]) ??
      parseWindowsInstallDate(value["InstalledOn"])

    const experience =
      readFlexible("Experience", "experience", "FeatureExperiencePack", "featureExperiencePack") ??
      (currentBuildNumber ? `OS Build ${currentBuildNumber}` : undefined)

    const productId = readFlexible("ProductID", "productID", "ProductId", "productId", "ProductKeyId", "productKeyId")
    const partialProductKey = readFlexible("PartialProductKey", "partialProductKey")
    const computerName = readFlexible("DeviceName", "deviceName", "ComputerName", "computerName", "CSName", "csName", "HostName", "hostName")
    const registeredOwner = readFlexible("RegisteredOwner", "registeredOwner", "RegisteredOrganization", "registeredOrganization")

    return {
      productName,
      editionId,
      displayVersion,
      version: versionValue,
      releaseId: read("ReleaseId", "releaseId"),
      currentBuild,
      currentBuildNumber,
      licenseStatus,
      isActivated,
      licenseStatusText,
      productId,
      partialProductKey,
      computerName,
      registeredOwner,
      installDate,
      experience,
    }
  }

  if (Array.isArray(raw)) {
    for (const entry of raw) {
      const record = toRecord(entry)
      if (record) {
        return parseRecord(record)
      }
    }
    return null
  }
  if (typeof raw === "string") {
    return { productName: raw }
  }
  const record = toRecord(raw)
  if (!record) return null
  return parseRecord(record)
}

function normalizeWindowsSoftwareEntry(value: unknown): NormalizedSoftwareEntry | null {
  const record = toRecord(value)
  if (!record) return null

  const name =
    readString(record, "DisplayName", "displayName", "Name", "name") ??
    readText(record, "Title", "title") ??
    ""
  if (!name) return null

  const version = readString(record, "DisplayVersion", "displayVersion", "Version", "version") ?? undefined
  const publisher = readString(record, "Publisher", "publisher", "Vendor", "vendor") ?? undefined
  const installDate =
    parseWindowsInstallDate(record["InstallDate"]) ??
    parseWindowsInstallDate(record["InstallDateUTC"]) ??
    parseWindowsInstallDate(record["InstallDateTime"]) ??
    parseWindowsInstallDate(record["InstallDateFromRegistry"]) ??
    parseWindowsInstallDate(record["InstallDateFromRegistryUTC"]) ??
    parseWindowsInstallDate(record["InstalledDate"]) ??
    parseWindowsInstallDate(record["InstalledOn"]) ??
    null

  const source = readString(record, "ParentDisplayName", "ParentKeyName", "SystemComponent") ?? undefined

  return {
    name,
    version,
    publisher,
    installDate,
    source,
  }
}

function parseBytesLike(value: unknown): number | undefined {
  if (typeof value === "number" && Number.isFinite(value)) return value
  if (typeof value === "string") {
    const trimmed = value.trim()
    if (!trimmed) return undefined
    const normalized = trimmed.replace(",", ".")
    const match = normalized.match(/^([\d.]+)\s*(ti|tb|tib|gb|gib|mb|mib|kb|kib|b)?$/i)
    if (match) {
      const amount = Number(match[1])
      if (Number.isNaN(amount)) return undefined
      const unit = match[2]?.toLowerCase()
      const base = 1024
      const unitMap: Record<string, number> = {
        b: 1,
        kb: base,
        kib: base,
        mb: base ** 2,
        mib: base ** 2,
        gb: base ** 3,
        gib: base ** 3,
        tb: base ** 4,
        tib: base ** 4,
        ti: base ** 4,
      }
      if (unit) {
        const multiplier = unitMap[unit]
        if (multiplier) {
          return amount * multiplier
        }
      }
      return amount
    }
    const digits = normalized.replace(/[^0-9.]/g, "")
    if (digits) {
      const fallback = Number(digits)
      if (!Number.isNaN(fallback)) return fallback
    }
  }
  return undefined
}

function deriveVendor(record: Record<string, unknown>): string | undefined {
  const direct = readString(record, "vendor", "Vendor", "AdapterCompatibility")
  if (direct) return direct
  const pnp = readString(record, "PNPDeviceID")
  if (!pnp) return undefined
  const match = pnp.match(/VEN_([0-9A-F]{4})/i)
  if (match) {
    const vendorCode = match[1].toUpperCase()
    const vendorMap: Record<string, string> = {
      "10DE": "NVIDIA",
      "1002": "AMD",
      "1022": "AMD",
      "8086": "Intel",
      "8087": "Intel",
      "1AF4": "Red Hat",
    }
    return vendorMap[vendorCode] ?? `VEN_${vendorCode}`
  }
  const segments = pnp.split("\\")
  const last = segments.pop()
  return last && last.trim().length > 0 ? last : pnp
}

function normalizeGpuSource(value: unknown): GpuAdapter | null {
  if (typeof value === "string") {
    const name = value.trim()
    return name ? { name } : null
  }
  const record = toRecord(value)
  if (!record) return null
  const name = readString(record, "name", "Name", "_name", "AdapterCompatibility")
  const vendor = deriveVendor(record)
  const driver = readString(record, "driver", "DriverVersion", "driverVersion")
  const memoryBytes =
    readNumber(record, "memoryBytes", "MemoryBytes", "AdapterRAM", "VRAM", "vramBytes") ??
    parseBytesLike(record["AdapterRAM"] ?? record["VRAM"] ?? record["vram"])
  if (!name && !vendor && !driver && memoryBytes === undefined) {
    return null
  }
  return { name, vendor, driver, memoryBytes }
}

function uniqueBy<T>(items: T[], keyFn: (item: T) => string): T[] {
  const seen = new Set<string>()
  const result: T[] = []
  items.forEach((item) => {
    const key = keyFn(item)
    if (key && !seen.has(key)) {
      seen.add(key)
      result.push(item)
    }
  })
  return result
}

export type MachinesQueryItem = {
  id: string
  tenantId: string
  hostname: string
  companyId: string | null
  companySlug: string | null
  osName: string | null
  osVersion: string | null
  architecture: string | null
  macAddresses: string[]
  serialNumbers: string[]
  authUserId: string | null
  authEmail: string | null
  persona: string | null
  assignedUserId: string | null
  assignedUserEmail: string | null
  assignedUserName: string | null
  assignedUserRole: string | null
  status: string | null
  isActive: boolean
  lastHeartbeatAt: number | null
  heartbeatAgeMs: number | null
  registeredBy: string | null
  createdAt: number
  updatedAt: number
  token: {
    expiresAt: number
    lastUsedAt: number | null
    usageCount: number
  } | null
  metrics: MachineMetrics
  inventory: MachineInventory | null
  postureAlerts?: Array<Record<string, unknown>> | null
  lastPostureAt?: number | null
}

function useMachinesQuery(tenantId: string): MachinesQueryItem[] {
  return (
    (useQuery(api.machines.listByTenant, {
      tenantId,
      includeMetadata: true,
    }) ?? []) as MachinesQueryItem[]
  )
}

const DEFAULT_OFFLINE_THRESHOLD_MS = 10 * 60 * 1000
const DEFAULT_STALE_THRESHOLD_MS = DEFAULT_OFFLINE_THRESHOLD_MS * 12

function parseThreshold(raw: string | undefined, fallback: number) {
  if (!raw) return fallback
  const parsed = Number(raw)
  if (!Number.isFinite(parsed) || parsed <= 0) return fallback
  return parsed
}

const MACHINE_OFFLINE_THRESHOLD_MS = parseThreshold(process.env.NEXT_PUBLIC_MACHINE_OFFLINE_THRESHOLD_MS, DEFAULT_OFFLINE_THRESHOLD_MS)
const MACHINE_STALE_THRESHOLD_MS = parseThreshold(process.env.NEXT_PUBLIC_MACHINE_STALE_THRESHOLD_MS, DEFAULT_STALE_THRESHOLD_MS)

const statusLabels: Record<string, string> = {
  online: "Online",
  offline: "Offline",
  stale: "Sem sinal",
  maintenance: "Manutenção",
  blocked: "Bloqueada",
  deactivated: "Desativada",
  unknown: "Desconhecida",
}

const statusClasses: Record<string, string> = {
  online: "border-emerald-500/20 bg-emerald-500/15 text-emerald-600",
  offline: "border-rose-500/20 bg-rose-500/15 text-rose-600",
  stale: "border-slate-400/30 bg-slate-200 text-slate-700",
  maintenance: "border-amber-500/20 bg-amber-500/15 text-amber-600",
  blocked: "border-orange-500/20 bg-orange-500/15 text-orange-600",
  deactivated: "border-slate-400/40 bg-slate-100 text-slate-600",
  unknown: "border-slate-300 bg-slate-200 text-slate-700",
}

const POSTURE_ALERT_LABELS: Record<string, string> = {
  CPU_HIGH: "CPU alta",
  SERVICE_DOWN: "Serviço indisponível",
  SMART_FAIL: "Falha SMART",
}

function formatPostureAlertKind(raw?: string | null): string {
  if (!raw) return "Alerta"
  const normalized = raw.toUpperCase()
  if (POSTURE_ALERT_LABELS[normalized]) {
    return POSTURE_ALERT_LABELS[normalized]
  }
  return raw
    .toLowerCase()
    .replace(/_/g, " ")
    .replace(/\b\w/g, (char) => char.toUpperCase())
}

function postureSeverityClass(severity?: string | null) {
  return (severity ?? "warning").toLowerCase() === "critical"
    ? "border-rose-500/20 bg-rose-500/10"
    : "border-amber-500/20 bg-amber-500/10"
}

function formatRelativeTime(date?: Date | null) {
  if (!date) return "Nunca"
  try {
    return formatDistanceToNowStrict(date, { addSuffix: true, locale: ptBR })
  } catch {
    return "—"
  }
}

function formatInstallDate(date?: Date | null) {
  if (!date) return null
  return `${formatAbsoluteDateTime(date)} (${formatRelativeTime(date)})`
}

function formatDate(date?: Date | null) {
  if (!date) return "—"
  return format(date, "dd/MM/yyyy HH:mm")
}

function formatAbsoluteDateTime(date?: Date | null) {
  if (!date) return "—"
  return new Intl.DateTimeFormat("pt-BR", {
    dateStyle: "long",
    timeStyle: "short",
  }).format(date)
}

function parseDateish(value: unknown): Date | null {
  if (!value) return null
  if (value instanceof Date && !Number.isNaN(value.getTime())) return value
  if (typeof value === "number" && Number.isFinite(value)) {
    const numeric = value > 1e12 ? value : value > 1e9 ? value * 1000 : value
    const date = new Date(numeric)
    return Number.isNaN(date.getTime()) ? null : date
  }
  if (typeof value === "string") {
    const trimmed = value.trim()
    if (!trimmed) return null
    const numericValue = Number(trimmed)
    if (Number.isFinite(numericValue)) {
      const asMs = trimmed.length >= 13 ? numericValue : numericValue * 1000
      const date = new Date(asMs)
      if (!Number.isNaN(date.getTime())) return date
    }
    const date = new Date(trimmed)
    if (!Number.isNaN(date.getTime())) return date
  }
  return null
}

function getMetricsTimestamp(metrics: MachineMetrics): Date | null {
  if (!metrics || typeof metrics !== "object") return null
  const data = metrics as Record<string, unknown>
  const candidates = [
    data["collectedAt"],
    data["collected_at"],
    data["collected_at_iso"],
    data["collected_at_ms"],
    data["timestamp"],
    data["updatedAt"],
    data["updated_at"],
    data["createdAt"],
    data["created_at"],
  ]
  for (const candidate of candidates) {
    const parsed = parseDateish(candidate)
    if (parsed) return parsed
  }
  return null
}

function formatBytes(bytes?: number | null) {
  if (!bytes || Number.isNaN(bytes)) return "—"
  const units = ["B", "KB", "MB", "GB", "TB"]
  let value = bytes
  let unitIndex = 0
  while (value >= 1024 && unitIndex < units.length - 1) {
    value /= 1024
    unitIndex += 1
  }
  return `${value.toFixed(value >= 10 || unitIndex === 0 ? 0 : 1)} ${units[unitIndex]}`
}

function formatPercent(value?: number | null) {
  if (value === null || value === undefined || Number.isNaN(value)) return "—"
  const normalized = value > 1 ? value : value * 100
  return `${normalized.toFixed(0)}%`
}

function readBool(source: unknown, key: string): boolean | undefined {
  if (!source || typeof source !== "object") return undefined
  const value = (source as Record<string, unknown>)[key]
  return typeof value === "boolean" ? value : undefined
}

function getStatusVariant(status?: string | null) {
  if (!status) return { label: statusLabels.unknown, className: statusClasses.unknown }
  const normalized = status.toLowerCase()
  return {
    label: statusLabels[normalized] ?? status,
    className: statusClasses[normalized] ?? statusClasses.unknown,
  }
}

function resolveMachineStatus(machine: { status?: string | null; lastHeartbeatAt?: number | null; isActive?: boolean | null }): string {
  if (machine.isActive === false) return "deactivated"
  const manualStatus = (machine.status ?? "").toLowerCase()
  if (["maintenance", "blocked"].includes(manualStatus)) {
    return manualStatus
  }
  const heartbeat = machine.lastHeartbeatAt
  if (typeof heartbeat === "number" && Number.isFinite(heartbeat) && heartbeat > 0) {
    const age = Date.now() - heartbeat
    if (age <= MACHINE_OFFLINE_THRESHOLD_MS) return "online"
    if (age <= MACHINE_STALE_THRESHOLD_MS) return "offline"
    return "stale"
  }
  return machine.status ?? "unknown"
}

function OsIcon({ osName }: { osName?: string | null }) {
  const name = (osName ?? "").toLowerCase()
  if (name.includes("mac") || name.includes("darwin") || name.includes("macos")) return <Apple className="size-4 text-black" />
  if (name.includes("linux")) return <Terminal className="size-4 text-black" />
  // fallback para Windows/outros como monitor genérico
  return <Monitor className="size-4 text-black" />
}

export function AdminMachinesOverview({ tenantId }: { tenantId: string }) {
  const machines = useMachinesQuery(tenantId)
  const [q, setQ] = useState("")
  const [statusFilter, setStatusFilter] = useState<string>("all")
  const [osFilter, setOsFilter] = useState<string>("all")
  const [companyQuery, setCompanyQuery] = useState<string>("")
  const [onlyAlerts, setOnlyAlerts] = useState<boolean>(false)
  const { convexUserId } = useAuth()
  const companies = useQuery(
    convexUserId ? api.companies.list : "skip",
    convexUserId ? { tenantId, viewerId: convexUserId as Id<"users"> } : ("skip" as const)
  ) as Array<{ id: string; name: string; slug?: string }> | undefined
  const companyNameBySlug = useMemo(() => {
    const map = new Map<string, string>()
    ;(companies ?? []).forEach((c) => c.slug && map.set(c.slug, c.name))
    return map
  }, [companies])

  const osOptions = useMemo(() => {
    const set = new Set<string>()
    machines.forEach((m) => m.osName && set.add(m.osName))
    return Array.from(set).sort()
  }, [machines])

  const companyNameOptions = useMemo(() => (companies ?? []).map((c) => c.name).sort((a,b)=>a.localeCompare(b,"pt-BR")), [companies])

const filteredMachines = useMemo(() => {
    const text = q.trim().toLowerCase()
    return machines.filter((m) => {
      if (onlyAlerts && !(Array.isArray(m.postureAlerts) && m.postureAlerts.length > 0)) return false
      if (statusFilter !== "all") {
        const s = resolveMachineStatus(m).toLowerCase()
        if (s !== statusFilter) return false
      }
      if (osFilter !== "all" && (m.osName ?? "").toLowerCase() !== osFilter.toLowerCase()) return false
      if (companyQuery && companyQuery.trim().length > 0) {
        const name = companyNameBySlug.get(m.companySlug ?? "")?.toLowerCase() ?? ""
        if (!name.includes(companyQuery.trim().toLowerCase())) return false
      }
      if (!text) return true
      const hay = [
        m.hostname,
        m.authEmail ?? "",
        (m.macAddresses ?? []).join(" "),
        (m.serialNumbers ?? []).join(" "),
      ]
        .join(" ")
        .toLowerCase()
      return hay.includes(text)
    })
  }, [machines, q, statusFilter, osFilter, companyQuery, onlyAlerts, companyNameBySlug])

  return (
    <div className="grid gap-6">
      <Card className="border-slate-200">
        <CardHeader>
          <CardTitle>Máquinas registradas</CardTitle>
          <CardDescription>Sincronizadas via agente local ou Fleet. Atualiza em tempo real.</CardDescription>
        </CardHeader>
        <CardContent className="overflow-hidden">
          <div className="mb-3 flex flex-wrap items-center gap-2">
            <div className="min-w-[220px] flex-1">
              <Input value={q} onChange={(e) => setQ(e.target.value)} placeholder="Buscar hostname, e-mail, MAC, serial..." />
            </div>
            <Select value={statusFilter} onValueChange={setStatusFilter}>
              <SelectTrigger className="min-w-36">
                <SelectValue placeholder="Status" />
              </SelectTrigger>
              <SelectContent>
                <SelectItem value="all">Todos status</SelectItem>
                <SelectItem value="online">Online</SelectItem>
                <SelectItem value="offline">Offline</SelectItem>
                <SelectItem value="stale">Sem sinal</SelectItem>
                <SelectItem value="unknown">Desconhecido</SelectItem>
              </SelectContent>
            </Select>
            <Select value={osFilter} onValueChange={setOsFilter}>
              <SelectTrigger className="min-w-40">
                <SelectValue placeholder="Sistema" />
              </SelectTrigger>
              <SelectContent>
                <SelectItem value="all">Todos sistemas</SelectItem>
                {osOptions.map((os) => (
                  <SelectItem key={os} value={os}>{os}</SelectItem>
                ))}
              </SelectContent>
            </Select>
            <div className="relative">
              <Input
                value={companyQuery}
                onChange={(e) => setCompanyQuery(e.target.value)}
                placeholder="Buscar empresa"
                className="min-w-[220px]"
              />
              {companyQuery && companyNameOptions.filter((c) => c.toLowerCase().includes(companyQuery.toLowerCase())).slice(0,6).length > 0 ? (
                <div className="absolute z-10 mt-1 max-h-52 w-full overflow-auto rounded-md border bg-white p-1 shadow-sm">
                  {companyNameOptions
                    .filter((c) => c.toLowerCase().includes(companyQuery.toLowerCase()))
                    .slice(0, 8)
                    .map((c) => (
                      <button
                        key={c}
                        type="button"
                        onClick={() => setCompanyQuery(c)}
                        className="w-full rounded px-2 py-1 text-left text-sm hover:bg-slate-100"
                      >
                        {c}
                      </button>
                    ))}
                </div>
              ) : null}
            </div>
            <label className="inline-flex items-center gap-2 rounded-md border border-slate-200 bg-slate-50/80 px-3 py-1.5 text-sm">
              <Checkbox checked={onlyAlerts} onCheckedChange={(v) => setOnlyAlerts(Boolean(v))} />
              <span>Somente com alertas</span>
            </label>
            <Button variant="outline" onClick={() => { setQ(""); setStatusFilter("all"); setOsFilter("all"); setCompanyQuery(""); setOnlyAlerts(false) }}>Limpar</Button>
          </div>
          {machines.length === 0 ? (
            <EmptyState />
          ) : (
            <MachinesGrid machines={filteredMachines} companyNameBySlug={companyNameBySlug} />
          )}
        </CardContent>
      </Card>
    </div>
  )
}

function MachineStatusBadge({ status }: { status?: string | null }) {
  const { label, className } = getStatusVariant(status)
  const s = String(status ?? "").toLowerCase()
  const colorClass =
    s === "online"
      ? "bg-emerald-500"
      : s === "offline"
        ? "bg-rose-500"
        : s === "maintenance"
          ? "bg-amber-500"
          : s === "blocked"
            ? "bg-orange-500"
            : s === "deactivated"
              ? "bg-slate-500"
            : "bg-slate-400"
  const ringClass =
    s === "online"
      ? "bg-emerald-400/30"
      : s === "offline"
        ? "bg-rose-400/30"
        : s === "maintenance"
          ? "bg-amber-400/30"
          : s === "blocked"
            ? "bg-orange-400/30"
            : s === "deactivated"
              ? "bg-slate-400/40"
            : "bg-slate-300/30"

  const isOnline = s === "online"
  return (
    <Badge className={cn("inline-flex h-9 items-center gap-5 rounded-full border border-slate-200 px-3 text-sm font-semibold", className)}>
      <span className="relative inline-flex items-center">
        <span className={cn("size-2 rounded-full", colorClass)} />
        {isOnline ? (
          <span className={cn("absolute left-1/2 top-1/2 size-4 -translate-x-1/2 -translate-y-1/2 rounded-full animate-ping [animation-duration:2s]", ringClass)} />
        ) : null}
      </span>
      {label}
    </Badge>
  )
}

function EmptyState() {
  return (
    <div className="flex flex-col items-center gap-3 rounded-lg border border-dashed border-slate-300 bg-slate-50/50 py-12 text-center">
      <ServerCog className="size-10 text-slate-400" />
      <div className="space-y-1">
        <p className="text-sm font-semibold text-slate-600">Nenhuma máquina registrada ainda</p>
        <p className="text-sm text-muted-foreground">
          Execute o agente local ou o webhook do Fleet para registrar as máquinas do tenant.
        </p>
      </div>
    </div>
  )
}

type MachineDetailsProps = {
  machine: MachinesQueryItem | null
}

export function MachineDetails({ machine }: MachineDetailsProps) {
  const { convexUserId } = useAuth()
  const router = useRouter()
  const effectiveStatus = machine ? resolveMachineStatus(machine) : "unknown"
  const isActive = machine?.isActive ?? true
  const isDeactivated = !isActive || effectiveStatus === "deactivated"
  // Company name lookup (by slug)
  const companyQueryArgs = convexUserId && machine ? { tenantId: machine.tenantId, viewerId: convexUserId as Id<"users"> } : undefined
  const companies = useQuery(
    api.companies.list,
    companyQueryArgs ?? ("skip" as const)
  ) as Array<{ id: string; name: string; slug?: string }> | undefined
  // Convex codegen precisa ser atualizado para tipar `machines.listAlerts`.
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  const machinesApi: any = api
  const alertsHistory = useQuery(
    machine && machinesApi?.machines?.listAlerts ? machinesApi.machines.listAlerts : "skip",
    machine && machinesApi?.machines?.listAlerts ? { machineId: machine.id as Id<"machines">, limit: 50 } : ("skip" as const)
  ) as MachineAlertEntry[] | undefined
  const machineAlertsHistory = alertsHistory ?? []
  const metadata = machine?.inventory ?? null
  const metrics = machine?.metrics ?? null
  const metricsCapturedAt = useMemo(() => getMetricsTimestamp(metrics), [metrics])
  // Live refresh the relative time label every second when we have a capture timestamp
  const [, setRelativeTick] = useState(0)
  useEffect(() => {
    if (!metricsCapturedAt) return
    const id = setInterval(() => setRelativeTick((t) => t + 1), 1000)
    return () => clearInterval(id)
  }, [metricsCapturedAt])
  const lastUpdateRelative = metricsCapturedAt ? formatRelativeTime(metricsCapturedAt) : null
  const hardware = metadata?.hardware
  const network = metadata?.network ?? null
  const networkInterfaces = Array.isArray(network) ? network : null
  const networkSummary = !Array.isArray(network) && network ? network : null
  const software = metadata?.software ?? null
  const labels = metadata?.labels ?? null
  const fleet = metadata?.fleet ?? null
  const disks = Array.isArray(metadata?.disks) ? metadata.disks : []
  const extended = metadata?.extended ?? null
  const linuxExt = extended?.linux ?? null
  const windowsExt = extended?.windows ?? null
  const macosExt = extended?.macos ?? null
  const windowsOsInfo = parseWindowsOsInfo(windowsExt?.osInfo)
  const windowsActivationStatus = windowsOsInfo?.isActivated ?? (typeof windowsOsInfo?.licenseStatus === "number" ? windowsOsInfo.licenseStatus === 1 : null)
  const windowsMemoryModulesRaw = windowsExt?.memoryModules
  const windowsVideoControllersRaw = windowsExt?.videoControllers
  const windowsDiskEntriesRaw = windowsExt?.disks
  const windowsServicesRaw = windowsExt?.services
  const windowsSoftwareRaw = windowsExt?.software
  const windowsBaseboardRaw = windowsExt?.baseboard
  const windowsBaseboard = Array.isArray(windowsBaseboardRaw)
    ? windowsBaseboardRaw[0]
    : windowsBaseboardRaw && typeof windowsBaseboardRaw === "object"
      ? windowsBaseboardRaw
      : null
  const windowsSerialNumber = windowsBaseboard ? readString(toRecord(windowsBaseboard) ?? {}, "SerialNumber", "serialNumber") : undefined
  const windowsMemoryModules = useMemo(() => {
    if (Array.isArray(windowsMemoryModulesRaw)) return windowsMemoryModulesRaw
    if (windowsMemoryModulesRaw && typeof windowsMemoryModulesRaw === "object") return [windowsMemoryModulesRaw]
    return []
  }, [windowsMemoryModulesRaw])
  const windowsVideoControllers = useMemo(() => {
    if (Array.isArray(windowsVideoControllersRaw)) return windowsVideoControllersRaw
    if (windowsVideoControllersRaw && typeof windowsVideoControllersRaw === "object") return [windowsVideoControllersRaw]
    return []
  }, [windowsVideoControllersRaw])
  const windowsDiskEntries = useMemo(() => {
    if (Array.isArray(windowsDiskEntriesRaw)) return windowsDiskEntriesRaw
    if (windowsDiskEntriesRaw && typeof windowsDiskEntriesRaw === "object") return [windowsDiskEntriesRaw]
    return []
  }, [windowsDiskEntriesRaw])
  const windowsServices = useMemo(() => {
    if (Array.isArray(windowsServicesRaw)) return windowsServicesRaw
    if (windowsServicesRaw && typeof windowsServicesRaw === "object") return [windowsServicesRaw]
    return []
  }, [windowsServicesRaw])
  const windowsSoftware = useMemo(() => {
    if (Array.isArray(windowsSoftwareRaw)) return windowsSoftwareRaw
    if (windowsSoftwareRaw && typeof windowsSoftwareRaw === "object") return [windowsSoftwareRaw]
    return []
  }, [windowsSoftwareRaw])
  const normalizedWindowsSoftware = useMemo(() => {
    return windowsSoftware
      .map((item) => normalizeWindowsSoftwareEntry(item))
      .filter((entry): entry is NormalizedSoftwareEntry => Boolean(entry))
      .sort((a, b) => {
        const aTime = a.installDate ? a.installDate.getTime() : 0
        const bTime = b.installDate ? b.installDate.getTime() : 0
        if (aTime !== bTime) return bTime - aTime
        return a.name.localeCompare(b.name, "pt-BR")
      })
  }, [windowsSoftware])
  const windowsEditionLabel = windowsOsInfo?.productName ?? windowsOsInfo?.editionId ?? null
  const windowsVersionLabel = windowsOsInfo?.displayVersion ?? windowsOsInfo?.version ?? windowsOsInfo?.releaseId ?? null
  const windowsBuildLabel = windowsOsInfo?.currentBuildNumber ?? windowsOsInfo?.currentBuild ?? null
  const windowsInstallDateLabel = windowsOsInfo?.installDate ? formatAbsoluteDateTime(windowsOsInfo.installDate) : null
  const windowsExperienceLabel = windowsOsInfo?.experience ?? null
  const windowsProductId = windowsOsInfo?.productId ?? null
  const windowsPartialProductKey = windowsOsInfo?.partialProductKey ?? null
  const windowsComputerName = windowsOsInfo?.computerName ?? hardware?.model ?? machine?.hostname ?? null
  const windowsRegisteredOwner = windowsOsInfo?.registeredOwner ?? null
  const windowsLicenseStatusLabel = (() => {
    if (windowsOsInfo?.licenseStatusText) {
      return windowsOsInfo.licenseStatusText
    }
    switch (windowsOsInfo?.licenseStatus) {
      case 0:
        return "Sem licença"
      case 1:
        return "Licenciado"
      case 2:
        return "Período inicial (OOB Grace)"
      case 3:
        return "Período exposto (OOT Grace)"
      case 4:
        return "Período não genuíno"
      case 5:
        return "Notificação"
      case 6:
        return "Período estendido"
      default:
        return null
    }
  })()
  const linuxLsblk = linuxExt?.lsblk ?? []
  const linuxSmartEntries = linuxExt?.smart ?? []
  const normalizedHardwareGpus = Array.isArray(hardware?.gpus)
    ? hardware.gpus.map((gpu) => normalizeGpuSource(gpu)).filter((gpu): gpu is GpuAdapter => Boolean(gpu))
    : []
  const hardwarePrimaryGpu = hardware?.primaryGpu ? normalizeGpuSource(hardware.primaryGpu) : null

  const windowsCpuRaw = windowsExt?.cpu
  const winCpu = windowsCpuRaw
    ? (Array.isArray(windowsCpuRaw) ? windowsCpuRaw[0] ?? null : windowsCpuRaw)
    : null
  const winMemTotal = windowsMemoryModules.reduce((acc, module) => acc + (parseBytesLike(module?.Capacity) ?? 0), 0)
  const normalizedWindowsGpus = windowsVideoControllers
    .map((controller) => normalizeGpuSource(controller))
    .filter((gpu): gpu is GpuAdapter => Boolean(gpu))
  const combinedGpus = uniqueBy(
    [
      ...(hardwarePrimaryGpu ? [hardwarePrimaryGpu] : []),
      ...normalizedHardwareGpus,
      ...normalizedWindowsGpus,
    ],
    (gpu) => `${gpu.name ?? ""}|${gpu.vendor ?? ""}|${gpu.driver ?? ""}`
  )
  const displayGpus = [...combinedGpus].sort(
    (a, b) => (b.memoryBytes ?? 0) - (a.memoryBytes ?? 0)
  )
  const primaryGpu = hardwarePrimaryGpu ?? displayGpus[0] ?? null
  const windowsPrimaryGpu = [...normalizedWindowsGpus].sort(
    (a, b) => (b.memoryBytes ?? 0) - (a.memoryBytes ?? 0)
  )[0] ?? null
  const windowsCpuDetails = windowsCpuRaw
    ? Array.isArray(windowsCpuRaw)
      ? windowsCpuRaw
      : [windowsCpuRaw]
    : []
  const winDiskStats = windowsDiskEntries.length > 0
    ? {
        count: windowsDiskEntries.length,
        total: windowsDiskEntries.reduce((acc, disk) => acc + (parseBytesLike(disk?.Size) ?? 0), 0),
      }
    : { count: 0, total: 0 }

  const lastHeartbeatDate = machine?.lastHeartbeatAt ? new Date(machine.lastHeartbeatAt) : null
  const tokenExpiry = machine?.token?.expiresAt ? new Date(machine.token.expiresAt) : null
  const tokenLastUsed = machine?.token?.lastUsedAt ? new Date(machine.token.lastUsedAt) : null

  const copyEmail = async () => {
    if (!machine?.authEmail) return
    try {
      await navigator.clipboard.writeText(machine.authEmail)
      toast.success("E-mail da máquina copiado.")
    } catch {
      toast.error("Não foi possível copiar o e-mail da máquina.")
    }
  }

  // collaborator (from machine assignment or metadata)
  type Collaborator = { email?: string; name?: string; role?: string }
  const collaborator: Collaborator | null = useMemo(() => {
    if (machine?.assignedUserEmail) {
      return {
        email: machine.assignedUserEmail ?? undefined,
        name: machine.assignedUserName ?? undefined,
        role: machine.persona ?? machine.assignedUserRole ?? undefined,
      }
    }
    if (!metadata || typeof metadata !== "object") return null
    const inv = metadata as Record<string, unknown>
    const c = inv["collaborator"]
    if (c && typeof c === "object") {
      const base = c as Record<string, unknown>
      return {
        email: typeof base.email === "string" ? base.email : undefined,
        name: typeof base.name === "string" ? base.name : undefined,
        role: typeof base.role === "string" ? (base.role as string) : undefined,
      }
    }
    return null
  }, [machine?.assignedUserEmail, machine?.assignedUserName, machine?.persona, machine?.assignedUserRole, metadata])

  const personaLabel = collaborator?.role === "manager" ? "Gestor" : "Colaborador"

  const summaryChips = useMemo(() => {
    const chips: Array<{ key: string; label: string; value: string; icon: ReactNode; tone?: "warning" | "muted" }> = []
    const osName = machine?.osName ?? "Sistema desconhecido"
    const osVersion = machine?.osVersion ?? windowsVersionLabel ?? ""
    chips.push({
      key: "os",
      label: "Sistema",
      value: [osName, osVersion].filter(Boolean).join(" ").trim(),
      icon: <OsIcon osName={machine?.osName} />,
    })
    if (machine?.architecture) {
      chips.push({
        key: "arch",
        label: "Arquitetura",
        value: machine.architecture.toUpperCase(),
        icon: <Cpu className="size-4 text-neutral-500" />,
      })
    }
    if (windowsBuildLabel) {
      chips.push({
        key: "build",
        label: "Build",
        value: windowsBuildLabel,
        icon: <ServerCog className="size-4 text-neutral-500" />,
      })
    }
    if (windowsActivationStatus !== null && windowsActivationStatus !== undefined) {
      chips.push({
        key: "activation",
        label: "Licença",
        value: windowsActivationStatus ? "Ativada" : "Não ativada",
        icon: windowsActivationStatus ? <ShieldCheck className="size-4 text-emerald-500" /> : <ShieldAlert className="size-4 text-amber-500" />,
        tone: windowsActivationStatus ? undefined : "warning",
      })
    }
    if (primaryGpu?.name) {
      chips.push({
        key: "gpu",
        label: "GPU principal",
        value: `${primaryGpu.name}${typeof primaryGpu.memoryBytes === "number" ? ` · ${formatBytes(primaryGpu.memoryBytes)}` : ""}`,
        icon: <MemoryStick className="size-4 text-neutral-500" />,
      })
    }
    if (collaborator?.email) {
      const collaboratorValue = collaborator.name ? `${collaborator.name} · ${collaborator.email}` : collaborator.email
      chips.push({
        key: "collaborator",
        label: personaLabel,
        value: collaboratorValue,
        icon: <ShieldCheck className="size-4 text-neutral-500" />,
      })
    }
    return chips
  }, [machine?.osName, machine?.osVersion, machine?.architecture, windowsVersionLabel, windowsBuildLabel, windowsActivationStatus, primaryGpu, collaborator?.email, collaborator?.name, personaLabel])

  const companyName = (() => {
    if (!companies || !machine?.companySlug) return machine?.companySlug ?? null
    const found = companies.find((c) => c.slug === machine.companySlug)
    return found?.name ?? machine.companySlug
  })()

  const [renaming, setRenaming] = useState(false)
  const [newName, setNewName] = useState<string>(machine?.hostname ?? "")

  const [openDialog, setOpenDialog] = useState(false)
  const [dialogQuery, setDialogQuery] = useState("")
  const [deleteDialog, setDeleteDialog] = useState(false)
  const [deleting, setDeleting] = useState(false)
  const [accessDialog, setAccessDialog] = useState(false)
  const [accessEmail, setAccessEmail] = useState<string>(collaborator?.email ?? "")
  const [accessName, setAccessName] = useState<string>(collaborator?.name ?? "")
  const [accessRole, setAccessRole] = useState<"collaborator" | "manager">(
    (machine?.persona === "manager" || collaborator?.role === "manager") ? "manager" : "collaborator"
  )
  const [savingAccess, setSavingAccess] = useState(false)
  const [togglingActive, setTogglingActive] = useState(false)
  const [showAllWindowsSoftware, setShowAllWindowsSoftware] = useState(false)
  const jsonText = useMemo(() => {
    const payload = {
      id: machine?.id,
      hostname: machine?.hostname,
      status: machine?.status,
      lastHeartbeatAt: machine?.lastHeartbeatAt,
      metrics,
      inventory: metadata,
      postureAlerts: machine?.postureAlerts ?? null,
      lastPostureAt: machine?.lastPostureAt ?? null,
    }
    return JSON.stringify(payload, null, 2)
  }, [machine, metrics, metadata])
  const handleDownloadInventory = useCallback(() => {
    if (!machine) return
    const safeHostname = machine.hostname.replace(/[^a-z0-9_-]/gi, "-").replace(/-{2,}/g, "-").toLowerCase()
    const fileName = `${safeHostname || "machine"}_${machine.id}.json`
    const blob = new Blob([jsonText], { type: "application/json" })
    const url = URL.createObjectURL(blob)
    const link = document.createElement("a")
    link.href = url
    link.download = fileName
    document.body.appendChild(link)
    link.click()
    document.body.removeChild(link)
    URL.revokeObjectURL(url)
  }, [jsonText, machine])

  const filteredJsonHtml = useMemo(() => {
    if (!dialogQuery.trim()) return jsonText
    const q = dialogQuery.trim().toLowerCase()
    // highlight simples
    return jsonText.replace(new RegExp(q.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "gi"), (m) => `__HIGHLIGHT__${m}__END__`)
  }, [jsonText, dialogQuery])

  // removed copy/export inventory JSON buttons as requested
  useEffect(() => {
    setAccessEmail(collaborator?.email ?? "")
    setAccessName(collaborator?.name ?? "")
    setAccessRole((machine?.persona === "manager" || collaborator?.role === "manager") ? "manager" : "collaborator")
  }, [machine?.id, machine?.persona, collaborator?.email, collaborator?.name, collaborator?.role])

  useEffect(() => {
    setShowAllWindowsSoftware(false)
  }, [machine?.id])

  const displayedWindowsSoftware = useMemo(
    () => (showAllWindowsSoftware ? normalizedWindowsSoftware : normalizedWindowsSoftware.slice(0, 12)),
    [showAllWindowsSoftware, normalizedWindowsSoftware]
  )

  const handleSaveAccess = async () => {
    if (!machine) return
    if (!accessEmail.trim()) {
      toast.error("Informe o e-mail do colaborador ou gestor.")
      return
    }
    setSavingAccess(true)
    try {
      const response = await fetch("/api/admin/machines/access", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          machineId: machine.id,
          persona: accessRole,
          email: accessEmail.trim(),
          name: accessName.trim() || undefined,
        }),
      })
      if (!response.ok) {
        throw new Error(await response.text())
      }
      toast.success("Perfil de acesso atualizado.")
      setAccessDialog(false)
    } catch (error) {
      console.error(error)
      toast.error("Falha ao atualizar acesso da máquina.")
    } finally {
      setSavingAccess(false)
    }
  }

  const handleToggleActive = async () => {
    if (!machine) return
    setTogglingActive(true)
    try {
      const response = await fetch("/api/admin/machines/toggle-active", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ machineId: machine.id, active: !isActive }),
        credentials: "include",
      })
      if (!response.ok) {
        const payload = await response.json().catch(() => ({})) as { error?: string }
        throw new Error(payload?.error ?? "Falha ao atualizar status")
      }
      toast.success(!isActive ? "Máquina reativada" : "Máquina desativada")
    } catch (error) {
      console.error(error)
      toast.error("Não foi possível atualizar o status da máquina.")
    } finally {
      setTogglingActive(false)
    }
  }

  return (
    <Card className="border-slate-200">
      <CardHeader className="gap-1">
        <CardTitle>Detalhes</CardTitle>
        <CardDescription>Resumo da máquina selecionada</CardDescription>
        {machine ? (
          <CardAction>
            <div className="flex flex-col items-end gap-2 text-xs sm:text-sm">
              {companyName ? (
                <div className="rounded-lg border border-slate-200 bg-white px-3 py-1 font-semibold text-neutral-600 shadow-sm">
                  {companyName}
                </div>
              ) : null}
              {!isDeactivated ? <MachineStatusBadge status={effectiveStatus} /> : null}
              {!isActive ? (
                <Badge variant="outline" className="h-7 border-rose-200 bg-rose-50 px-3 font-semibold uppercase text-rose-700">
                  Máquina desativada
                </Badge>
              ) : null}
            </div>
          </CardAction>
        ) : null}
      </CardHeader>
      <CardContent className="space-y-6">
        {!machine ? (
          <p className="text-sm text-muted-foreground">Selecione uma máquina para visualizar detalhes.</p>
        ) : (
          <div className="space-y-6">
            <section className="space-y-3">
              <div className="flex flex-wrap items-start gap-2">
                <div className="space-y-1">
                  <div className="flex items-center gap-2">
                    <h1 className="break-words text-2xl font-semibold text-neutral-900">{machine.hostname}</h1>
                    <Button size="icon" variant="ghost" className="size-7" onClick={() => { setNewName(machine.hostname); setRenaming(true) }}>
                      <Pencil className="size-4" />
                      <span className="sr-only">Renomear máquina</span>
                    </Button>
                  </div>
                  <p className="text-xs text-muted-foreground">
                    {machine.authEmail ?? "E-mail não definido"}
                  </p>
                </div>
              </div>
              {/* ping integrado na badge de status */}
              <div className="grid gap-3 sm:grid-cols-2 xl:grid-cols-3">
                {summaryChips.map((chip) => (
                  <InfoChip key={chip.key} label={chip.label} value={chip.value} icon={chip.icon} tone={chip.tone} />
                ))}
              </div>
              <div className="flex flex-wrap gap-2">
                {machine.authEmail ? (
                  <Button size="sm" variant="outline" onClick={copyEmail} className="gap-2 border-dashed">
                    <ClipboardCopy className="size-4" />
                    Copiar e-mail
                  </Button>
                ) : null}
                <Button size="sm" variant="outline" className="gap-2 border-dashed" onClick={() => { setAccessDialog(true) }}>
                  <ShieldCheck className="size-4" />
                  Ajustar acesso
                </Button>
                <Button
                  size="sm"
                  variant={isActive ? "outline" : "default"}
                  className={cn(
                    "gap-2 border-dashed",
                    !isActive && "bg-emerald-600 text-white hover:bg-emerald-600/90"
                  )}
                  onClick={handleToggleActive}
                  disabled={togglingActive}
                >
                  {isActive ? <Power className="size-4" /> : <PlayCircle className="size-4" />}
                  {isActive ? (togglingActive ? "Desativando..." : "Desativar") : togglingActive ? "Reativando..." : "Reativar"}
                </Button>
                {machine.registeredBy ? (
                  <Badge className="inline-flex h-9 items-center gap-2 rounded-full border border-slate-200 bg-white px-3 text-sm font-semibold text-neutral-700">
                    Registrada via {machine.registeredBy}
                  </Badge>
                ) : null}
              </div>
            </section>

            {/* Renomear máquina */}
            <Dialog open={renaming} onOpenChange={setRenaming}>
              <DialogContent>
                <DialogHeader>
                  <DialogTitle>Renomear máquina</DialogTitle>
                </DialogHeader>
                <div className="grid gap-3 py-2">
                  <Input value={newName} onChange={(e) => setNewName(e.target.value)} placeholder="Novo hostname" />
                  <div className="flex justify-end gap-2">
                    <Button variant="outline" onClick={() => setRenaming(false)}>Cancelar</Button>
                    <Button
                      onClick={async () => {
                        if (!machine) return
                        const name = (newName ?? "").trim()
                        if (name.length < 2) {
                          toast.error("Informe um nome válido")
                          return
                        }
                        try {
                          const res = await fetch("/api/admin/machines/rename", {
                            method: "POST",
                            headers: { "Content-Type": "application/json" },
                            body: JSON.stringify({ machineId: machine.id, hostname: name }),
                          })
                          if (!res.ok) throw new Error(`HTTP ${res.status}`)
                          toast.success("Máquina renomeada")
                          setRenaming(false)
                        } catch (err) {
                          console.error(err)
                          toast.error("Falha ao renomear máquina")
                        }
                      }}
                    >
                      Salvar
                    </Button>
                  </div>
                </div>
              </DialogContent>
            </Dialog>

            <Dialog open={accessDialog} onOpenChange={setAccessDialog}>
              <DialogContent>
                <DialogHeader>
                  <DialogTitle>Ajustar acesso da máquina</DialogTitle>
                </DialogHeader>
                <div className="grid gap-3 py-2">
                  <div className="grid gap-2">
                    <label className="text-sm font-medium">Perfil</label>
                    <Select value={accessRole} onValueChange={(value) => setAccessRole((value as "collaborator" | "manager") ?? "collaborator")}>
                      <SelectTrigger>
                        <SelectValue placeholder="Selecione o perfil" />
                      </SelectTrigger>
                      <SelectContent>
                        <SelectItem value="collaborator">Colaborador (portal)</SelectItem>
                        <SelectItem value="manager">Gestor (painel completo)</SelectItem>
                      </SelectContent>
                    </Select>
                  </div>
                  <div className="grid gap-2">
                    <label className="text-sm font-medium">E-mail</label>
                    <Input type="email" value={accessEmail} onChange={(e) => setAccessEmail(e.target.value)} placeholder="colaborador@empresa.com" />
                  </div>
                  <div className="grid gap-2">
                    <label className="text-sm font-medium">Nome (opcional)</label>
                    <Input value={accessName} onChange={(e) => setAccessName(e.target.value)} placeholder="Nome completo" />
                  </div>
                </div>
                <div className="flex justify-end gap-2">
                  <Button variant="outline" onClick={() => setAccessDialog(false)} disabled={savingAccess}>Cancelar</Button>
                  <Button onClick={handleSaveAccess} disabled={savingAccess || !accessEmail.trim()}>
                    {savingAccess ? "Salvando..." : "Salvar"}
                  </Button>
                </div>
              </DialogContent>
            </Dialog>

            <section className="space-y-2">
              <h4 className="text-sm font-semibold">Sincronização</h4>
              <div className="grid gap-2 text-sm text-muted-foreground">
                <div className="flex justify-between gap-4">
                  <span>Último heartbeat</span>
                  <span className="text-right font-medium text-foreground">
                    {formatRelativeTime(lastHeartbeatDate)}
                  </span>
                </div>
                <div className="flex justify-between gap-4">
                  <span>Criada em</span>
                  <span className="text-right font-medium text-foreground">{formatDate(new Date(machine.createdAt))}</span>
                </div>
                <div className="flex justify-between gap-4">
                  <span>Atualizada em</span>
                  <span className="text-right font-medium text-foreground">{formatDate(new Date(machine.updatedAt))}</span>
                </div>
                <div className="flex justify-between gap-4">
                  <span>Token expira</span>
                  <span className="text-right font-medium text-foreground">
                    {tokenExpiry ? formatRelativeTime(tokenExpiry) : "—"}
                  </span>
                </div>
                <div className="flex justify-between gap-4">
                  <span>Token usado por último</span>
                  <span className="text-right font-medium text-foreground">
                    {tokenLastUsed ? formatRelativeTime(tokenLastUsed) : "—"}
                  </span>
                </div>
                <div className="flex justify-between gap-4">
                  <span>Uso do token</span>
                  <span className="text-right font-medium text-foreground">{machine.token?.usageCount ?? 0} trocas</span>
                </div>
              </div>
            </section>

            <section className="space-y-2">
              <div className="flex flex-wrap items-center gap-2">
                <h4 className="text-sm font-semibold">Métricas recentes</h4>
                {lastUpdateRelative ? (
                  <span className="text-xs font-medium text-muted-foreground">
                    Última atualização {lastUpdateRelative}
                  </span>
                ) : null}
              </div>
              <MetricsGrid metrics={metrics} hardware={hardware} disks={disks} />
            </section>

            {hardware || network || (labels && labels.length > 0) ? (
              <section className="space-y-3">
                <div>
                  <h4 className="text-sm font-semibold">Inventário</h4>
                  <p className="text-xs text-muted-foreground">
                    Dados sincronizados via agente ou Fleet.
                  </p>
                </div>
                <div className="space-y-3 text-sm text-muted-foreground">
                  {hardware ? (
                    <div className="rounded-md border border-slate-200 bg-slate-50/60 p-3">
                      <p className="text-xs font-semibold uppercase text-slate-500">Hardware</p>
                      <div className="mt-2 grid gap-1">
                        <DetailLine label="Fabricante" value={hardware.vendor} />
                        <DetailLine label="Modelo" value={hardware.model} />
                        <DetailLine label="Número de série" value={hardware.serial} />
                        <DetailLine label="CPU" value={hardware.cpuType} />
                        <DetailLine
                          label="Núcleos"
                          value={`${hardware.physicalCores ?? "?"} físicos / ${hardware.logicalCores ?? "?"} lógicos`}
                        />
                        <DetailLine label="Memória" value={formatBytes(Number(hardware.memoryBytes ?? hardware.memory))} />
                        {displayGpus.length > 0 ? (
                          <div className="mt-2 space-y-1 text-xs text-muted-foreground">
                            <p className="font-semibold uppercase text-slate-500">GPUs</p>
                            <ul className="space-y-1">
                              {displayGpus.slice(0, 3).map((gpu, idx) => {
                                const { name, memoryBytes, driver, vendor } = gpu
                                return (
                                  <li key={`gpu-${idx}`}>
                                    <span className="font-medium text-foreground">{name ?? "Adaptador de vídeo"}</span>
                                    {memoryBytes ? <span className="ml-1 text-muted-foreground">{formatBytes(memoryBytes)}</span> : null}
                                    {vendor ? <span className="ml-1 text-muted-foreground">· {vendor}</span> : null}
                                    {driver ? <span className="ml-1 text-muted-foreground">· Driver {driver}</span> : null}
                                  </li>
                                )
                              })}
                              {displayGpus.length > 3 ? (
                                <li className="text-muted-foreground">+{displayGpus.length - 3} adaptadores adicionais</li>
                              ) : null}
                            </ul>
                          </div>
                        ) : null}
                      </div>
                    </div>
                  ) : null}

                  {networkInterfaces ? (
                    <div className="rounded-md border border-slate-200 bg-slate-50/60 p-3">
                      <p className="text-xs font-semibold uppercase text-slate-500">Rede (interfaces)</p>
                      <div className="mt-2 overflow-hidden rounded-md border border-slate-200">
                        <Table>
                          <TableHeader>
                            <TableRow className="border-slate-200 bg-slate-100/80">
                              <TableHead className="text-xs text-slate-500">Interface</TableHead>
                              <TableHead className="text-xs text-slate-500">MAC</TableHead>
                              <TableHead className="text-xs text-slate-500">IP</TableHead>
                            </TableRow>
                          </TableHeader>
                          <TableBody>
                            {networkInterfaces.map((iface, idx) => (
                              <TableRow key={`iface-${idx}`} className="border-slate-100">
                                <TableCell className="text-sm">{iface?.name ?? "—"}</TableCell>
                                <TableCell className="text-sm text-muted-foreground">{iface?.mac ?? "—"}</TableCell>
                                <TableCell className="text-sm text-muted-foreground">{iface?.ip ?? "—"}</TableCell>
                              </TableRow>
                            ))}
                          </TableBody>
                        </Table>
                      </div>
                    </div>
                  ) : networkSummary ? (
                    <div className="rounded-md border border-slate-200 bg-slate-50/60 p-3">
                      <p className="text-xs font-semibold uppercase text-slate-500">Rede</p>
                      <div className="mt-2 grid gap-1">
                        <DetailLine label="IP primário" value={networkSummary.primaryIp} />
                        <DetailLine label="IP público" value={networkSummary.publicIp} />
                        <DetailLine
                          label="MAC addresses"
                          value={
                            Array.isArray(networkSummary.macAddresses)
                              ? networkSummary.macAddresses.join(", ")
                              : machine?.macAddresses.join(", ")
                          }
                        />
                      </div>
                    </div>
                  ) : null}

                  {labels && labels.length > 0 ? (
                    <div className="rounded-md border border-slate-200 bg-slate-50/60 p-3">
                      <p className="text-xs font-semibold uppercase text-slate-500">Labels</p>
                      <div className="mt-2 flex flex-wrap gap-2">
                        {labels.slice(0, 12).map((label, index) => (
                          <Badge key={String(label.id ?? `${label.name ?? "label"}-${index}`)} variant="outline">
                            {label.name ?? `Label ${index + 1}`}
                          </Badge>
                        ))}
                        {labels.length > 12 ? (
                          <Badge variant="outline">+{labels.length - 12} outras</Badge>
                        ) : null}
                      </div>
                    </div>
                  ) : null}
                </div>
              </section>
            ) : null}

            {/* Discos (agente) */}
            {disks.length > 0 ? (
              <section className="space-y-2">
                <h4 className="text-sm font-semibold">Discos e partições</h4>
                <div className="rounded-md border border-slate-200 bg-slate-50/60">
                  <Table>
                    <TableHeader>
                      <TableRow className="border-slate-200 bg-slate-100/80">
                        <TableHead className="text-xs text-slate-500">Nome</TableHead>
                        <TableHead className="text-xs text-slate-500">Mount</TableHead>
                        <TableHead className="text-xs text-slate-500">FS</TableHead>
                        <TableHead className="text-xs text-slate-500">Capacidade</TableHead>
                        <TableHead className="text-xs text-slate-500">Livre</TableHead>
                      </TableRow>
                    </TableHeader>
                    <TableBody>
                      {disks.map((d, idx) => (
                        <TableRow key={`disk-${idx}`} className="border-slate-100">
                          <TableCell className="text-sm">{d.name ?? "—"}</TableCell>
                          <TableCell className="text-sm text-muted-foreground">{d.mountPoint ?? "—"}</TableCell>
                          <TableCell className="text-sm text-muted-foreground">{d.fs ?? "—"}</TableCell>
                          <TableCell className="text-sm text-foreground">{formatBytes(Number(d.totalBytes))}</TableCell>
                          <TableCell className="text-sm text-muted-foreground">{formatBytes(Number(d.availableBytes))}</TableCell>
                        </TableRow>
                      ))}
                    </TableBody>
                  </Table>
                </div>
              </section>
            ) : null}

            {/* Inventário estendido por SO */}
            {extended ? (
              <section className="space-y-3">
                <div>
                  <h4 className="text-sm font-semibold">Inventário estendido</h4>
                  <p className="text-xs text-muted-foreground">Dados ricos coletados pelo agente, variam por sistema operacional.</p>
                </div>

                {/* Linux */}
                {linuxExt ? (
                  <div className="space-y-3">
                    {linuxLsblk.length > 0 ? (
                      <div className="rounded-md border border-slate-200 bg-slate-50/60 p-3">
                        <p className="text-xs font-semibold uppercase text-slate-500">Montagens (lsblk)</p>
                        <div className="mt-2 overflow-hidden rounded-md border border-slate-200">
                          <Table>
                            <TableHeader>
                              <TableRow className="border-slate-200 bg-slate-100/80">
                                <TableHead className="text-xs text-slate-500">Nome</TableHead>
                                <TableHead className="text-xs text-slate-500">Ponto de montagem</TableHead>
                                <TableHead className="text-xs text-slate-500">FS</TableHead>
                                <TableHead className="text-xs text-slate-500">Tamanho</TableHead>
                              </TableRow>
                            </TableHeader>
                            <TableBody>
                              {linuxLsblk.slice(0, 18).map((entry, idx) => {
                                const name = entry.name ?? "—"
                                const mp = entry.mountPoint ?? entry.mountpoint ?? "—"
                                const fs = entry.fs ?? entry.fstype ?? "—"
                                const sizeRaw = typeof entry.sizeBytes === "number" ? entry.sizeBytes : entry.size
                                return (
                                  <TableRow key={`lsblk-${idx}`} className="border-slate-100">
                                    <TableCell className="text-sm text-foreground">{name}</TableCell>
                                    <TableCell className="text-sm text-muted-foreground">{mp || "—"}</TableCell>
                                    <TableCell className="text-sm text-muted-foreground">{fs || "—"}</TableCell>
                                    <TableCell className="text-sm text-muted-foreground">{typeof sizeRaw === "number" ? formatBytes(sizeRaw) : "—"}</TableCell>
                                  </TableRow>
                                )
                              })}
                            </TableBody>
                          </Table>
                        </div>
                      </div>
                    ) : null}
                    {linuxSmartEntries.length > 0 ? (
                      <div className="rounded-md border border-slate-200 bg-emerald-50/40 p-3 dark:bg-emerald-900/10">
                        <p className="text-xs font-semibold uppercase text-slate-500">SMART</p>
                        <div className="mt-2 grid gap-2">
                          {linuxSmartEntries.map((smartEntry, idx) => {
                            const ok = smartEntry.smart_status?.passed !== false
                            const model = smartEntry.model_name ?? smartEntry.model_family ?? "Disco"
                            const serial = smartEntry.serial_number ?? smartEntry.device?.name ?? "—"
                            return (
                              <div
                                key={`smart-${idx}`}
                                className={cn(
                                  "flex items-center justify-between gap-2 rounded-md border px-3 py-2 text-sm",
                                  ok
                                    ? "border-emerald-500/20 bg-emerald-500/15 text-emerald-700"
                                    : "border-rose-500/20 bg-rose-500/15 text-rose-700"
                                )}
                              >
                                <span className="font-medium text-foreground">
                                  {model} <span className="text-muted-foreground">({serial})</span>
                                </span>
                                <Badge variant="outline" className="text-xs uppercase">
                                  {ok ? "OK" : "ALERTA"}
                                </Badge>
                              </div>
                            )
                          })}
                        </div>
                      </div>
                    ) : null}

                    {linuxExt.lspci ? (
                      <div className="rounded-md border border-slate-200 bg-slate-50/60 p-3">
                        <p className="text-xs font-semibold uppercase text-slate-500">PCI</p>
                        <pre className="mt-2 whitespace-pre-wrap break-words text-xs text-muted-foreground">{linuxExt.lspci}</pre>
                      </div>
                    ) : null}
                    {linuxExt.lsusb ? (
                      <div className="rounded-md border border-slate-200 bg-slate-50/60 p-3">
                        <p className="text-xs font-semibold uppercase text-slate-500">USB</p>
                        <pre className="mt-2 whitespace-pre-wrap break-words text-xs text-muted-foreground">{linuxExt.lsusb}</pre>
                      </div>
                    ) : null}
                  </div>
                ) : null}

                {/* Windows */}
                {windowsExt ? (
                  <div className="space-y-3">
                    {/* Cards resumidos: CPU / RAM / GPU / Discos */}
                    <div className="grid gap-3 sm:grid-cols-2 xl:grid-cols-5">
                      <Card className="border-slate-200">
                        <CardContent className="flex items-center gap-3 py-3">
                          <Cpu className="size-5 text-slate-500" />
                          <div className="min-w-0">
                            <p className="text-xs text-muted-foreground">CPU</p>
                            <p className="break-words text-sm font-semibold text-foreground">{winCpu?.Name ?? "—"}</p>
                          </div>
                        </CardContent>
                      </Card>
                      <Card className="border-slate-200">
                        <CardContent className="flex items-center gap-3 py-3">
                          <MemoryStick className="size-5 text-slate-500" />
                          <div>
                            <p className="text-xs text-muted-foreground">Memória total</p>
                            <p className="text-sm font-semibold text-foreground">{formatBytes(winMemTotal)}</p>
                          </div>
                        </CardContent>
                      </Card>
                      <Card className="border-slate-200">
                        <CardContent className="flex items-center gap-3 py-3">
                          <Terminal className="size-5 text-slate-500" />
                          <div className="min-w-0 space-y-0.5">
                            <p className="text-xs text-muted-foreground">Windows</p>
                            <p className="break-words text-sm font-semibold text-foreground">
                              {windowsEditionLabel ?? machine?.osName ?? "—"}
                            </p>
                            <p className="break-words text-xs text-muted-foreground">
                              {windowsVersionLabel ?? windowsBuildLabel ?? "Versão desconhecida"}
                            </p>
                          </div>
                        </CardContent>
                      </Card>
                      <Card className="border-slate-200">
                        <CardContent className="flex items-center gap-3 py-3">
                          <Monitor className="size-5 text-slate-500" />
                          <div className="min-w-0 space-y-0.5">
                            <p className="text-xs text-muted-foreground">GPU</p>
                            <p className="break-words text-sm font-semibold text-foreground">
                              {(windowsPrimaryGpu ?? primaryGpu)?.name ?? "—"}
                            </p>
                          </div>
                        </CardContent>
                      </Card>
                      <Card className="border-slate-200">
                        <CardContent className="flex items-center gap-3 py-3">
                          <HardDrive className="size-5 text-slate-500" />
                          <div>
                            <p className="text-xs text-muted-foreground">Discos</p>
                            <p className="text-sm font-semibold text-foreground">{winDiskStats.count} · {formatBytes(winDiskStats.total)}</p>
                          </div>
                        </CardContent>
                      </Card>
                    </div>
                    {windowsOsInfo ? (
                      <div className="rounded-md border border-slate-200 bg-slate-50/60 p-3">
                        <p className="text-xs font-semibold uppercase text-slate-500">Informações do Windows</p>
                        <div className="mt-2 grid gap-1 text-sm text-muted-foreground">
                          <DetailLine label="Nome do dispositivo" value={windowsComputerName ?? "—"} classNameValue="break-words" />
                          <DetailLine label="Edição" value={windowsEditionLabel ?? "—"} classNameValue="break-words" />
                          <DetailLine label="Versão" value={windowsVersionLabel ?? "—"} />
                          <DetailLine label="Compilação do SO" value={windowsBuildLabel ?? "—"} />
                          <DetailLine label="Instalado em" value={windowsInstallDateLabel ?? "—"} />
                          <DetailLine label="Experiência" value={windowsExperienceLabel ?? "—"} />
                          <DetailLine label="Status da licença" value={windowsLicenseStatusLabel ?? "—"} classNameValue="break-words" />
                          <DetailLine
                            label="Ativação"
                            value={windowsActivationStatus == null ? "—" : windowsActivationStatus ? "Ativado" : "Não ativado"}
                          />
                          <DetailLine label="ID do produto" value={windowsProductId ?? "—"} classNameValue="break-words" />
                          <DetailLine label="Chave parcial" value={windowsPartialProductKey ?? "—"} />
                          <DetailLine label="Proprietário registrado" value={windowsRegisteredOwner ?? "—"} classNameValue="break-words" />
                          <DetailLine label="Número de série" value={windowsSerialNumber ?? "—"} />
                        </div>
                      </div>
                    ) : null}

                    {windowsCpuDetails.length > 0 ? (
                      <div className="rounded-md border border-slate-200 bg-slate-50/60 p-3">
                        <p className="text-xs font-semibold uppercase text-slate-500">CPU</p>
                        {windowsCpuDetails.slice(0, 1).map((cpuRecord, idx) => (
                          <div key={`cpu-${idx}`} className="mt-2 grid gap-1 text-sm text-muted-foreground">
                            <DetailLine label="Modelo" value={cpuRecord?.Name ?? "—"} classNameValue="break-words" />
                            <DetailLine label="Fabricante" value={cpuRecord?.Manufacturer ?? "—"} />
                            <DetailLine label="Socket" value={cpuRecord?.SocketDesignation ?? "—"} />
                            <DetailLine label="Núcleos" value={cpuRecord?.NumberOfCores != null ? `${cpuRecord.NumberOfCores}` : "—"} />
                            <DetailLine label="Threads" value={cpuRecord?.NumberOfLogicalProcessors != null ? `${cpuRecord.NumberOfLogicalProcessors}` : "—"} />
                            <DetailLine label="L2" value={cpuRecord?.L2CacheSize != null ? `${cpuRecord.L2CacheSize} KB` : "—"} />
                            <DetailLine label="L3" value={cpuRecord?.L3CacheSize != null ? `${cpuRecord.L3CacheSize} KB` : "—"} />
                            <DetailLine label="Clock máx" value={cpuRecord?.MaxClockSpeed != null ? `${cpuRecord.MaxClockSpeed} MHz` : "—"} />
                          </div>
                        ))}
                      </div>
                    ) : null}

                    {windowsExt.baseboard || windowsExt.bios ? (
                      <div className="rounded-md border border-slate-200 bg-slate-50/60 p-3">
                        <p className="text-xs font-semibold uppercase text-slate-500">Placa-mãe / BIOS</p>
                        <div className="mt-2 grid gap-1 text-sm text-muted-foreground">
                          {(() => {
                            const b = Array.isArray(windowsExt.baseboard) ? windowsExt.baseboard[0] : windowsExt.baseboard
                            const bios = Array.isArray(windowsExt.bios) ? windowsExt.bios[0] : windowsExt.bios
                            return (
                              <>
                                <DetailLine label="Board" value={b ? `${String(b?.["Manufacturer"] ?? "")} ${String(b?.["Product"] ?? "")}`.trim() : "—"} />
                                <DetailLine label="Board SN" value={b ? String(b?.["SerialNumber"] ?? "—") : "—"} />
                                <DetailLine label="BIOS" value={bios ? `${String(bios?.["Manufacturer"] ?? "")} ${String(bios?.["SMBIOSBIOSVersion"] ?? "")}`.trim() : "—"} />
                              </>
                            )
                          })()}
                        </div>
                      </div>
                    ) : null}
                    {windowsServices.length > 0 ? (
                      <div className="rounded-md border border-slate-200 bg-slate-50/60 p-3">
                        <p className="text-xs font-semibold uppercase text-slate-500">Serviços</p>
                        <div className="mt-2 overflow-hidden rounded-md border border-slate-200">
                          <Table>
                            <TableHeader>
                              <TableRow className="border-slate-200 bg-slate-100/80">
                                <TableHead className="text-xs text-slate-500">Nome</TableHead>
                                <TableHead className="text-xs text-slate-500">Exibição</TableHead>
                                <TableHead className="text-xs text-slate-500">Status</TableHead>
                              </TableRow>
                            </TableHeader>
                            <TableBody>
                              {windowsServices.slice(0, 10).map((service, index) => {
                                const record = toRecord(service) ?? {}
                                const name = readString(record, "Name", "name") ?? "—"
                                const displayName = readString(record, "DisplayName", "displayName") ?? "—"
                                const status = readString(record, "Status", "status") ?? "—"
                                return (
                                  <TableRow key={`svc-${index}`} className="border-slate-100">
                                    <TableCell className="text-sm">{name}</TableCell>
                                    <TableCell className="text-sm text-muted-foreground">{displayName}</TableCell>
                                    <TableCell className="text-sm text-muted-foreground">{status}</TableCell>
                                  </TableRow>
                                )
                              })}
                            </TableBody>
                          </Table>
                        </div>
                      </div>
                    ) : null}

                    {normalizedWindowsSoftware.length > 0 ? (
                      <div className="rounded-md border border-slate-200 bg-slate-50/60 p-3">
                        <div className="flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between">
                          <p className="text-xs font-semibold uppercase text-slate-500">Aplicativos instalados</p>
                          {normalizedWindowsSoftware.length > 12 ? (
                            <Button
                              type="button"
                              variant="ghost"
                              size="sm"
                              className="h-7 px-2 text-xs text-slate-600 hover:bg-slate-200/60"
                              onClick={() => setShowAllWindowsSoftware((prev) => !prev)}
                            >
                              {showAllWindowsSoftware ? "Mostrar menos" : `Ver todos (${normalizedWindowsSoftware.length})`}
                            </Button>
                          ) : null}
                        </div>
                        <ul className="mt-2 space-y-2">
                          {displayedWindowsSoftware.map((softwareItem, index) => {
                            const initials = collectInitials(softwareItem.name)
                            const installedAt = formatInstallDate(softwareItem.installDate)
                            return (
                              <li key={`sw-${index}`} className="flex items-start gap-3 rounded-md border border-slate-200 bg-white px-3 py-2">
                                <span className="mt-0.5 flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-slate-200 text-xs font-semibold uppercase text-slate-700">
                                  {initials}
                                </span>
                                <div className="flex-1 space-y-1">
                                  <div className="flex flex-wrap items-center gap-2">
                                    <span className="text-sm font-semibold text-foreground">{softwareItem.name}</span>
                                    {softwareItem.version ? (
                                      <Badge variant="outline" className="border-slate-300 bg-slate-100 text-[11px] text-slate-700">
                                        {softwareItem.version}
                                      </Badge>
                                    ) : null}
                                  </div>
                                  <div className="flex flex-wrap gap-2 text-xs text-muted-foreground">
                                    {softwareItem.publisher ? <span>{softwareItem.publisher}</span> : null}
                                    {installedAt ? <span>Instalado em {installedAt}</span> : null}
                                  </div>
                                </div>
                              </li>
                            )
                          })}
                        </ul>
                      </div>
                    ) : null}

                    {windowsMemoryModules.length > 0 ? (
                      <div className="rounded-md border border-slate-200 bg-slate-50/60 p-3">
                        <p className="text-xs font-semibold uppercase text-slate-500">Módulos de memória</p>
                        <div className="mt-2 overflow-hidden rounded-md border border-slate-200">
                          <Table>
                            <TableHeader>
                              <TableRow className="border-slate-200 bg-slate-100/80">
                                <TableHead className="text-xs text-slate-500">Banco</TableHead>
                                <TableHead className="text-xs text-slate-500">Capacidade</TableHead>
                                <TableHead className="text-xs text-slate-500">Fabricante</TableHead>
                                <TableHead className="text-xs text-slate-500">PartNumber</TableHead>
                                <TableHead className="text-xs text-slate-500">Clock</TableHead>
                              </TableRow>
                            </TableHeader>
                            <TableBody>
                              {windowsMemoryModules.map((module, idx) => {
                                const record = toRecord(module) ?? {}
                                const bank = readString(record, "BankLabel", "bankLabel") ?? "—"
                                const capacityBytes =
                                  parseBytesLike(record["Capacity"]) ?? parseBytesLike(record["capacity"]) ?? 0
                                const manufacturer = readString(record, "Manufacturer", "manufacturer") ?? "—"
                                const partNumber = readString(record, "PartNumber", "partNumber") ?? "—"
                                const clockValue = readNumber(
                                  record,
                                  "ConfiguredClockSpeed",
                                  "configuredClockSpeed",
                                  "Speed",
                                  "speed"
                                )
                                const clockLabel =
                                  typeof clockValue === "number" && Number.isFinite(clockValue)
                                    ? `${clockValue} MHz`
                                    : "—"
                                return (
                                  <TableRow key={`mem-${idx}`} className="border-slate-100">
                                    <TableCell className="text-sm">{bank}</TableCell>
                                    <TableCell className="text-sm text-muted-foreground">
                                      {capacityBytes > 0 ? formatBytes(capacityBytes) : "—"}
                                    </TableCell>
                                    <TableCell className="text-sm text-muted-foreground">{manufacturer}</TableCell>
                                    <TableCell className="text-sm text-muted-foreground">{partNumber}</TableCell>
                                    <TableCell className="text-sm text-muted-foreground">{clockLabel}</TableCell>
                                  </TableRow>
                                )
                              })}
                            </TableBody>
                          </Table>
                        </div>
                      </div>
                    ) : null}

                    {windowsVideoControllers.length > 0 ? (
                      <div className="rounded-md border border-slate-200 bg-slate-50/60 p-3">
                        <p className="text-xs font-semibold uppercase text-slate-500">Adaptadores de vídeo</p>
                        <ul className="mt-2 grid gap-1 text-xs text-muted-foreground">
                          {windowsVideoControllers.map((controller, idx) => {
                            const record = toRecord(controller) ?? {}
                            const normalized = normalizeGpuSource(record)
                            const name =
                              normalized?.name ??
                              readString(record, "Name", "name") ??
                              "—"
                            const ram =
                              normalized?.memoryBytes ??
                              parseBytesLike(record["AdapterRAM"]) ??
                              undefined
                            const driver = normalized?.driver ?? readString(record, "DriverVersion", "driverVersion")
                            const vendor = normalized?.vendor ?? readString(record, "AdapterCompatibility")
                            return (
                              <li key={`vid-${idx}`}>
                                <span className="font-medium text-foreground">{name}</span>
                                {typeof ram === "number" && ram > 0 ? <span className="ml-1">{formatBytes(ram)}</span> : null}
                                {vendor ? <span className="ml-1 text-muted-foreground">· {vendor}</span> : null}
                                {driver ? <span className="ml-1">· Driver {driver}</span> : null}
                              </li>
                            )
                          })}
                        </ul>
                      </div>
                    ) : null}

                    {windowsDiskEntries.length > 0 ? (
                      <div className="rounded-md border border-slate-200 bg-slate-50/60 p-3">
                        <p className="text-xs font-semibold uppercase text-slate-500">Discos físicos</p>
                        <div className="mt-2 overflow-hidden rounded-md border border-slate-200">
                          <Table>
                            <TableHeader>
                              <TableRow className="border-slate-200 bg-slate-100/80">
                                <TableHead className="text-xs text-slate-500">Modelo</TableHead>
                                <TableHead className="text-xs text-slate-500">Tamanho</TableHead>
                                <TableHead className="text-xs text-slate-500">Interface</TableHead>
                                <TableHead className="text-xs text-slate-500">Tipo</TableHead>
                                <TableHead className="text-xs text-slate-500">Serial</TableHead>
                              </TableRow>
                            </TableHeader>
                            <TableBody>
                              {windowsDiskEntries.map((disk, idx) => {
                                const record = toRecord(disk) ?? {}
                                const model = readString(record, "Model", "model")
                                const serial = readString(record, "SerialNumber", "serialNumber")
                                const size = parseBytesLike(record["Size"])
                                const iface = readString(record, "InterfaceType", "interfaceType")
                                const media = readString(record, "MediaType", "mediaType")
                                return (
                                  <TableRow key={`diskp-${idx}`} className="border-slate-100">
                                    <TableCell className="text-sm">{model ?? serial ?? "—"}</TableCell>
                                    <TableCell className="text-sm text-muted-foreground">
                                      {typeof size === "number" && size > 0 ? formatBytes(size) : "—"}
                                    </TableCell>
                                    <TableCell className="text-sm text-muted-foreground">{iface ?? "—"}</TableCell>
                                    <TableCell className="text-sm text-muted-foreground">{media ?? "—"}</TableCell>
                                    <TableCell className="text-sm text-muted-foreground">{serial ?? "—"}</TableCell>
                                  </TableRow>
                                )
                              })}
                            </TableBody>
                          </Table>
                        </div>
                      </div>
                    ) : null}

                    {windowsExt.defender ? (
                      <div className="rounded-md border border-slate-200 bg-slate-50/60 p-3">
                        <p className="text-xs font-semibold uppercase text-slate-500">Defender</p>
                        <div className="mt-2 flex flex-wrap gap-2 text-xs">
                          {readBool(windowsExt.defender, "AntivirusEnabled") === true ? (
                            <Badge className="gap-1 border-emerald-500/20 bg-emerald-500/15 text-emerald-700">
                              <ShieldCheck className="size-3" /> Antivírus: Ativo
                            </Badge>
                          ) : (
                            <Badge className="gap-1 border-rose-500/20 bg-rose-500/15 text-rose-700">
                              <ShieldAlert className="size-3" /> Antivírus: Inativo
                            </Badge>
                          )}
                          {readBool(windowsExt.defender, "RealTimeProtectionEnabled") === true ? (
                            <Badge className="gap-1 border-emerald-500/20 bg-emerald-500/15 text-emerald-700">
                              <ShieldCheck className="size-3" /> Proteção em tempo real: Ativa
                            </Badge>
                          ) : (
                            <Badge className="gap-1 border-rose-500/20 bg-rose-500/15 text-rose-700">
                              <ShieldAlert className="size-3" /> Proteção em tempo real: Inativa
                            </Badge>
                          )}
                        </div>
                      </div>
                    ) : null}
                  </div>
                ) : null}

                {/* macOS */}
                {macosExt ? (
                  <div className="space-y-3">
                    {Array.isArray(macosExt.packages) && macosExt.packages.length > 0 ? (
                      <div className="rounded-md border border-slate-200 bg-slate-50/60 p-3">
                        <p className="text-xs font-semibold uppercase text-slate-500">Pacotes</p>
                        <p className="mt-1 text-xs text-muted-foreground">{macosExt.packages.slice(0, 8).join(", ")}</p>
                      </div>
                    ) : null}
                    {macosExt.launchctl ? (
                      <div className="rounded-md border border-slate-200 bg-slate-50/60 p-3">
                        <p className="text-xs font-semibold uppercase text-slate-500">Launchctl</p>
                        <pre className="mt-2 whitespace-pre-wrap break-words text-xs text-muted-foreground">{macosExt.launchctl}</pre>
                      </div>
                    ) : null}
                  </div>
                ) : null}
              </section>
            ) : null}

            {/* Postura/Alertas */}
            {Array.isArray(machine?.postureAlerts) && machine?.postureAlerts?.length ? (
              <section className="space-y-2">
                <h4 className="text-sm font-semibold">Alertas de postura</h4>
                <div className="space-y-2">
                  {machine?.postureAlerts?.map((a: { kind?: string; message?: string; severity?: string }, i: number) => (
                    <div
                      key={`alert-${i}`}
                      className={cn(
                        "flex items-center justify-between rounded-md border px-3 py-2 text-sm",
                        postureSeverityClass(a?.severity)
                      )}
                    >
                      <span className="font-medium text-foreground">{a?.message ?? formatPostureAlertKind(a?.kind)}</span>
                      <Badge variant="outline">{formatPostureAlertKind(a?.kind)}</Badge>
                    </div>
                  ))}
                </div>
                <p className="text-xs text-muted-foreground">
                  Última avaliação: {machine?.lastPostureAt ? formatRelativeTime(new Date(machine.lastPostureAt)) : "—"}
                </p>
              </section>
            ) : null}

            <section className="space-y-2">
              <div className="flex items-center justify-between">
                <h4 className="text-sm font-semibold">Histórico de alertas</h4>
                {machineAlertsHistory.length > 0 ? (
                  <span className="text-xs text-muted-foreground">
                    Últimos {machineAlertsHistory.length} {machineAlertsHistory.length === 1 ? "evento" : "eventos"}
                  </span>
                ) : null}
              </div>
              {machineAlertsHistory.length > 0 ? (
                <div className="relative max-h-64 overflow-y-auto pr-2">
                  <div className="absolute left-3 top-3 bottom-3 w-px bg-slate-200" />
                  <ol className="space-y-3 pl-6">
                    {machineAlertsHistory.map((alert) => {
                      const date = new Date(alert.createdAt)
                      return (
                        <li key={alert.id} className="relative rounded-md border border-slate-200/80 bg-white px-3 py-2 text-xs shadow-sm">
                          <span className="absolute -left-5 top-3 inline-flex size-3 items-center justify-center rounded-full border border-white bg-slate-200 ring-2 ring-white" />
                          <div className={cn("flex items-center justify-between", postureSeverityClass(alert.severity))}>
                            <span className="text-xs font-medium uppercase tracking-wide text-slate-600">{formatPostureAlertKind(alert.kind)}</span>
                            <span className="text-xs text-slate-500">{formatRelativeTime(date)}</span>
                          </div>
                          <p className="mt-1 text-sm text-foreground">{alert.message ?? formatPostureAlertKind(alert.kind)}</p>
                          <p className="mt-1 text-[11px] text-muted-foreground">{format(date, "dd/MM/yyyy HH:mm:ss")}</p>
                        </li>
                      )
                    })}
                  </ol>
                </div>
              ) : (
                <p className="text-xs text-muted-foreground">Nenhum alerta registrado para esta máquina.</p>
              )}
            </section>

            <div className="flex flex-wrap gap-2 pt-2">
              {Array.isArray(software) && software.length > 0 ? (
                <Button size="sm" variant="outline" onClick={() => exportCsv(software, "softwares.csv")}>Softwares CSV</Button>
              ) : null}
              {Array.isArray(metadata?.services) && metadata.services.length > 0 ? (
                <Button size="sm" variant="outline" onClick={() => exportCsv(metadata.services as Array<Record<string, unknown>>, "servicos.csv")}>Serviços CSV</Button>
              ) : null}
            </div>
            {fleet ? (
              <section className="space-y-2 text-sm text-muted-foreground">
                <Separator />
                <div className="flex items-center justify-between">
                  <span>ID Fleet</span>
                  <span className="font-medium text-foreground">{fleet.id ?? "—"}</span>
                </div>
                <div className="flex items-center justify-between">
                  <span>Team ID</span>
                  <span className="font-medium text-foreground">{fleet.teamId ?? "—"}</span>
                </div>
                <div className="flex items-center justify-between">
                  <span>Detalhes atualizados</span>
                  <span className="font-medium text-foreground">
                    {fleet.detailUpdatedAt ? formatDate(new Date(String(fleet.detailUpdatedAt))) : "—"}
                  </span>
                </div>
                <div className="flex items-center justify-between">
                  <span>Versão osquery</span>
                  <span className="font-medium text-foreground">{fleet.osqueryVersion ?? "—"}</span>
                </div>
              </section>
            ) : null}

            {software && software.length > 0 ? (
              <section className="space-y-2">
                <h4 className="text-sm font-semibold">Softwares detectados</h4>
                <div className="rounded-md border border-slate-200 bg-slate-50/60">
                  <Table>
                    <TableHeader>
                      <TableRow className="border-slate-200 bg-slate-100/80">
                        <TableHead className="text-xs text-slate-500">Nome</TableHead>
                        <TableHead className="text-xs text-slate-500">Versão</TableHead>
                        <TableHead className="text-xs text-slate-500">Fonte</TableHead>
                      </TableRow>
                    </TableHeader>
                    <TableBody>
                      {software.slice(0, 6).map((item, index) => (
                        <TableRow key={`${item.name ?? "software"}-${index}`} className="border-slate-100">
                          <TableCell className="text-sm text-foreground">{item.name ?? "—"}</TableCell>
                          <TableCell className="text-sm text-muted-foreground">{item.version ?? "—"}</TableCell>
                          <TableCell className="text-sm text-muted-foreground">{item.source ?? "—"}</TableCell>
                        </TableRow>
                      ))}
                    </TableBody>
                  </Table>
                  {software.length > 6 ? (
                    <p className="px-3 py-2 text-xs text-muted-foreground">
                      +{software.length - 6} softwares adicionais sincronizados via Fleet.
                    </p>
                  ) : null}
                </div>
              </section>
            ) : null}

            {machine ? (
              <section className="space-y-2 rounded-md border border-rose-200 bg-rose-50/60 p-3">
                <div className="space-y-1">
                  <h4 className="text-sm font-semibold text-rose-700">Zona perigosa</h4>
                  <p className="text-xs text-rose-600">
                    Excluir a máquina revoga o token atual e remove os dados de inventário sincronizados.
                  </p>
                </div>
                <Button variant="destructive" size="sm" onClick={() => setDeleteDialog(true)}>Excluir máquina</Button>
              </section>
            ) : null}

            <Dialog open={openDialog} onOpenChange={setOpenDialog}>
              <div className="flex justify-end">
                <DialogTrigger asChild>
                  <Button size="sm" variant="outline" onClick={() => setOpenDialog(true)}>Inventário completo</Button>
                </DialogTrigger>
              </div>
              <DialogContent className="max-w-3xl">
                <DialogHeader>
                  <DialogTitle>Inventário completo — {machine.hostname}</DialogTitle>
                </DialogHeader>
                <div className="space-y-2">
                  <div className="flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between">
                    <Input
                      placeholder="Buscar no JSON"
                      value={dialogQuery}
                      onChange={(e) => setDialogQuery(e.target.value)}
                      className="sm:flex-1"
                    />
                    <Button
                      type="button"
                      variant="outline"
                      size="sm"
                      onClick={handleDownloadInventory}
                      className="inline-flex items-center gap-2"
                    >
                      <Download className="size-4" /> Baixar JSON
                    </Button>
                  </div>
                  <div className="max-h-[60vh] overflow-auto rounded-md border border-slate-200 bg-slate-50/60 p-3 text-xs">
                    <pre className="whitespace-pre-wrap break-words text-muted-foreground" dangerouslySetInnerHTML={{ __html: filteredJsonHtml
                      .replaceAll("__HIGHLIGHT__", '<mark class="bg-yellow-200 text-foreground">')
                      .replaceAll("__END__", '</mark>')
                    }} />
                  </div>
                </div>
              </DialogContent>
            </Dialog>

            <Dialog open={deleteDialog} onOpenChange={(open) => { if (!open) setDeleting(false); setDeleteDialog(open) }}>
              <DialogContent>
                <DialogHeader>
                  <DialogTitle>Excluir máquina</DialogTitle>
                </DialogHeader>
                <div className="space-y-3 text-sm text-muted-foreground">
                  <p>Tem certeza que deseja excluir <span className="font-semibold text-foreground">{machine?.hostname}</span>? Esta ação não pode ser desfeita.</p>
                  <p>Os tokens ativos serão revogados e o inventário deixará de aparecer no painel.</p>
                  <div className="flex justify-end gap-2">
                    <Button variant="outline" onClick={() => setDeleteDialog(false)} disabled={deleting}>Cancelar</Button>
                    <Button
                      variant="destructive"
                      disabled={deleting}
                      onClick={async () => {
                        if (!machine) return
                        setDeleting(true)
                        try {
                          const res = await fetch("/api/admin/machines/delete", {
                            method: "POST",
                            headers: { "Content-Type": "application/json" },
                            body: JSON.stringify({ machineId: machine.id }),
                            credentials: "include",
                          })
                          if (!res.ok) throw new Error(`HTTP ${res.status}`)
                          toast.success("Máquina excluída")
                          setDeleteDialog(false)
                          router.push("/admin/machines")
                        } catch (err) {
                          console.error(err)
                          toast.error("Falha ao excluir máquina")
                        } finally {
                          setDeleting(false)
                        }
                      }}
                    >
                      {deleting ? "Excluindo..." : "Excluir máquina"}
                    </Button>
                  </div>
                </div>
              </DialogContent>
            </Dialog>
          </div>
        )}
      </CardContent>
    </Card>
  )
}

function MachinesGrid({ machines, companyNameBySlug }: { machines: MachinesQueryItem[]; companyNameBySlug: Map<string, string> }) {
  if (!machines || machines.length === 0) return <EmptyState />
  return (
    <div className="grid grid-cols-1 gap-3 [@supports(display:grid)]:grid-cols-[repeat(auto-fit,minmax(280px,1fr))]">
      {machines.map((m) => (
        <MachineCard
          key={m.id}
          machine={m}
          companyName={m.companySlug ? companyNameBySlug.get(m.companySlug) ?? m.companySlug : null}
        />
      ))}
    </div>
  )
}

function MachineCard({ machine, companyName }: { machine: MachinesQueryItem; companyName?: string | null }) {
  const effectiveStatus = resolveMachineStatus(machine)
  const isActive = machine.isActive
  const lastHeartbeat = machine.lastHeartbeatAt ? new Date(machine.lastHeartbeatAt) : null
  type AgentMetrics = {
    memoryUsedBytes?: number
    memoryTotalBytes?: number
    memoryUsedPercent?: number
    cpuUsagePercent?: number
  }
  const mm = (machine.metrics ?? null) as unknown as AgentMetrics | null
  const memUsed = mm?.memoryUsedBytes ?? NaN
  const memTotal = mm?.memoryTotalBytes ?? NaN
  const memPct = mm?.memoryUsedPercent ?? (Number.isFinite(memUsed) && Number.isFinite(memTotal) ? (Number(memUsed) / Number(memTotal)) * 100 : NaN)
  const cpuPct = mm?.cpuUsagePercent ?? NaN
  const collaborator = (() => {
    if (machine.assignedUserEmail) {
      return {
        email: machine.assignedUserEmail ?? undefined,
        name: machine.assignedUserName ?? undefined,
        role: machine.persona ?? machine.assignedUserRole ?? undefined,
      }
    }
    const inv = machine.inventory as unknown
    if (!inv || typeof inv !== "object") return null
    const raw = (inv as Record<string, unknown>).collaborator
    if (!raw || typeof raw !== "object") return null
    const obj = raw as Record<string, unknown>
    const email = typeof obj.email === "string" ? obj.email : undefined
    if (!email) return null
    return {
      email,
      name: typeof obj.name === "string" ? obj.name : undefined,
      role: typeof obj.role === "string" ? (obj.role as string) : undefined,
    }
  })()
  const persona = collaborator?.role === "manager" ? "Gestor" : "Colaborador"
  const companyLabel = companyName ?? machine.companySlug ?? null

  return (
    <Link href={`/admin/machines/${machine.id}`} className="group">
      <Card className={cn("relative h-full overflow-hidden border-slate-200 transition-colors hover:border-slate-300", !isActive && "border-slate-300 bg-slate-50") }>
        <div className="absolute right-2 top-2">
          <span
            aria-hidden
            className={cn(
              "relative block size-2 rounded-full",
              effectiveStatus === "online"
                ? "bg-emerald-500"
                : effectiveStatus === "offline"
                  ? "bg-rose-500"
                  : effectiveStatus === "maintenance"
                    ? "bg-amber-500"
                    : effectiveStatus === "blocked"
                      ? "bg-orange-500"
                      : effectiveStatus === "deactivated"
                        ? "bg-slate-500"
                        : "bg-slate-400"
            )}
          />
          {effectiveStatus === "online" ? (
            <span className="absolute left-1/2 top-1/2 -z-10 size-4 -translate-x-1/2 -translate-y-1/2 rounded-full bg-emerald-400/30 animate-ping" />
          ) : null}
        </div>
        <CardHeader className="pb-2">
          <CardTitle className="line-clamp-1 flex items-center gap-2 text-base font-semibold">
            <Monitor className="size-4 text-slate-500" /> {machine.hostname}
          </CardTitle>
          <CardDescription className="line-clamp-1 text-xs">{machine.authEmail ?? "—"}</CardDescription>
          {!isActive ? (
            <Badge variant="outline" className="mt-2 w-fit border-rose-200 bg-rose-50 text-[10px] font-semibold uppercase tracking-wide text-rose-700">
              Desativada
            </Badge>
          ) : null}
        </CardHeader>
        <CardContent className="flex grow flex-col gap-3 text-sm">
          <div className="flex flex-wrap items-center gap-2">
            <Badge variant="outline" className="border-slate-300 bg-slate-100 text-xs font-medium text-slate-700">
              {machine.osName ?? "SO"} {machine.osVersion ?? ""}
            </Badge>
            {machine.architecture ? (
              <Badge variant="outline" className="border-slate-300 bg-slate-100 text-xs font-medium text-slate-700">
                {machine.architecture.toUpperCase()}
              </Badge>
            ) : null}
            {companyLabel ? (
              <Badge variant="outline" className="text-xs">{companyLabel}</Badge>
            ) : null}
          </div>
          {collaborator?.email ? (
            <p className="text-[11px] text-muted-foreground">
              {persona}: {collaborator.name ? `${collaborator.name} · ` : ""}
              {collaborator.email}
            </p>
          ) : null}
          <div className="grid grid-cols-2 gap-2">
            <div className="flex items-center gap-2 rounded-md border border-slate-200 bg-slate-50/80 px-2 py-1.5">
              <Cpu className="size-4 text-slate-500" />
              <span className="text-xs font-medium text-slate-800">{formatPercent(cpuPct)}</span>
            </div>
            <div className="flex items-center gap-2 rounded-md border border-slate-200 bg-slate-50/80 px-2 py-1.5">
              <MemoryStick className="size-4 text-slate-500" />
              <span className="text-xs font-medium text-slate-800">
                {Number.isFinite(memUsed) && Number.isFinite(memTotal)
                  ? `${formatBytes(memUsed)} / ${formatBytes(memTotal)}`
                  : formatPercent(memPct)}
              </span>
            </div>
          </div>
          <div className="mt-auto flex items-center justify-between text-xs text-muted-foreground">
            <span className="flex items-center gap-1.5">
              <HardDrive className="size-3.5 text-slate-500" />
              {Array.isArray(machine.inventory?.disks) ? `${machine.inventory?.disks?.length ?? 0} discos` : "—"}
            </span>
            <span>
              {lastHeartbeat ? formatRelativeTime(lastHeartbeat) : "sem heartbeat"}
            </span>
          </div>
        </CardContent>
      </Card>
    </Link>
  )
}

function DetailLine({ label, value, classNameValue }: DetailLineProps) {
  if (value === null || value === undefined) return null
  if (typeof value === "string" && (value.trim() === "" || value === "undefined" || value === "null")) {
    return null
  }
  return (
    <div className="flex items-center justify-between gap-4">
      <span>{label}</span>
      <span className={cn("text-right font-medium text-foreground", classNameValue)}>{value}</span>
    </div>
  )
}

function InfoChip({ label, value, icon, tone = "default" }: { label: string; value: string; icon?: ReactNode; tone?: "default" | "warning" | "muted" }) {
  const toneClasses =
    tone === "warning"
      ? "border-amber-200 bg-amber-50 text-amber-700"
      : tone === "muted"
        ? "border-slate-200 bg-slate-50 text-neutral-600"
        : "border-slate-200 bg-white text-neutral-800"

  return (
    <div className={cn("flex items-center gap-3 rounded-xl border px-3 py-2 shadow-sm", toneClasses)}>
      {icon ? <span className="text-neutral-500">{icon}</span> : null}
      <div className="min-w-0 leading-tight">
        <p className="text-xs uppercase text-neutral-500">{label}</p>
        <p className="truncate text-sm font-semibold">{value}</p>
      </div>
    </div>
  )
}

function clampPercent(raw: number): number {
  if (!Number.isFinite(raw)) return 0
  const normalized = raw > 1 && raw <= 100 ? raw : raw <= 1 ? raw * 100 : raw
  return Math.max(0, Math.min(100, normalized))
}

function deriveUsageMetrics({
  metrics,
  hardware,
  disks,
}: {
  metrics: MachineMetrics
  hardware?: MachineInventory["hardware"]
  disks?: MachineInventory["disks"]
}) {
  const data = (metrics ?? {}) as Record<string, unknown>

  const cpuRaw = Number(
    data.cpuUsagePercent ?? data.cpuUsage ?? data.cpu_percent ?? data.cpu ?? NaN
  )
  const cpuPercent = Number.isFinite(cpuRaw) ? clampPercent(cpuRaw) : null

  const totalCandidates = [
    data.memoryTotalBytes,
    data.memory_total,
    data.memoryTotal,
    hardware?.memoryBytes,
    hardware?.memory,
  ]
  let memoryTotalBytes: number | null = null
  for (const candidate of totalCandidates) {
    const parsed = parseBytesLike(candidate)
    if (parsed && Number.isFinite(parsed) && parsed > 0) {
      memoryTotalBytes = parsed
      break
    }
    const numeric = Number(candidate)
    if (Number.isFinite(numeric) && numeric > 0) {
      memoryTotalBytes = numeric
      break
    }
  }

  const usedCandidates = [
    data.memoryUsedBytes,
    data.memoryBytes,
    data.memory_used,
    data.memory,
  ]
  let memoryUsedBytes: number | null = null
  for (const candidate of usedCandidates) {
    const parsed = parseBytesLike(candidate)
    if (parsed !== undefined && Number.isFinite(parsed)) {
      memoryUsedBytes = parsed
      break
    }
    const numeric = Number(candidate)
    if (Number.isFinite(numeric)) {
      memoryUsedBytes = numeric
      break
    }
  }

  const memoryPercentRaw = Number(data.memoryUsedPercent ?? data.memory_percent ?? NaN)
  let memoryPercent = Number.isFinite(memoryPercentRaw) ? clampPercent(memoryPercentRaw) : null
  if (memoryTotalBytes && memoryUsedBytes === null && memoryPercent !== null) {
    memoryUsedBytes = (memoryPercent / 100) * memoryTotalBytes
  } else if (memoryTotalBytes && memoryUsedBytes !== null) {
    memoryPercent = clampPercent((memoryUsedBytes / memoryTotalBytes) * 100)
  }

  let diskTotalBytes: number | null = null
  let diskUsedBytes: number | null = null
  let diskPercent: number | null = null
  if (Array.isArray(disks) && disks.length > 0) {
    let total = 0
    let available = 0
    disks.forEach((disk) => {
      const totalParsed = parseBytesLike(disk?.totalBytes)
      if (typeof totalParsed === "number" && Number.isFinite(totalParsed) && totalParsed > 0) {
        total += totalParsed
      }
      const availableParsed = parseBytesLike(disk?.availableBytes)
      if (typeof availableParsed === "number" && Number.isFinite(availableParsed) && availableParsed >= 0) {
        available += availableParsed
      }
    })
    if (total > 0) {
      diskTotalBytes = total
      const used = Math.max(0, total - available)
      diskUsedBytes = used
      diskPercent = clampPercent((used / total) * 100)
    }
  }
  if (diskPercent === null) {
    const diskMetric = Number(
      data.diskUsage ?? data.disk ?? data.diskUsedPercent ?? data.storageUsedPercent ?? NaN
    )
    if (Number.isFinite(diskMetric)) {
      diskPercent = clampPercent(diskMetric)
    }
  }

  const gpuMetric = Number(
    data.gpuUsagePercent ?? data.gpuUsage ?? data.gpu_percent ?? data.gpu ?? NaN
  )
  const gpuPercent = Number.isFinite(gpuMetric) ? clampPercent(gpuMetric) : null

  return {
    cpuPercent,
    memoryUsedBytes,
    memoryTotalBytes,
    memoryPercent,
    diskPercent,
    diskUsedBytes,
    diskTotalBytes,
    gpuPercent,
  }
}

function MetricsGrid({ metrics, hardware, disks }: { metrics: MachineMetrics; hardware?: MachineInventory["hardware"]; disks?: MachineInventory["disks"] }) {
  const derived = useMemo(
    () => deriveUsageMetrics({ metrics, hardware, disks }),
    [metrics, hardware, disks]
  )

  const cards = [
    {
      key: "cpu",
      label: "CPU",
      percent: derived.cpuPercent,
      primaryText: derived.cpuPercent !== null ? formatPercent(derived.cpuPercent) : "Sem dados",
      secondaryText: derived.cpuPercent !== null ? "Uso instantâneo" : "Sem leituras recentes",
      icon: <Cpu className="size-4 text-neutral-500" />,
      color: "var(--chart-1)",
    },
    {
      key: "memory",
      label: "Memória",
      percent: derived.memoryPercent,
      primaryText:
        derived.memoryUsedBytes !== null && derived.memoryTotalBytes !== null
          ? `${formatBytes(derived.memoryUsedBytes)} / ${formatBytes(derived.memoryTotalBytes)}`
          : derived.memoryPercent !== null
            ? formatPercent(derived.memoryPercent)
            : "Sem dados",
      secondaryText: derived.memoryPercent !== null ? `${Math.round(derived.memoryPercent)}% em uso` : null,
      icon: <MemoryStick className="size-4 text-neutral-500" />,
      color: "var(--chart-2)",
    },
    {
      key: "disk",
      label: "Disco",
      percent: derived.diskPercent,
      primaryText:
        derived.diskUsedBytes !== null && derived.diskTotalBytes !== null
          ? `${formatBytes(derived.diskUsedBytes)} / ${formatBytes(derived.diskTotalBytes)}`
          : derived.diskPercent !== null
            ? formatPercent(derived.diskPercent)
            : "Sem dados",
      secondaryText: derived.diskPercent !== null ? `${Math.round(derived.diskPercent)}% utilizado` : null,
      icon: <HardDrive className="size-4 text-neutral-500" />,
      color: "var(--chart-3)",
    },
  ] as Array<{ key: string; label: string; percent: number | null; primaryText: string; secondaryText?: string | null; icon: ReactNode; color: string }>

  if (derived.gpuPercent !== null) {
    cards.push({
      key: "gpu",
      label: "GPU",
      percent: derived.gpuPercent,
      primaryText: formatPercent(derived.gpuPercent),
      secondaryText: null,
      icon: <Monitor className="size-4 text-neutral-500" />,
      color: "var(--chart-4)",
    })
  }

  return (
    <div className="grid gap-3 md:grid-cols-2 xl:grid-cols-3">
      {cards.map((card) => {
        const percentValue = Number.isFinite(card.percent ?? NaN) ? Math.max(0, Math.min(100, card.percent ?? 0)) : 0
        const percentLabel = card.percent !== null ? `${Math.round(card.percent)}%` : "—"
        return (
          <div key={card.key} className="flex items-center gap-4 rounded-xl border border-slate-200 bg-white px-4 py-3 shadow-sm">
            <div className="relative h-24 w-24">
              <ChartContainer
                config={{ usage: { label: card.label, color: card.color } }}
                className="h-24 w-24 aspect-square"
              >
                <RadialBarChart
                  data={[{ name: card.label, value: percentValue }]}
                  innerRadius="68%"
                  outerRadius="100%"
                  startAngle={90}
                  endAngle={-270}
                >
                  <PolarAngleAxis type="number" domain={[0, 100]} tick={false} />
                  <RadialBar dataKey="value" cornerRadius={10} fill="var(--color-usage)" background />
                </RadialBarChart>
              </ChartContainer>
              <div className="pointer-events-none absolute inset-[18%] flex items-center justify-center rounded-full bg-white/70 text-sm font-semibold text-neutral-900">
                {percentLabel}
              </div>
            </div>
            <div className="flex min-w-0 flex-1 flex-col gap-1">
              <div className="flex items-center gap-2 text-sm font-semibold text-neutral-900">
                {card.icon}
                {card.label}
              </div>
              <div className="text-sm text-neutral-700">{card.primaryText}</div>
              {card.secondaryText ? (
                <div className="text-xs text-neutral-500">{card.secondaryText}</div>
              ) : null}
            </div>
          </div>
        )
      })}
    </div>
  )
}

function exportCsv(items: Array<Record<string, unknown>>, filename: string) {
  if (!Array.isArray(items) || items.length === 0) return
  const headersSet = new Set<string>()
  items.forEach((it) => Object.keys(it ?? {}).forEach((k) => headersSet.add(k)))
  const headers = Array.from(headersSet)
  const csv = [headers.join(",")]
  for (const it of items) {
    const row = headers
      .map((h) => {
        const v = (it as Record<string, unknown>)[h]
        if (v === undefined || v === null) return ""
        const s = typeof v === "string" ? v : JSON.stringify(v)
        return `"${s.replace(/"/g, '""')}"`
      })
      .join(",")
    csv.push(row)
  }
  const blob = new Blob([csv.join("\n")], { type: "text/csv;charset=utf-8;" })
  const url = URL.createObjectURL(blob)
  const a = document.createElement("a")
  a.href = url
  a.download = filename
  document.body.appendChild(a)
  a.click()
  a.remove()
  URL.revokeObjectURL(url)
}
