"use client"

import Link from "next/link"
import { useCallback, useEffect, useMemo, useState, useTransition } from "react"
import { IconSearch, IconUserPlus, IconTrash, IconAlertTriangle, IconPencil } from "@tabler/icons-react"

import { toast } from "sonner"

import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import { Checkbox } from "@/components/ui/checkbox"
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select"
import {
  Pagination,
  PaginationContent,
  PaginationItem,
  PaginationLink,
  PaginationNext,
  PaginationPrevious,
} from "@/components/ui/pagination"
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table"
import { Sheet, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle } from "@/components/ui/sheet"
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
import { useQuery } from "convex/react"
import { api } from "@/convex/_generated/api"
import { useAuth } from "@/lib/auth-client"
import { ROLE_OPTIONS, type RoleOption } from "@/lib/authz"
import { canReactivateInvite as canReactivateInvitePolicy } from "@/lib/invite-policies"
import { SearchableCombobox, type SearchableComboboxOption } from "@/components/ui/searchable-combobox"

type AdminRole = RoleOption | "machine"
const NO_COMPANY_ID = "__none__"

type AdminUser = {
  id: string
  email: string
  name: string
  role: AdminRole
  tenantId: string
  createdAt: string
  updatedAt: string | null
  companyId: string | null
  companyName: string | null
  machinePersona: string | null
}

type AdminInvite = {
  id: string
  email: string
  name: string | null
  role: RoleOption
  tenantId: string
  status: "pending" | "accepted" | "revoked" | "expired"
  token: string
  inviteUrl: string
  expiresAt: string
  createdAt: string
  createdById: string | null
  acceptedAt: string | null
  acceptedById: string | null
  revokedAt: string | null
  revokedById: string | null
  revokedReason: string | null
}

type CompanyOption = {
  id: string
  name: string
}

type AdminUsersTab = "team" | "users" | "invites"

type Props = {
  initialUsers: AdminUser[]
  initialInvites: AdminInvite[]
  roleOptions: readonly AdminRole[]
  defaultTenantId: string
  viewerRole: string
  visibleTabs?: readonly AdminUsersTab[]
  defaultTab?: AdminUsersTab
}

const ROLE_LABELS: Record<string, string> = {
  admin: "Administrador",
  manager: "Gestor",
  agent: "Agente",
  collaborator: "Colaborador",
  machine: "Agente de dispositivo",
}

function formatRole(role: string) {
  const key = role?.toLowerCase?.() ?? ""
  return ROLE_LABELS[key] ?? role
}

function formatMachinePersona(persona: string | null | undefined) {
  const normalized = persona?.toLowerCase?.() ?? ""
  if (normalized === "manager") return "Gestor"
  if (normalized === "collaborator") return "Colaborador"
  return "Sem persona"
}

function machinePersonaBadgeVariant(persona: string | null | undefined) {
  const normalized = persona?.toLowerCase?.() ?? ""
  if (normalized === "manager") return "secondary" as const
  if (normalized === "collaborator") return "outline" as const
  return "outline" as const
}

const ALL_TABS: AdminUsersTab[] = ["team", "users", "invites"]
const DEFAULT_KEEP_EMAILS = ["renan.pac@paulicon.com.br"]

// Tenant removido da UI (sem exibição)

function formatDate(dateIso: string) {
  const date = new Date(dateIso)
  return new Intl.DateTimeFormat("pt-BR", {
    dateStyle: "medium",
    timeStyle: "short",
  }).format(date)
}

function formatStatus(status: AdminInvite["status"]) {
  switch (status) {
    case "pending":
      return "Pendente"
    case "accepted":
      return "Aceito"
    case "revoked":
      return "Revogado"
    case "expired":
      return "Expirado"
    default:
      return status
  }
}

function inviteStatusVariant(status: AdminInvite["status"]) {
  switch (status) {
    case "pending":
      return "secondary" as const
    case "accepted":
      return "default" as const
    case "revoked":
      return "destructive" as const
    default:
      return "outline" as const
  }
}

function sanitizeInvite(invite: AdminInvite & { events?: unknown }): AdminInvite {
  const { events: unusedEvents, ...rest } = invite
  void unusedEvents
  return rest
}

function coerceRole(role: AdminRole | string | null | undefined): RoleOption {
  const candidate = (role ?? "agent").toLowerCase()
  return (ROLE_OPTIONS as readonly string[]).includes(candidate) ? (candidate as RoleOption) : "agent"
}

function extractMachineId(email: string): string | null {
  const match = /^machine-(.+)@machines\.local$/i.exec(email.trim())
  return match ? match[1] : null
}

function isRestrictedRole(role?: string | null) {
  const normalized = (role ?? "").toLowerCase()
  return normalized === "admin" || normalized === "agent"
}

export function AdminUsersManager({
  initialUsers,
  initialInvites,
  roleOptions,
  defaultTenantId,
  viewerRole,
  visibleTabs,
  defaultTab,
}: Props) {
  const { convexUserId, session } = useAuth()
  const [users, setUsers] = useState<AdminUser[]>(initialUsers)
  const [invites, setInvites] = useState<AdminInvite[]>(initialInvites)
  const [companies, setCompanies] = useState<CompanyOption[]>([])

  const [email, setEmail] = useState("")
  const [name, setName] = useState("")
  const [role, setRole] = useState<RoleOption>("agent")
  const [tenantId, setTenantId] = useState(defaultTenantId)
  const [expiresInDays, setExpiresInDays] = useState("7")
  const [lastInviteLink, setLastInviteLink] = useState<string | null>(null)
  const [revokingId, setRevokingId] = useState<string | null>(null)
  const [reactivatingId, setReactivatingId] = useState<string | null>(null)
  const [isPending, startTransition] = useTransition()

  const [linkEmail, setLinkEmail] = useState("")
  const [linkCompanyId, setLinkCompanyId] = useState("")
  const [assigningCompany, setAssigningCompany] = useState(false)

  const [editUserId, setEditUserId] = useState<string | null>(null)
  const editUser = useMemo(() => users.find((user) => user.id === editUserId) ?? null, [users, editUserId])
  const [editForm, setEditForm] = useState({
    name: "",
    email: "",
    role: "agent" as RoleOption,
    tenantId: defaultTenantId,
    companyId: "",
  })
  const [isSavingUser, setIsSavingUser] = useState(false)
  const [isResettingPassword, setIsResettingPassword] = useState(false)
  const [passwordPreview, setPasswordPreview] = useState<string | null>(null)
  const [deleteUserId, setDeleteUserId] = useState<string | null>(null)
  const deleteTarget = useMemo(
    () => users.find((candidate) => candidate.id === deleteUserId) ?? null,
    [users, deleteUserId]
  )
  const [isDeletingUser, setIsDeletingUser] = useState(false)
  const [revokeDialogInviteId, setRevokeDialogInviteId] = useState<string | null>(null)
  const revokeCandidate = useMemo(
    () => invites.find((invite) => invite.id === revokeDialogInviteId) ?? null,
    [invites, revokeDialogInviteId]
  )
  const viewerRoleNormalized = viewerRole?.toLowerCase?.() ?? "agent"
  const viewerIsAdmin = viewerRoleNormalized === "admin"
  const viewerEmail = session?.user?.email?.toLowerCase() ?? null

  const tabs = useMemo<AdminUsersTab[]>(() => {
    const source = visibleTabs && visibleTabs.length > 0 ? Array.from(new Set(visibleTabs)) : ALL_TABS
    return source.filter((value): value is AdminUsersTab => ALL_TABS.includes(value))
  }, [visibleTabs])

  const initialTabValue = useMemo<AdminUsersTab>(() => {
    if (tabs.length === 0) {
      return "team"
    }
    if (defaultTab && tabs.includes(defaultTab)) {
      return defaultTab
    }
    if (tabs.includes("team")) {
      return "team"
    }
    return tabs[0]
  }, [tabs, defaultTab])

  const [tab, setTab] = useState<AdminUsersTab>(initialTabValue)

  useEffect(() => {
    if (!tabs.includes(tab)) {
      setTab(tabs[0] ?? "team")
    }
  }, [tabs, tab])
  const canManageUser = useCallback((role?: string | null) => viewerIsAdmin || !isRestrictedRole(role), [viewerIsAdmin])
  const canManageInvite = useCallback((role: RoleOption) => viewerIsAdmin || !["admin", "agent"].includes(role), [viewerIsAdmin])

  const normalizedRoles = useMemo<readonly AdminRole[]>(() => {
    return (roleOptions && roleOptions.length > 0 ? roleOptions : ROLE_OPTIONS) as readonly AdminRole[]
  }, [roleOptions])
  const selectableRoles = useMemo(() => {
    const unique = new Set<RoleOption>()
    normalizedRoles.forEach((roleOption) => {
      const coerced = coerceRole(roleOption)
      if (!viewerIsAdmin && isRestrictedRole(coerced)) return
      unique.add(coerced)
    })
    return Array.from(unique)
  }, [normalizedRoles, viewerIsAdmin])

  // Split users: team (admin/agent) and people (manager/collaborator); exclude machines
  const teamUsers = useMemo(
    () => users.filter((user) => user.role !== "machine" && ["admin", "agent"].includes(coerceRole(user.role))),
    [users],
  )
  const peopleUsers = useMemo(
    () => users.filter((user) => user.role !== "machine" && ["manager", "collaborator"].includes(coerceRole(user.role))),
    [users],
  )
  const machineUsers = useMemo(() => users.filter((user) => user.role === "machine"), [users])

  const teamRoleFilterOptions = useMemo<SearchableComboboxOption[]>(() => {
    const teamRoles = selectableRoles.filter((option) => ["admin", "agent"].includes(option))
    return [
      { value: "all", label: "Todos os papéis" },
      ...teamRoles.map((option) => ({ value: option, label: formatRole(option) })),
    ]
  }, [selectableRoles])

  const usersTypeFilterOptions = useMemo<SearchableComboboxOption[]>(
    () => [
      { value: "all", label: "Todos" },
      { value: "people", label: "Pessoas" },
      { value: "machines", label: "Dispositivos" },
    ],
    [],
  )

  const companyFilterOptions = useMemo<SearchableComboboxOption[]>(
    () => [
      { value: "all", label: "Todas as empresas" },
      ...companies.map((company) => ({ value: company.id, label: company.name })),
    ],
    [companies],
  )

  const defaultCreateRole: RoleOption = selectableRoles[0] ?? "agent"
  // Equipe
  const [teamSearch, setTeamSearch] = useState("")
  const [teamRoleFilter, setTeamRoleFilter] = useState<"all" | RoleOption>("all")
  const [teamCompanyFilter, setTeamCompanyFilter] = useState<string>("all")
  // Removido: filtro por espaço (tenant)
  const [teamSelection, setTeamSelection] = useState<Set<string>>(new Set())
  const [isBulkDeletingTeam, setIsBulkDeletingTeam] = useState(false)
  const [bulkDeleteTeamOpen, setBulkDeleteTeamOpen] = useState(false)
  // Removidos filtros antigos de Pessoas/Dispositivos (agora unificado)
  // Unificado (pessoas + dispositivos)
  const [usersSearch, setUsersSearch] = useState("")
  const [usersTypeFilter, setUsersTypeFilter] = useState<"all" | "people" | "machines">("people")
  const [usersCompanyFilter, setUsersCompanyFilter] = useState<string>("all")
  // Removido: filtro por espaço (tenant)
  const [usersSelection, setUsersSelection] = useState<Set<string>>(new Set())
  const [isBulkDeletingUsersCombined, setIsBulkDeletingUsersCombined] = useState(false)
  const [bulkDeleteUsersCombinedOpen, setBulkDeleteUsersCombinedOpen] = useState(false)
  const [createDialogOpen, setCreateDialogOpen] = useState(false)
  const [createForm, setCreateForm] = useState({
    name: "",
    email: "",
    role: defaultCreateRole,
    tenantId: defaultTenantId,
    companyId: NO_COMPANY_ID,
  })
  const [isCreatingUser, setIsCreatingUser] = useState(false)
  const [createPassword, setCreatePassword] = useState<string | null>(null)
  const [cleanupDialogOpen, setCleanupDialogOpen] = useState(false)
  const [cleanupKeepEmails, setCleanupKeepEmails] = useState(DEFAULT_KEEP_EMAILS.join(", "))
  const [cleanupPending, setCleanupPending] = useState(false)

  const buildKeepEmailSet = useCallback(() => {
    const keep = new Set<string>()
    DEFAULT_KEEP_EMAILS.forEach((email) => keep.add(email.toLowerCase()))
    if (viewerEmail) {
      keep.add(viewerEmail)
    }
    cleanupKeepEmails
      .split(",")
      .map((entry) => entry.trim().toLowerCase())
      .filter(Boolean)
      .forEach((email) => keep.add(email))
    return keep
  }, [cleanupKeepEmails, viewerEmail])

  const cleanupPreview = useMemo(() => Array.from(buildKeepEmailSet()).join(", "), [buildKeepEmailSet])

  // Dispositivos (para listar vínculos por usuário)
  type MachinesListItem = {
    id: string
    hostname?: string
    assignedUserEmail?: string | null
    metadata?: unknown
    linkedUsers?: Array<{ id: string; email: string; name: string }>
  }
  const machinesList = useQuery(
    api.devices.listByTenant,
    convexUserId ? { tenantId: defaultTenantId, includeMetadata: true } : "skip"
  ) as MachinesListItem[] | undefined

  const machinesByUserEmail = useMemo(() => {
    const map = new Map<string, Array<{ id: string; hostname?: string }>>()
    ;(machinesList ?? []).forEach((m) => {
      const push = (email?: string | null) => {
        const e = (email ?? '').toLowerCase()
        if (!e) return
        const arr = map.get(e) ?? []
        arr.push({ id: m.id, hostname: m.hostname })
        map.set(e, arr)
      }
      push(m.assignedUserEmail)
      // metadata collaborator
      if (m.metadata && typeof m.metadata === 'object') {
        const rec = m.metadata as Record<string, unknown>
        const c = rec['collaborator']
        if (c && typeof c === 'object') {
          const base = c as Record<string, unknown>
          if (typeof base.email === 'string') push(base.email)
        }
      }
      // linked users
      if (Array.isArray(m.linkedUsers)) {
        m.linkedUsers.forEach((lu) => push(lu.email))
      }
    })
    return map
  }, [machinesList])

  // Tenant removido da UI

  const filteredTeamUsers = useMemo(() => {
    const term = teamSearch.trim().toLowerCase()
    return teamUsers.filter((user) => {
      if (teamCompanyFilter !== "all" && user.companyId !== teamCompanyFilter) return false
      // filtro por espaço removido
      if (teamRoleFilter !== "all" && coerceRole(user.role) !== teamRoleFilter) return false
      if (!term) return true
      const haystack = [
        user.name ?? "",
        user.email ?? "",
        user.companyName ?? "",
        formatRole(user.role),
      ]
        .join(" ")
        .toLowerCase()
      return haystack.includes(term)
    })
  }, [teamUsers, teamSearch, teamRoleFilter, teamCompanyFilter])

  // Removido: lista específica de Pessoas (uso substituído pelo unificado)

  // Removido: filtro específico de agentes (uso substituído pelo unificado)

  const combinedBaseUsers = useMemo(() => {
    if (usersTypeFilter === "people") return peopleUsers
    if (usersTypeFilter === "machines") return machineUsers
    return [...peopleUsers, ...machineUsers]
  }, [peopleUsers, machineUsers, usersTypeFilter])

  const filteredCombinedUsers = useMemo(() => {
    const term = usersSearch.trim().toLowerCase()
    return combinedBaseUsers.filter((user) => {
      if (usersCompanyFilter !== "all" && user.companyId !== usersCompanyFilter) return false
      // filtro por espaço removido
      if (!term) return true
      const persona = (user.machinePersona ?? "").toLowerCase()
      const machineId = extractMachineId(user.email) ?? ""
      const haystack = [
        user.name ?? "",
        user.email ?? "",
        user.companyName ?? "",
        formatRole(user.role),
        persona,
        machineId,
      ]
        .join(" ")
        .toLowerCase()
      return haystack.includes(term)
    })
  }, [combinedBaseUsers, usersSearch, usersCompanyFilter])

  const [teamPageSize, setTeamPageSize] = useState<number>(10)
  const [teamPageIndex, setTeamPageIndex] = useState<number>(0)
  const teamTotal = filteredTeamUsers.length
  const teamPageCount = Math.max(1, Math.ceil(teamTotal / teamPageSize))
  const teamPaginated = useMemo(
    () => filteredTeamUsers.slice(teamPageIndex * teamPageSize, teamPageIndex * teamPageSize + teamPageSize),
    [filteredTeamUsers, teamPageIndex, teamPageSize]
  )
  const teamStart = teamTotal === 0 ? 0 : teamPageIndex * teamPageSize + 1
  const teamEnd = teamTotal === 0 ? 0 : Math.min(teamTotal, teamPageIndex * teamPageSize + teamPageSize)

  useEffect(() => {
    setTeamPageIndex(0)
  }, [teamSearch, teamRoleFilter, teamCompanyFilter])

  useEffect(() => {
    if (teamPageIndex > teamPageCount - 1) {
      setTeamPageIndex(Math.max(0, teamPageCount - 1))
    }
  }, [teamPageIndex, teamPageCount])

  const [usersPageSize, setUsersPageSize] = useState<number>(10)
  const [usersPageIndex, setUsersPageIndex] = useState<number>(0)
  const usersTotal = filteredCombinedUsers.length
  const usersPageCount = Math.max(1, Math.ceil(usersTotal / usersPageSize))
  const usersPaginated = useMemo(
    () =>
      filteredCombinedUsers.slice(
        usersPageIndex * usersPageSize,
        usersPageIndex * usersPageSize + usersPageSize
      ),
    [filteredCombinedUsers, usersPageIndex, usersPageSize]
  )
  const usersStart = usersTotal === 0 ? 0 : usersPageIndex * usersPageSize + 1
  const usersEnd = usersTotal === 0 ? 0 : Math.min(usersTotal, usersPageIndex * usersPageSize + usersPageSize)

  useEffect(() => {
    setUsersPageIndex(0)
  }, [usersSearch, usersTypeFilter, usersCompanyFilter])

  useEffect(() => {
    if (usersPageIndex > usersPageCount - 1) {
      setUsersPageIndex(Math.max(0, usersPageCount - 1))
    }
  }, [usersPageIndex, usersPageCount])

  const [invitesPageSize, setInvitesPageSize] = useState<number>(10)
  const [invitesPageIndex, setInvitesPageIndex] = useState<number>(0)
  const invitesTotal = invites.length
  const invitesPageCount = Math.max(1, Math.ceil(invitesTotal / invitesPageSize))
  const paginatedInvites = useMemo(
    () => invites.slice(invitesPageIndex * invitesPageSize, invitesPageIndex * invitesPageSize + invitesPageSize),
    [invites, invitesPageIndex, invitesPageSize]
  )
  const invitesStart = invitesTotal === 0 ? 0 : invitesPageIndex * invitesPageSize + 1
  const invitesEnd =
    invitesTotal === 0 ? 0 : Math.min(invitesTotal, invitesPageIndex * invitesPageSize + invitesPageSize)

  useEffect(() => {
    setInvitesPageIndex(0)
  }, [invitesTotal])

  useEffect(() => {
    if (invitesPageIndex > invitesPageCount - 1) {
      setInvitesPageIndex(Math.max(0, invitesPageCount - 1))
    }
  }, [invitesPageIndex, invitesPageCount])

  useEffect(() => {
    void (async () => {
      try {
        const response = await fetch("/api/admin/companies", { credentials: "include" })
        const json = (await response.json()) as { companies?: CompanyOption[] }
        const mapped = (json.companies ?? []).map((company) => ({ id: company.id, name: company.name }))
        setCompanies(mapped)
        if (mapped.length > 0 && !linkCompanyId) {
          setLinkCompanyId(mapped[0].id)
        }
      } catch (error) {
        console.error("Falha ao carregar empresas", error)
      }
    })()
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [])

  useEffect(() => {
    if (!editUser) {
      setEditForm({ name: "", email: "", role: "agent", tenantId: defaultTenantId, companyId: "" })
      setPasswordPreview(null)
      return
    }

    setEditForm({
      name: editUser.name || "",
      email: editUser.email,
      role: coerceRole(editUser.role),
      tenantId: editUser.tenantId || defaultTenantId,
      companyId: editUser.companyId ?? "",
    })
    setPasswordPreview(null)
  }, [editUser, defaultTenantId])

  const linkedMachinesForEditUser = useMemo(() => {
    if (!editUser || !machinesList) return [] as Array<{ id: string; hostname?: string }>
    const email = (editUser.email ?? "").toLowerCase()
    const results: Array<{ id: string; hostname?: string }> = []
    machinesList.forEach((m) => {
      const assigned = (m.assignedUserEmail ?? "").toLowerCase()
      let collaboratorEmail = ""
      if (m.metadata && typeof m.metadata === "object") {
        const rec = m.metadata as Record<string, unknown>
        const c = rec["collaborator"]
        if (c && typeof c === "object") {
          const base = c as Record<string, unknown>
          if (typeof base.email === "string") collaboratorEmail = base.email.toLowerCase()
        }
      }
      const linked = Array.isArray(m.linkedUsers)
        ? m.linkedUsers.some((lu) => (lu.email ?? '').toLowerCase() === email)
        : false
      if (assigned === email || (collaboratorEmail && collaboratorEmail === email) || linked) {
        results.push({ id: m.id, hostname: m.hostname })
      }
    })
    return results
  }, [editUser, machinesList])
  useEffect(() => {
    setCreateForm((prev) => ({
      ...prev,
      role: defaultCreateRole,
      tenantId: defaultTenantId,
    }))
  }, [defaultCreateRole, defaultTenantId])


  async function handleInviteSubmit(event: React.FormEvent<HTMLFormElement>) {
    event.preventDefault()
    const normalizedEmail = email.trim().toLowerCase()
    if (!normalizedEmail || !normalizedEmail.includes("@")) {
      toast.error("Informe um e-mail válido")
      return
    }

    const payload = {
      email: normalizedEmail,
      name: name.trim(),
      role,
      tenantId,
      expiresInDays: Number.parseInt(expiresInDays, 10),
    }

    startTransition(async () => {
      try {
        const response = await fetch("/api/admin/invites", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify(payload),
        })

        if (!response.ok) {
          const data = await response.json().catch(() => ({}))
          throw new Error(data.error ?? "Não foi possível gerar o convite")
        }

        const data = (await response.json()) as { invite: AdminInvite }
        const nextInvite = sanitizeInvite(data.invite)
        setInvites((previous) => [nextInvite, ...previous.filter((item) => item.id !== nextInvite.id)])
        setEmail("")
        setName("")
        setRole("agent")
        setTenantId(defaultTenantId)
        setExpiresInDays("7")
        setLastInviteLink(nextInvite.inviteUrl)
        toast.success("Convite criado com sucesso")
      } catch (error) {
        const message = error instanceof Error ? error.message : "Falha ao criar convite"
        toast.error(message)
      }
    })
  }

  function handleCopy(link: string) {
    navigator.clipboard
      .writeText(link)
      .then(() => toast.success("Link de convite copiado"))
      .catch(() => toast.error("Não foi possível copiar o link"))
  }

  async function handleRevokeConfirmed() {
    if (!revokeCandidate || revokeCandidate.status !== "pending") {
      setRevokeDialogInviteId(null)
      return
    }

    if (!canManageInvite(revokeCandidate.role)) {
      toast.error("Você não pode revogar convites deste papel")
      setRevokeDialogInviteId(null)
      return
    }

    setRevokingId(revokeCandidate.id)
    try {
      const response = await fetch(`/api/admin/invites/${revokeCandidate.id}`, {
        method: "PATCH",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ reason: "Revogado manualmente" }),
      })

      if (!response.ok) {
        const data = await response.json().catch(() => ({}))
        throw new Error(data.error ?? "Falha ao revogar convite")
      }

      const data = (await response.json()) as { invite: AdminInvite }
      const updated = sanitizeInvite(data.invite)
      setInvites((previous) => previous.map((item) => (item.id === updated.id ? updated : item)))
      toast.success("Convite revogado")
    } catch (error) {
      const message = error instanceof Error ? error.message : "Erro ao revogar convite"
      toast.error(message)
    } finally {
      setRevokingId(null)
      setRevokeDialogInviteId(null)
    }
  }

  async function handleReactivate(invite: AdminInvite) {
    if (!canReactivateInvitePolicy(invite)) return
    if (!canManageInvite(invite.role)) {
      toast.error("Você não pode reativar convites deste papel")
      return
    }
    setReactivatingId(invite.id)
    try {
      const response = await fetch(`/api/admin/invites/${invite.id}`, {
        method: "PATCH",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ action: "reactivate" }),
      })
      if (!response.ok) {
        const data = await response.json().catch(() => ({}))
        throw new Error(data.error ?? "Falha ao reativar convite")
      }
      const data = (await response.json()) as { invite: AdminInvite }
      const normalized = sanitizeInvite(data.invite)
      setInvites((previous) => previous.map((item) => (item.id === normalized.id ? normalized : item)))
      toast.success("Convite reativado")
    } catch (error) {
      const message = error instanceof Error ? error.message : "Não foi possível reativar"
      toast.error(message)
    } finally {
      setReactivatingId(null)
    }
  }

  const handleCleanupConfirm = useCallback(async () => {
    if (cleanupPending) return
    const keepSet = buildKeepEmailSet()
    setCleanupPending(true)
    toast.loading("Limpando dados antigos...", { id: "cleanup-users" })
    try {
      const response = await fetch("/api/admin/users/cleanup", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ keepEmails: Array.from(keepSet) }),
      })
      if (!response.ok) {
        const data = await response.json().catch(() => ({}))
        throw new Error(data.error ?? "Não foi possível remover os dados antigos.")
      }
      const summary = (await response.json()) as {
        removedPortalUserIds: string[]
        removedPortalEmails: string[]
        removedConvexUserIds: string[]
        removedTicketIds: string[]
        keepEmails: string[]
      }
      setUsers((previous) => previous.filter((user) => !summary.removedPortalUserIds.includes(user.id)))
      setUsersSelection((previous) => {
        if (previous.size === 0) return previous
        const next = new Set(previous)
        summary.removedPortalUserIds.forEach((id) => next.delete(id))
        return next
      })
      setCleanupKeepEmails(Array.from(keepSet).join(", "))
      toast.success("Dados de teste removidos.", { id: "cleanup-users" })
      setCleanupDialogOpen(false)
    } catch (error) {
      const message = error instanceof Error ? error.message : "Não foi possível remover os dados antigos."
      toast.error(message, { id: "cleanup-users" })
    } finally {
      setCleanupPending(false)
    }
  }, [buildKeepEmailSet, cleanupPending, setUsersSelection])

  async function handleAssignCompany(event: React.FormEvent<HTMLFormElement>) {
    event.preventDefault()
    const normalizedEmail = linkEmail.trim().toLowerCase()
    if (!normalizedEmail || !normalizedEmail.includes("@")) {
      toast.error("Informe um e-mail válido para vincular")
      return
    }
    if (!linkCompanyId) {
      toast.error("Selecione a empresa para vincular")
      return
    }

    setAssigningCompany(true)
    toast.loading("Vinculando colaborador...", { id: "assign-company" })
    try {
      const response = await fetch("/api/admin/users/assign-company", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ email: normalizedEmail, companyId: linkCompanyId }),
        credentials: "include",
      })
      if (!response.ok) {
        const data = await response.json().catch(() => ({}))
        throw new Error(data.error ?? "Falha ao vincular")
      }
      toast.success("Colaborador vinculado com sucesso", { id: "assign-company" })
      setLinkEmail("")
      setLinkCompanyId("")
    } catch (error) {
      const message = error instanceof Error ? error.message : "Não foi possível vincular"
      toast.error(message, { id: "assign-company" })
    } finally {
      setAssigningCompany(false)
    }
  }

  const resetCreateForm = useCallback(() => {
    setCreateForm({
      name: "",
      email: "",
      role: defaultCreateRole,
      tenantId: defaultTenantId,
      companyId: NO_COMPANY_ID,
    })
    setCreatePassword(null)
  }, [defaultCreateRole, defaultTenantId])

  const handleOpenCreateUser = useCallback(() => {
    resetCreateForm()
    setCreateDialogOpen(true)
  }, [resetCreateForm])

  const handleCloseCreateDialog = useCallback(() => {
    resetCreateForm()
    setCreateDialogOpen(false)
  }, [resetCreateForm])

  async function handleCreateUser(event: React.FormEvent<HTMLFormElement>) {
    event.preventDefault()

    const payload = {
      name: createForm.name.trim(),
      email: createForm.email.trim().toLowerCase(),
      role: createForm.role,
      tenantId: createForm.tenantId.trim() || defaultTenantId,
    }

    if (!payload.name) {
      toast.error("Informe o nome do usuário")
      return
    }
    if (!payload.email || !payload.email.includes("@")) {
      toast.error("Informe um e-mail válido")
      return
    }

    setIsCreatingUser(true)
    setCreatePassword(null)
    try {
      const response = await fetch("/api/admin/users", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        credentials: "include",
        body: JSON.stringify(payload),
      })

      if (!response.ok) {
        const data = await response.json().catch(() => ({}))
        throw new Error(data.error ?? "Não foi possível criar o usuário")
      }

      const data = (await response.json()) as { user: { id: string; email: string; name: string | null; role: string; tenantId: string | null; createdAt: string }; temporaryPassword: string }
      const normalizedRole = coerceRole(data.user.role)
      const normalizedUser: AdminUser = {
        id: data.user.id,
        email: data.user.email,
        name: data.user.name ?? data.user.email,
        role: normalizedRole,
        tenantId: data.user.tenantId ?? defaultTenantId,
        createdAt: data.user.createdAt,
        updatedAt: null,
        companyId: null,
        companyName: null,
        machinePersona: null,
      }

      if (createForm.companyId && createForm.companyId !== NO_COMPANY_ID) {
        try {
          const assignResponse = await fetch("/api/admin/users/assign-company", {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            credentials: "include",
            body: JSON.stringify({ email: normalizedUser.email, companyId: createForm.companyId }),
          })
          if (assignResponse.ok) {
            const company = companies.find((company) => company.id === createForm.companyId)
            normalizedUser.companyId = createForm.companyId
            normalizedUser.companyName = company?.name ?? null
          } else {
            const assignData = await assignResponse.json().catch(() => ({}))
            toast.error(assignData.error ?? "Não foi possível vincular a empresa")
          }
        } catch (error) {
          const message = error instanceof Error ? error.message : "Falha ao vincular empresa"
          toast.error(message)
        }
      }

      setUsers((previous) => [normalizedUser, ...previous])
      setCreatePassword(data.temporaryPassword)
      toast.success("Usuário criado com sucesso")
      setCreateForm((prev) => ({
        ...prev,
        name: "",
        email: "",
        companyId: NO_COMPANY_ID,
      }))
    } catch (error) {
      const message = error instanceof Error ? error.message : "Erro ao criar usuário"
      toast.error(message)
    } finally {
      setIsCreatingUser(false)
    }
  }

  // Bulk selection helpers
  const selectedTeamUsers = useMemo(() => filteredTeamUsers.filter((u) => teamSelection.has(u.id)), [filteredTeamUsers, teamSelection])
  const allTeamSelected = selectedTeamUsers.length > 0 && selectedTeamUsers.length === filteredTeamUsers.length
  const someTeamSelected = selectedTeamUsers.length > 0 && !allTeamSelected

  // Removido: seleção específica de Pessoas (uso substituído pelo unificado)

  // Removido: seleção específica de Dispositivos (uso substituído pelo unificado)

  const [inviteSelection, setInviteSelection] = useState<Set<string>>(new Set())
  const selectedInvites = useMemo(() => invites.filter((i) => inviteSelection.has(i.id)), [invites, inviteSelection])
  const allInvitesSelected = selectedInvites.length > 0 && selectedInvites.length === invites.length
  const someInvitesSelected = selectedInvites.length > 0 && !allInvitesSelected
  const [isBulkRevokingInvites, setIsBulkRevokingInvites] = useState(false)
  const [bulkRevokeInvitesOpen, setBulkRevokeInvitesOpen] = useState(false)

  function toggleTeamSelectAll(checked: boolean) {
    setTeamSelection(checked ? new Set(filteredTeamUsers.map((u) => u.id)) : new Set())
  }
  // Removidos: toggles de seleção específicos (uso substituído pelo unificado)
  function toggleInvitesSelectAll(checked: boolean) {
    setInviteSelection(checked ? new Set(invites.map((i) => i.id)) : new Set())
  }

  function toggleUsersCombinedSelectAll(checked: boolean) {
    setUsersSelection(checked ? new Set(filteredCombinedUsers.map((u) => u.id)) : new Set())
  }

  async function performBulkDeleteUsers(ids: string[]) {
    if (ids.length === 0) return
    const tasks = ids.map(async (id) => {
      const user = users.find((u) => u.id === id)
      if (!user) return
      if (!canManageUser(user.role)) return
      const response = await fetch(`/api/admin/users/${id}`, { method: "DELETE", credentials: "include" })
      if (!response.ok) {
        const data = await response.json().catch(() => ({}))
        throw new Error(data.error ?? `Falha ao remover ${user.email}`)
      }
    })
    await Promise.allSettled(tasks)
    setUsers((prev) => prev.filter((u) => !ids.includes(u.id)))
  }

  async function performBulkDeleteMachines(ids: string[]) {
    if (ids.length === 0) return
    const tasks = ids.map(async (id) => {
      const user = users.find((u) => u.id === id)
      if (!user) return
      const machineId = extractMachineId(user.email)
      if (!machineId) return
      const response = await fetch(`/api/admin/devices/delete`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        credentials: "include",
        body: JSON.stringify({ machineId }),
      })
      if (!response.ok) {
        const data = await response.json().catch(() => ({}))
        throw new Error(data.error ?? `Falha ao remover agente ${user.email}`)
      }
    })
    await Promise.allSettled(tasks)
    setUsers((prev) => prev.filter((u) => !ids.includes(u.id)))
  }

  async function performBulkRevokeInvites(ids: string[]) {
    if (ids.length === 0) return
    const tasks = ids.map(async (id) => {
      const invite = invites.find((i) => i.id === id)
      if (!invite) return
      if (!canManageInvite(invite.role)) return
      const response = await fetch(`/api/admin/invites/${id}`, {
        method: "PATCH",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ reason: "Revogado em massa" }),
      })
      if (!response.ok) {
        const data = await response.json().catch(() => ({}))
        throw new Error(data.error ?? `Falha ao revogar ${invite.email}`)
      }
    })
    await Promise.allSettled(tasks)
    setInvites((prev) => prev.map((i) => (ids.includes(i.id) && i.status === "pending" ? { ...i, status: "revoked", revokedAt: new Date().toISOString() } : i)))
  }

  async function performBulkDeleteUsersCombined(ids: string[]) {
    if (ids.length === 0) return
    const machineIds: string[] = []
    const humanIds: string[] = []
    ids.forEach((id) => {
      const u = users.find((x) => x.id === id)
      if (!u) return
      if (u.role === "machine") machineIds.push(id)
      else humanIds.push(id)
    })
    await Promise.allSettled([
      performBulkDeleteMachines(machineIds),
      performBulkDeleteUsers(humanIds),
    ])
  }

  async function handleSaveUser(event: React.FormEvent<HTMLFormElement>) {
    event.preventDefault()
    if (!editUser) return

    const payload = {
      name: editForm.name.trim(),
      email: editForm.email.trim().toLowerCase(),
      role: editForm.role,
      tenantId: editForm.tenantId.trim() || defaultTenantId,
      companyId: editForm.companyId || null,
    }

    if (!payload.name) {
      toast.error("Informe o nome do usuário")
      return
    }
    if (!payload.email || !payload.email.includes("@")) {
      toast.error("Informe um e-mail válido")
      return
    }

    setIsSavingUser(true)
    try {
      const response = await fetch(`/api/admin/users/${editUser.id}`, {
        method: "PATCH",
        headers: { "Content-Type": "application/json" },
        credentials: "include",
        body: JSON.stringify(payload),
      })

      if (!response.ok) {
        const data = await response.json().catch(() => ({}))
        throw new Error(data.error ?? "Não foi possível atualizar o usuário")
      }

      const data = (await response.json()) as { user: AdminUser }
      setUsers((previous) => previous.map((item) => (item.id === data.user.id ? data.user : item)))
      toast.success("Usuário atualizado com sucesso")
      setEditUserId(null)
    } catch (error) {
      const message = error instanceof Error ? error.message : "Erro ao salvar alterações"
      toast.error(message)
    } finally {
      setIsSavingUser(false)
    }
  }

  async function handleResetPassword() {
    if (!editUser) return
    if (!canManageUser(editUser.role)) {
      toast.error("Você não pode gerar senha para este usuário")
      return
    }
    setIsResettingPassword(true)
    toast.loading("Gerando nova senha...", { id: "reset-password" })
    try {
      const response = await fetch(`/api/admin/users/${editUser.id}/reset-password`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        credentials: "include",
      })
      if (!response.ok) {
        const data = await response.json().catch(() => ({}))
        throw new Error(data.error ?? "Falha ao gerar nova senha")
      }
      const data = (await response.json()) as { temporaryPassword: string }
      setPasswordPreview(data.temporaryPassword)
      toast.success("Senha temporária criada", { id: "reset-password" })
    } catch (error) {
      const message = error instanceof Error ? error.message : "Erro ao gerar senha"
      toast.error(message, { id: "reset-password" })
    } finally {
      setIsResettingPassword(false)
    }
  }

  const isMachineEditing = editUser?.role === "machine"
  const editingRestricted = editUser ? !canManageUser(editUser.role) : false
  const companyOptions = useMemo(
    () => [{ id: NO_COMPANY_ID, name: "Sem empresa vinculada" }, ...companies],
    [companies]
  )
async function handleDeleteUser() {
    if (!deleteTarget) return
    if (!canManageUser(deleteTarget.role)) {
      toast.error("Você não pode remover esse usuário")
      setDeleteUserId(null)
      return
    }
    setIsDeletingUser(true)
    const isMachine = deleteTarget.role === "machine"

    try {
      if (isMachine) {
        const machineId = extractMachineId(deleteTarget.email)
        if (!machineId) {
          throw new Error("Não foi possível identificar a dispositivo associada.")
        }
        const response = await fetch("/api/admin/devices/delete", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ machineId }),
          credentials: "include",
        })
        if (!response.ok) {
          const data = await response.json().catch(() => ({}))
          throw new Error(data.error ?? "Falha ao remover agente de dispositivo")
        }
        toast.success("Agente de dispositivo removido")
      } else {
        const response = await fetch(`/api/admin/users/${deleteTarget.id}`, {
          method: "DELETE",
          credentials: "include",
        })
        if (!response.ok) {
          const data = await response.json().catch(() => ({}))
          throw new Error(data.error ?? "Falha ao remover colaborador")
        }
        toast.success("Colaborador removido")
      }

      setUsers((previous) => previous.filter((user) => user.id !== deleteTarget.id))
      if (editUserId === deleteTarget.id) {
        setEditUserId(null)
      }
    } catch (error) {
      const message = error instanceof Error ? error.message : "Não foi possível remover o usuário"
      toast.error(message)
    } finally {
      setIsDeletingUser(false)
      setDeleteUserId(null)
    }
  }

  return (
    <>
      <Tabs value={tab} onValueChange={(value) => setTab(value as AdminUsersTab)} className="w-full">
        <TabsList className="h-12 w-full justify-start rounded-xl bg-slate-100 p-1">
          {tabs.includes("team") ? (
            <TabsTrigger value="team" className="rounded-lg">
              Equipe
            </TabsTrigger>
          ) : null}
          {tabs.includes("users") ? (
            <TabsTrigger value="users" className="rounded-lg">
              Usuários
            </TabsTrigger>
          ) : null}
          {tabs.includes("invites") ? (
            <TabsTrigger value="invites" className="rounded-lg">
              Convites
            </TabsTrigger>
          ) : null}
        </TabsList>

        {tabs.includes("team") ? (
        <TabsContent value="team" className="mt-6 space-y-6">
          <div className="flex flex-col gap-4 rounded-xl border border-slate-200 bg-white p-4 shadow-sm sm:flex-row sm:items-center sm:justify-between">
            <div className="space-y-1">
              <p className="text-sm font-semibold text-neutral-900">Equipe cadastrada</p>
              <p className="text-xs text-neutral-500">{filteredTeamUsers.length} {filteredTeamUsers.length === 1 ? "membro" : "membros"}</p>
            </div>
            <div className="flex flex-col gap-2 sm:flex-row sm:items-center sm:gap-3">
              <Button onClick={handleOpenCreateUser} size="sm" className="gap-2 self-start sm:self-auto">
                <IconUserPlus className="size-4" />
                Novo usuário
              </Button>
              <Button
                type="button"
                variant="ghost"
                size="sm"
                className="gap-2 self-start text-amber-600 hover:bg-amber-50 hover:text-amber-700 sm:self-auto"
                onClick={() => setCleanupDialogOpen(true)}
              >
                <IconAlertTriangle className="size-4" />
                Limpar dados antigos
              </Button>
            </div>
          </div>
          <div className="rounded-xl border border-slate-200 bg-white p-4 shadow-sm md:grid md:grid-cols-[minmax(0,1fr)_auto_auto_auto_auto] md:items-center md:gap-3">
            <div className="relative w-full md:max-w-sm">
              <IconSearch className="text-muted-foreground pointer-events-none absolute left-3 top-1/2 size-4 -translate-y-1/2" />
              <Input
                value={teamSearch}
                onChange={(event) => setTeamSearch(event.target.value)}
                placeholder="Buscar por nome, e-mail ou empresa..."
                className="h-9 pl-9"
              />
            </div>
            <div className="mt-3 flex flex-wrap items-center gap-3 md:mt-0">
              <SearchableCombobox
                value={teamRoleFilter}
                onValueChange={(value) => {
                  if (value === "admin" || value === "agent") {
                    setTeamRoleFilter(value)
                    return
                  }
                  setTeamRoleFilter("all")
                }}
                options={teamRoleFilterOptions}
                placeholder="Todos os papéis"
                searchPlaceholder="Buscar papel..."
                className="md:w-48"
              />
              <SearchableCombobox
                value={teamCompanyFilter}
                onValueChange={(value) => setTeamCompanyFilter(value ?? "all")}
                options={companyFilterOptions}
                placeholder="Todas as empresas"
                searchPlaceholder="Buscar empresa..."
                className="md:w-56"
              />
              {/* Filtro por espaço removido */}
              {(teamSearch.trim().length > 0 || teamRoleFilter !== "all") ? (
                <Button
                  variant="ghost"
                  size="sm"
                  onClick={() => {
                    setTeamSearch("")
                    setTeamRoleFilter("all")
                    setTeamCompanyFilter("all")
                    // filtro por espaço removido
                  }}
                >
                  Limpar filtros
                </Button>
              ) : null}
              <Button
                variant="outline"
                size="sm"
                className="gap-2 border-rose-200 text-rose-600 hover:bg-rose-50 hover:text-rose-700 disabled:text-rose-300 disabled:border-rose-100"
                disabled={selectedTeamUsers.length === 0 || isBulkDeletingTeam}
                onClick={() => setBulkDeleteTeamOpen(true)}
              >
                <IconTrash className="size-4" /> Excluir selecionados
              </Button>
            </div>
          </div>
          <Card>
            <CardHeader>
              <CardTitle>Equipe cadastrada</CardTitle>
              <CardDescription>Usuários com acesso ao sistema. Edite papéis, dados pessoais ou gere uma nova senha.</CardDescription>
            </CardHeader>
            <CardContent className="space-y-4">
              <div className="w-full overflow-x-auto">
                <div className="overflow-hidden rounded-lg border">
                  <Table className="min-w-[900px] table-auto text-sm">
                  <TableHeader className="bg-slate-100/80">
                    <TableRow className="text-xs uppercase tracking-wide text-neutral-500">
                      <TableHead className="w-16 pl-6 pr-4">
                        <Checkbox
                          checked={allTeamSelected || (someTeamSelected && "indeterminate")}
                          onCheckedChange={(value) => toggleTeamSelectAll(!!value)}
                          aria-label="Selecionar todos"
                        />
                      </TableHead>
                      <TableHead className="px-4">Nome</TableHead>
                      <TableHead className="px-4 md:w-72">E-mail</TableHead>
                      <TableHead className="px-4 md:w-44">Papel</TableHead>
                      <TableHead className="px-4">Empresa</TableHead>
                      <TableHead className="px-4">Criado em</TableHead>
                      <TableHead className="px-4 text-right">Ações</TableHead>
                    </TableRow>
                  </TableHeader>
                  <TableBody className="bg-white">
                    {teamPaginated.length > 0 ? (
                      teamPaginated.map((user) => (
                        <TableRow key={user.id} className="hover:bg-slate-100/70">
                          <TableCell className="w-16 pl-6 pr-4">
                            <div className="flex items-center justify-start">
                              <Checkbox
                                checked={teamSelection.has(user.id)}
                                onCheckedChange={(checked) => {
                                  setTeamSelection((prev) => {
                                    const next = new Set(prev)
                                    if (checked) next.add(user.id)
                                    else next.delete(user.id)
                                    return next
                                  })
                                }}
                                aria-label="Selecionar linha"
                              />
                            </div>
                          </TableCell>
                          <TableCell className="px-4 font-medium text-neutral-800">{user.name || "—"}</TableCell>
                          <TableCell className="px-4 text-neutral-600 break-words">{user.email}</TableCell>
                          <TableCell className="px-4 text-neutral-600 whitespace-nowrap">{formatRole(user.role)}</TableCell>
                          <TableCell className="px-4 text-neutral-600">{user.companyName ?? "—"}</TableCell>
                          <TableCell className="px-4 text-neutral-500">{formatDate(user.createdAt)}</TableCell>
                          <TableCell className="px-4">
                            <div className="flex flex-wrap justify-end gap-2">
                              <Button
                                size="icon"
                                aria-label="Editar usuário"
                                title="Editar usuário"
                                className="h-9 w-9 rounded-lg border border-slate-200 bg-white text-neutral-800 transition hover:bg-slate-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-slate-200 disabled:pointer-events-none disabled:opacity-50"
                                disabled={!canManageUser(user.role)}
                                onClick={() => {
                                  if (!canManageUser(user.role)) return
                                  setEditUserId(user.id)
                                }}
                              >
                                <IconPencil className="size-4" />
                              </Button>
                              <Button
                                size="icon"
                                aria-label="Remover usuário"
                                title="Remover usuário"
                                className="h-9 w-9 rounded-lg border border-rose-300 bg-white text-rose-600 transition hover:bg-rose-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-rose-200 disabled:pointer-events-none disabled:opacity-50"
                                disabled={!canManageUser(user.role)}
                                onClick={() => {
                                  if (!canManageUser(user.role)) return
                                  setDeleteUserId(user.id)
                                }}
                              >
                                <IconTrash className="size-4" />
                              </Button>
                            </div>
                          </TableCell>
                        </TableRow>
                      ))
                    ) : (
                      <TableRow>
                        <TableCell colSpan={7} className="px-6 py-6 text-center text-sm text-neutral-500">
                          {teamUsers.length === 0
                            ? "Nenhum usuário cadastrado até o momento."
                            : "Nenhum usuário corresponde aos filtros atuais."}
                        </TableCell>
                      </TableRow>
                    )}
                  </TableBody>
                </Table>
                </div>
              </div>
              <div className="flex flex-col items-center justify-between gap-3 border-t border-slate-200 pt-2 text-xs text-neutral-500 md:flex-row md:text-sm">
                <div>{teamTotal === 0 ? "Nenhum registro" : `Mostrando ${teamStart}-${teamEnd} de ${teamTotal}`}</div>
                <div className="flex items-center gap-3">
                  <div className="flex items-center gap-2 text-xs tracking-wide text-neutral-500 md:text-sm">
                    <span>Itens por página</span>
                    <Select
                      value={`${teamPageSize}`}
                      onValueChange={(value) => {
                        const next = Number(value)
                        setTeamPageSize(next)
                        setTeamPageIndex(0)
                      }}
                    >
                      <SelectTrigger className="h-8 w-20">
                        <SelectValue placeholder={`${teamPageSize}`} />
                      </SelectTrigger>
                      <SelectContent align="end">
                        {[10, 20, 30, 50].map((n) => (
                          <SelectItem key={`team-page-${n}`} value={`${n}`}>
                            {n}
                          </SelectItem>
                        ))}
                      </SelectContent>
                    </Select>
                  </div>
                  <Pagination>
                    <PaginationContent>
                      <PaginationItem>
                        <PaginationPrevious
                          disabled={teamPageIndex === 0}
                          onClick={() => setTeamPageIndex((previous) => Math.max(0, previous - 1))}
                        />
                      </PaginationItem>
                      <PaginationItem>
                        <PaginationLink
                          href="#"
                          isActive
                          onClick={(event) => {
                            event.preventDefault()
                          }}
                        >
                          {teamPageIndex + 1}
                        </PaginationLink>
                      </PaginationItem>
                      <PaginationItem>
                        <PaginationNext
                          disabled={teamPageIndex >= teamPageCount - 1}
                          onClick={() =>
                            setTeamPageIndex((previous) => Math.min(teamPageCount - 1, previous + 1))
                          }
                        />
                      </PaginationItem>
                    </PaginationContent>
                  </Pagination>
                </div>
              </div>
            </CardContent>
          </Card>

          <Card>
            <CardHeader>
              <CardTitle>Vincular usuário a empresa</CardTitle>
              <CardDescription>Associe colaboradores existentes a uma empresa para liberar painéis de gestores e filtros específicos.</CardDescription>
            </CardHeader>
            <CardContent>
              <form onSubmit={handleAssignCompany} className="grid gap-4 lg:grid-cols-[minmax(0,2fr)_minmax(0,2fr)_auto]">
                <div className="grid gap-2">
                  <Label>E-mail do usuário</Label>
                  <Input
                    value={linkEmail}
                    onChange={(event) => setLinkEmail(event.target.value)}
                    placeholder="colaborador@empresa.com"
                    type="email"
                    required
                  />
                </div>
                <div className="grid gap-2">
                  <Label>Empresa</Label>
                  <Select value={linkCompanyId} onValueChange={setLinkCompanyId}>
                    <SelectTrigger>
                      <SelectValue placeholder="Selecionar" />
                    </SelectTrigger>
                    <SelectContent>
                      {companies.map((company) => (
                        <SelectItem key={company.id} value={company.id}>
                          {company.name}
                        </SelectItem>
                      ))}
                    </SelectContent>
                  </Select>
                </div>
                <div className="flex items-end">
                  <Button type="submit" disabled={assigningCompany || companies.length === 0}>
                    {assigningCompany ? "Vinculando..." : "Vincular"}
                  </Button>
                </div>
              </form>
              <p className="mt-2 text-xs text-neutral-500">Caso a empresa ainda não exista, cadastre-a em <Link href="/admin/companies" className="underline underline-offset-4">Admin ▸ Empresas &amp; clientes</Link>.</p>
            </CardContent>
          </Card>
        </TabsContent>
        ) : null}

        {tabs.includes("users") ? (
        <TabsContent value="users" className="mt-6 space-y-6">
          <div className="flex flex-col gap-4 rounded-xl border border-slate-200 bg-white p-4 shadow-sm sm:flex-row sm:items-center sm:justify-between">
            <div className="space-y-1">
              <p className="text-sm font-semibold text-neutral-900">Usuários</p>
              <p className="text-xs text-neutral-500">{filteredCombinedUsers.length} {filteredCombinedUsers.length === 1 ? "usuário" : "usuários"}</p>
            </div>
            <Button onClick={handleOpenCreateUser} size="sm" className="gap-2 self-start sm:self-auto">
              <IconUserPlus className="size-4" />
              Novo usuário
            </Button>
          </div>
          <div className="rounded-xl border border-slate-200 bg-white p-4 shadow-sm md:grid md:grid-cols-[minmax(0,1fr)_auto_auto_auto_auto] md:items-center md:gap-3">
            <div className="relative w-full md:max-w-sm">
              <IconSearch className="text-muted-foreground pointer-events-none absolute left-3 top-1/2 size-4 -translate-y-1/2" />
              <Input
                value={usersSearch}
                onChange={(event) => setUsersSearch(event.target.value)}
                placeholder="Buscar por nome, e-mail, empresa ou dispositivo..."
                className="h-9 pl-9"
              />
            </div>
            <div className="mt-3 flex flex-wrap items-center gap-3 md:mt-0">
              <SearchableCombobox
                value={usersTypeFilter}
                onValueChange={(value) => {
                  if (value === "people" || value === "machines") {
                    setUsersTypeFilter(value)
                    return
                  }
                  setUsersTypeFilter("all")
                }}
                options={usersTypeFilterOptions}
                placeholder="Todos"
                searchPlaceholder="Buscar tipo..."
                className="md:w-40"
              />
              <SearchableCombobox
                value={usersCompanyFilter}
                onValueChange={(value) => setUsersCompanyFilter(value ?? "all")}
                options={companyFilterOptions}
                placeholder="Todas as empresas"
                searchPlaceholder="Buscar empresa..."
                className="md:w-56"
              />
              {/* Filtro por espaço removido */}
              {(usersSearch.trim().length > 0 || usersTypeFilter !== "all" || usersCompanyFilter !== "all") ? (
                <Button
                  variant="ghost"
                  size="sm"
                  onClick={() => {
                    setUsersSearch("")
                    setUsersTypeFilter("all")
                    setUsersCompanyFilter("all")
                    // filtro por espaço removido
                  }}
                >
                  Limpar filtros
                </Button>
              ) : null}
              <Button
                variant="outline"
                size="sm"
                className="gap-2 border-rose-200 text-rose-600 hover:bg-rose-50 hover:text-rose-700 disabled:text-rose-300 disabled:border-rose-100"
                disabled={usersSelection.size === 0 || isBulkDeletingUsersCombined}
                onClick={() => setBulkDeleteUsersCombinedOpen(true)}
              >
                <IconTrash className="size-4" /> Excluir selecionados
              </Button>
            </div>
          </div>
          <Card>
            <CardHeader>
              <CardTitle>Usuários</CardTitle>
              <CardDescription>Pessoas e dispositivos com acesso ao sistema.</CardDescription>
            </CardHeader>
            <CardContent className="space-y-4">
              <div className="w-full overflow-x-auto">
                <div className="overflow-hidden rounded-lg border">
                  <Table className="min-w-[960px] table-fixed text-sm">
                    <TableHeader className="bg-slate-100/80">
                      <TableRow className="text-xs uppercase tracking-wide text-neutral-500">
                        <TableHead className="w-12 px-4">
                          <Checkbox
                            checked={
                              usersSelection.size > 0 && usersSelection.size === filteredCombinedUsers.length
                                ? true
                                : usersSelection.size > 0
                                  ? "indeterminate"
                                  : false
                            }
                            onCheckedChange={(value) => toggleUsersCombinedSelectAll(!!value)}
                            aria-label="Selecionar todos"
                          />
                        </TableHead>
                        <TableHead className="px-4">Nome</TableHead>
                        <TableHead className="px-4">E-mail</TableHead>
                        <TableHead className="px-4">Tipo</TableHead>
                        <TableHead className="px-4">Perfil</TableHead>
                        <TableHead className="px-4">Empresa</TableHead>
                        <TableHead className="px-4">Criado em</TableHead>
                        <TableHead className="px-4 text-right">Ações</TableHead>
                      </TableRow>
                    </TableHeader>
                    <TableBody className="bg-white">
                    {usersPaginated.length > 0 ? (
                      usersPaginated.map((user) => (
                        <TableRow key={user.id} className="hover:bg-slate-100/70">
                          <TableCell className="w-12 px-4">
                            <div className="flex items-center justify-center">
                              <Checkbox
                                checked={usersSelection.has(user.id)}
                                onCheckedChange={(checked) => {
                                  setUsersSelection((prev) => {
                                    const next = new Set(prev)
                                    if (checked) next.add(user.id)
                                    else next.delete(user.id)
                                    return next
                                  })
                                }}
                                aria-label="Selecionar linha"
                              />
                            </div>
                          </TableCell>
                          <TableCell className="px-4 font-medium text-neutral-800">
                            {user.name || (user.role === "machine" ? "Dispositivo" : "—")}
                          </TableCell>
                          <TableCell className="px-4 text-neutral-600">{user.email}</TableCell>
                          <TableCell className="px-4 text-neutral-600">
                            {user.role === "machine" ? "Dispositivo" : "Pessoa"}
                          </TableCell>
                          <TableCell className="px-4 text-neutral-600">
                            {user.role === "machine" ? (
                              user.machinePersona ? (
                                <Badge
                                  variant={machinePersonaBadgeVariant(user.machinePersona)}
                                  className="rounded-full px-3 py-1 text-xs font-medium"
                                >
                                  {formatMachinePersona(user.machinePersona)}
                                </Badge>
                              ) : (
                                <span className="text-neutral-500">Sem persona</span>
                              )
                            ) : (
                              formatRole(user.role)
                            )}
                          </TableCell>
                          <TableCell className="px-4 text-neutral-600">{user.companyName ?? "—"}</TableCell>
                          <TableCell className="px-4 text-neutral-500">{formatDate(user.createdAt)}</TableCell>
                          <TableCell className="px-4">
                            <div className="flex flex-wrap justify-end gap-2">
                              <Button
                                variant="outline"
                                size="sm"
                                disabled={!canManageUser(user.role)}
                                onClick={() => {
                                  if (!canManageUser(user.role)) return
                                  setEditUserId(user.id)
                                }}
                              >
                                Editar
                              </Button>
                              {user.role === "machine" ? (
                                <Button variant="ghost" size="sm" asChild>
                                  <Link
                                    href={
                                      extractMachineId(user.email)
                                        ? `/admin/devices/${extractMachineId(user.email)}`
                                        : "/admin/devices"
                                    }
                                  >
                                    Detalhes da dispositivo
                                  </Link>
                                </Button>
                              ) : null}
                              <Button
                                variant="outline"
                                size="sm"
                                className="border-rose-200 text-rose-600 hover:bg-rose-50 hover:text-rose-700"
                                disabled={!canManageUser(user.role)}
                                onClick={() => {
                                  if (!canManageUser(user.role)) return
                                  setDeleteUserId(user.id)
                                }}
                              >
                                Remover
                              </Button>
                            </div>
                          </TableCell>
                        </TableRow>
                      ))
                    ) : (
                      <TableRow>
                        <TableCell colSpan={8} className="px-6 py-6 text-center text-sm text-neutral-500">
                          {combinedBaseUsers.length === 0
                            ? "Nenhum usuário cadastrado até o momento."
                            : "Nenhum usuário corresponde aos filtros atuais."}
                        </TableCell>
                      </TableRow>
                    )}
                  </TableBody>
                </Table>
                </div>
              </div>
              <div className="flex flex-col items-center justify-between gap-3 border-t border-slate-200 pt-2 text-xs text-neutral-500 md:flex-row md:text-sm">
                <div>{usersTotal === 0 ? "Nenhum registro" : `Mostrando ${usersStart}-${usersEnd} de ${usersTotal}`}</div>
                <div className="flex items-center gap-3">
                  <div className="flex items-center gap-2 text-xs tracking-wide text-neutral-500 md:text-sm">
                    <span>Itens por página</span>
                    <Select
                      value={`${usersPageSize}`}
                      onValueChange={(value) => {
                        const next = Number(value)
                        setUsersPageSize(next)
                        setUsersPageIndex(0)
                      }}
                    >
                      <SelectTrigger className="h-8 w-20">
                        <SelectValue placeholder={`${usersPageSize}`} />
                      </SelectTrigger>
                      <SelectContent align="end">
                        {[10, 20, 30, 50].map((n) => (
                          <SelectItem key={`users-page-${n}`} value={`${n}`}>
                            {n}
                          </SelectItem>
                        ))}
                      </SelectContent>
                    </Select>
                  </div>
                  <Pagination>
                    <PaginationContent>
                      <PaginationItem>
                        <PaginationPrevious
                          disabled={usersPageIndex === 0}
                          onClick={() => setUsersPageIndex((previous) => Math.max(0, previous - 1))}
                        />
                      </PaginationItem>
                      <PaginationItem>
                        <PaginationLink
                          href="#"
                          isActive
                          onClick={(event) => {
                            event.preventDefault()
                          }}
                        >
                          {usersPageIndex + 1}
                        </PaginationLink>
                      </PaginationItem>
                      <PaginationItem>
                        <PaginationNext
                          disabled={usersPageIndex >= usersPageCount - 1}
                          onClick={() =>
                            setUsersPageIndex((previous) => Math.min(usersPageCount - 1, previous + 1))
                          }
                        />
                      </PaginationItem>
                    </PaginationContent>
                  </Pagination>
                </div>
              </div>
            </CardContent>
          </Card>
        </TabsContent>
        ) : null}

        {tabs.includes("invites") ? (
        <TabsContent value="invites" className="mt-6 space-y-6">
          <Card>
            <CardHeader>
              <CardTitle>Gerar convite</CardTitle>
              <CardDescription>Envie convites personalizados com validade controlada e acompanhe o status em tempo real.</CardDescription>
            </CardHeader>
            <CardContent>
              <form
                onSubmit={handleInviteSubmit}
                className="grid gap-4 md:grid-cols-2 xl:grid-cols-[minmax(0,2.4fr)_minmax(0,2fr)_minmax(0,1.2fr)_minmax(0,1.2fr)_auto]"
              >
                <div className="grid gap-2 md:col-span-2 xl:col-auto">
                  <Label htmlFor="invite-email">E-mail corporativo</Label>
                  <Input
                    id="invite-email"
                    type="email"
                    inputMode="email"
                    placeholder="nome@suaempresa.com"
                    value={email}
                    onChange={(event) => setEmail(event.target.value)}
                    required
                    autoComplete="off"
                  />
                </div>
                <div className="grid gap-2 md:col-span-2 xl:col-auto">
                  <Label htmlFor="invite-name">Nome</Label>
                  <Input
                    id="invite-name"
                    placeholder="Nome completo"
                    value={name}
                    onChange={(event) => setName(event.target.value)}
                    autoComplete="off"
                  />
                </div>
                <div className="grid gap-2 md:col-span-1 xl:col-auto">
                  <Label>Papel</Label>
                  <Select value={role} onValueChange={(value) => setRole(value as RoleOption)}>
                    <SelectTrigger id="invite-role" className="h-9 w-full">
                      <SelectValue placeholder="Selecione" />
                    </SelectTrigger>
                    <SelectContent>
                      {selectableRoles.map((option) => (
                        <SelectItem key={option} value={option}>
                          {formatRole(option)}
                        </SelectItem>
                      ))}
                    </SelectContent>
                  </Select>
                </div>
                <div className="grid gap-2 md:col-span-1 xl:col-auto">
                  <Label>Expira em</Label>
                  <Select value={expiresInDays} onValueChange={setExpiresInDays}>
                    <SelectTrigger id="invite-expiration" className="w-full">
                      <SelectValue placeholder="7 dias" />
                    </SelectTrigger>
                    <SelectContent>
                      <SelectItem value="7">7 dias</SelectItem>
                      <SelectItem value="14">14 dias</SelectItem>
                      <SelectItem value="30">30 dias</SelectItem>
                    </SelectContent>
                  </Select>
                </div>
                <div className="flex items-end md:col-span-2 xl:col-auto xl:justify-end">
                  <Button type="submit" disabled={isPending} className="w-full">
                    {isPending ? "Gerando..." : "Gerar convite"}
                  </Button>
                </div>
              </form>
              {lastInviteLink ? (
                <div className="mt-4 flex flex-col gap-2 rounded-lg border border-slate-200 bg-slate-50 p-4 text-sm text-neutral-700 lg:flex-row lg:items-center lg:justify-between">
                  <div>
                    <p className="font-medium text-neutral-900">Link de convite pronto</p>
                    <p className="text-neutral-600">Compartilhe com o convidado. O link expira automaticamente no prazo selecionado.</p>
                    <code className="mt-2 block rounded bg-white px-3 py-1 text-xs text-neutral-700">{lastInviteLink}</code>
                  </div>
                  <Button variant="outline" onClick={() => handleCopy(lastInviteLink)}>Copiar link</Button>
                </div>
              ) : null}
            </CardContent>
          </Card>

          <Card>
            <CardHeader>
              <CardTitle>Convites emitidos</CardTitle>
              <CardDescription>Histórico e status atual de todos os convites enviados para o workspace.</CardDescription>
            </CardHeader>
            <CardContent className="space-y-4">
              <div className="w-full overflow-x-auto">
                <div className="overflow-hidden rounded-lg border">
                  <Table className="min-w-[800px] table-fixed text-sm">
                    <TableHeader className="bg-slate-100/80">
                      <TableRow className="text-xs uppercase tracking-wide text-neutral-500">
                        <TableHead className="w-12 px-4">
                          <Checkbox
                            checked={allInvitesSelected || (someInvitesSelected && "indeterminate")}
                            onCheckedChange={(value) => toggleInvitesSelectAll(!!value)}
                            aria-label="Selecionar todos"
                          />
                        </TableHead>
                        <TableHead className="px-4">Colaborador</TableHead>
                        <TableHead className="px-4">Papel</TableHead>
                        <TableHead className="px-4">Expira em</TableHead>
                        <TableHead className="px-4">Status</TableHead>
                        <TableHead className="px-4 text-right">Ações</TableHead>
                      </TableRow>
                    </TableHeader>
                    <TableBody className="bg-white">
                    {paginatedInvites.length > 0 ? (
                      paginatedInvites.map((invite) => (
                        <TableRow key={invite.id} className="hover:bg-slate-100/70">
                          <TableCell className="w-12 px-4">
                            <div className="flex items-center justify-center">
                              <Checkbox
                                checked={inviteSelection.has(invite.id)}
                                onCheckedChange={(checked) => {
                                  setInviteSelection((prev) => {
                                    const next = new Set(prev)
                                    if (checked) next.add(invite.id)
                                    else next.delete(invite.id)
                                    return next
                                  })
                                }}
                                aria-label="Selecionar linha"
                              />
                            </div>
                          </TableCell>
                          <TableCell className="px-4">
                            <div className="flex flex-col">
                              <span className="font-medium text-neutral-800">{invite.name || invite.email}</span>
                              <span className="text-xs text-neutral-500">{invite.email}</span>
                            </div>
                          </TableCell>
                          <TableCell className="px-4 text-neutral-600">{formatRole(invite.role)}</TableCell>
                          <TableCell className="px-4 text-neutral-600">{formatDate(invite.expiresAt)}</TableCell>
                          <TableCell className="px-4">
                            <Badge
                              variant={inviteStatusVariant(invite.status)}
                              className="rounded-full px-3 py-1 text-xs font-medium"
                            >
                              {formatStatus(invite.status)}
                            </Badge>
                          </TableCell>
                          <TableCell className="px-4">
                            <div className="flex flex-wrap justify-end gap-2">
                              <Button variant="outline" size="sm" onClick={() => handleCopy(invite.inviteUrl)}>
                                Copiar link
                              </Button>
                              {invite.status === "pending" && canManageInvite(invite.role) ? (
                                <Button
                                  variant="ghost"
                                  size="sm"
                                  className="text-red-600 transition-colors hover:bg-red-500/10"
                                  onClick={() => setRevokeDialogInviteId(invite.id)}
                                  disabled={revokingId === invite.id}
                                >
                                  {revokingId === invite.id ? "Revogando..." : "Revogar"}
                                </Button>
                              ) : null}
                              {invite.status === "revoked" && canReactivateInvitePolicy(invite) && canManageInvite(invite.role) ? (
                                <Button
                                  variant="outline"
                                  size="sm"
                                  className="border-amber-400 text-amber-600 hover:bg-amber-50"
                                  onClick={() => handleReactivate(invite)}
                                  disabled={reactivatingId === invite.id}
                                >
                                  {reactivatingId === invite.id ? "Reativando..." : "Reativar"}
                                </Button>
                              ) : null}
                            </div>
                          </TableCell>
                        </TableRow>
                      ))
                    ) : (
                      <TableRow>
                        <TableCell colSpan={6} className="px-6 py-6 text-center text-sm text-neutral-500">
                          Nenhum convite emitido até o momento.
                        </TableCell>
                      </TableRow>
                    )}
                    </TableBody>
                  </Table>
                </div>
              </div>
              <div className="flex flex-col items-center justify-between gap-3 border-t border-slate-200 pt-2 text-xs text-neutral-500 md:flex-row md:text-sm">
                <div>{invitesTotal === 0 ? "Nenhum registro" : `Mostrando ${invitesStart}-${invitesEnd} de ${invitesTotal}`}</div>
                <div className="flex flex-col-reverse gap-3 md:flex-row md:items-center md:gap-4">
                  <Button
                    variant="outline"
                    size="sm"
                    className="gap-2 border-rose-200 text-rose-600 hover:bg-rose-50 hover:text-rose-700 disabled:text-rose-300 disabled:border-rose-100"
                    disabled={selectedInvites.length === 0 || isBulkRevokingInvites}
                    onClick={() => setBulkRevokeInvitesOpen(true)}
                  >
                    <IconTrash className="size-4" /> Revogar selecionados
                  </Button>
                  <div className="flex items-center gap-3">
                    <div className="flex items-center gap-2 text-xs tracking-wide text-neutral-500 md:text-sm">
                      <span>Itens por página</span>
                      <Select
                        value={`${invitesPageSize}`}
                        onValueChange={(value) => {
                          const next = Number(value)
                          setInvitesPageSize(next)
                          setInvitesPageIndex(0)
                        }}
                      >
                        <SelectTrigger className="h-8 w-20">
                          <SelectValue placeholder={`${invitesPageSize}`} />
                        </SelectTrigger>
                        <SelectContent align="end">
                          {[10, 20, 30, 50].map((n) => (
                            <SelectItem key={`invites-page-${n}`} value={`${n}`}>
                              {n}
                            </SelectItem>
                          ))}
                        </SelectContent>
                      </Select>
                    </div>
                    <Pagination>
                      <PaginationContent>
                        <PaginationItem>
                          <PaginationPrevious
                            disabled={invitesPageIndex === 0}
                            onClick={() => setInvitesPageIndex((previous) => Math.max(0, previous - 1))}
                          />
                        </PaginationItem>
                        <PaginationItem>
                          <PaginationLink
                            href="#"
                            isActive
                            onClick={(event) => {
                              event.preventDefault()
                            }}
                          >
                            {invitesPageIndex + 1}
                          </PaginationLink>
                        </PaginationItem>
                        <PaginationItem>
                          <PaginationNext
                            disabled={invitesPageIndex >= invitesPageCount - 1}
                            onClick={() =>
                              setInvitesPageIndex((previous) => Math.min(invitesPageCount - 1, previous + 1))
                            }
                          />
                        </PaginationItem>
                      </PaginationContent>
                    </Pagination>
                  </div>
                </div>
              </div>
            </CardContent>
          </Card>
        </TabsContent>
        ) : null}
      </Tabs>
      <Dialog
        open={cleanupDialogOpen}
        onOpenChange={(open) => {
          if (!open && cleanupPending) return
          setCleanupDialogOpen(open)
        }}
      >
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Remover dados de teste</DialogTitle>
            <DialogDescription>
              Remove usuários, tickets e acessos que não estiverem na lista de e-mails preservada. Esta ação não pode ser desfeita.
            </DialogDescription>
          </DialogHeader>
          <div className="space-y-3">
            <div className="space-y-1">
              <Label htmlFor="cleanup-keep-emails">E-mails a preservar</Label>
              <Input
                id="cleanup-keep-emails"
                value={cleanupKeepEmails}
                onChange={(event) => setCleanupKeepEmails(event.target.value)}
                placeholder="email@empresa.com, outro@dominio.com"
              />
              <p className="text-xs text-muted-foreground">
                Sempre preservamos automaticamente: {viewerEmail ?? "seu e-mail atual"} e{" "}
                {DEFAULT_KEEP_EMAILS.join(", ")}.
              </p>
            </div>
            <div className="rounded-lg border border-dashed border-slate-200 bg-slate-50 px-3 py-2">
              <p className="text-xs font-semibold text-neutral-700">Lista final preservada</p>
              <p className="text-xs text-neutral-500 break-all">{cleanupPreview}</p>
            </div>
          </div>
          <DialogFooter>
            <Button variant="outline" onClick={() => setCleanupDialogOpen(false)} disabled={cleanupPending}>
              Cancelar
            </Button>
            <Button variant="destructive" onClick={handleCleanupConfirm} disabled={cleanupPending}>
              {cleanupPending ? "Removendo..." : "Remover dados"}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
      <Dialog
        open={createDialogOpen}
        onOpenChange={(open) => {
          if (open) {
            setCreateDialogOpen(true)
          } else {
            handleCloseCreateDialog()
          }
        }}
      >
        <DialogContent className="max-w-lg space-y-4">
          <DialogHeader>
            <DialogTitle>Novo usuário</DialogTitle>
            <DialogDescription>Crie uma conta para membros da equipe com acesso imediato ao sistema.</DialogDescription>
          </DialogHeader>
          <form onSubmit={handleCreateUser} className="space-y-5">
            <div className="grid gap-2">
              <Label htmlFor="create-name">Nome</Label>
              <Input
                id="create-name"
                placeholder="Nome completo"
                value={createForm.name}
                onChange={(event) => setCreateForm((prev) => ({ ...prev, name: event.target.value }))}
                required
                autoComplete="off"
              />
            </div>
            <div className="grid gap-2">
              <Label htmlFor="create-email">E-mail</Label>
              <Input
                id="create-email"
                type="email"
                inputMode="email"
                placeholder="nome@suaempresa.com"
                value={createForm.email}
                onChange={(event) => setCreateForm((prev) => ({ ...prev, email: event.target.value }))}
                required
                autoComplete="off"
              />
            </div>
            <div className="grid gap-2">
              <Label htmlFor="create-role">Papel</Label>
              <Select
                value={createForm.role}
                onValueChange={(value) => setCreateForm((prev) => ({ ...prev, role: value as RoleOption }))}
              >
                <SelectTrigger id="create-role" className="h-9">
                  <SelectValue placeholder="Selecione" />
                </SelectTrigger>
                <SelectContent>
                  {selectableRoles.map((option) => (
                    <SelectItem key={`create-role-${option}`} value={option}>
                      {formatRole(option)}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>
            {/* Campo de espaço (tenant) removido */}
            <div className="grid gap-2">
              <Label htmlFor="create-company">Empresa vinculada</Label>
              <Select
                value={createForm.companyId}
                onValueChange={(value) => setCreateForm((prev) => ({ ...prev, companyId: value }))}
              >
                <SelectTrigger id="create-company" className="h-9">
                  <SelectValue placeholder="Sem vínculo" />
                </SelectTrigger>
                <SelectContent>
                  {companyOptions.map((company) => (
                    <SelectItem key={`create-company-${company.id}`} value={company.id}>
                      {company.name}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>
            {createPassword ? (
              <div className="rounded-lg border border-slate-300 bg-slate-50 p-3">
                <p className="text-xs text-neutral-600">Senha temporária gerada:</p>
                <div className="mt-2 flex flex-wrap items-center gap-3">
                  <code className="text-sm font-semibold text-neutral-900">{createPassword}</code>
                  <Button
                    type="button"
                    variant="ghost"
                    size="sm"
                    onClick={() => navigator.clipboard.writeText(createPassword).then(() => toast.success("Senha copiada"))}
                  >
                    Copiar
                  </Button>
                </div>
              </div>
            ) : null}
            <DialogFooter className="flex flex-col gap-2 sm:flex-row sm:justify-end">
              <Button type="button" variant="outline" onClick={handleCloseCreateDialog} disabled={isCreatingUser}>
                Cancelar
              </Button>
              <Button type="submit" disabled={isCreatingUser}>
                {isCreatingUser ? "Criando..." : "Criar usuário"}
              </Button>
            </DialogFooter>
          </form>
        </DialogContent>
      </Dialog>

      <Dialog open={bulkDeleteUsersCombinedOpen} onOpenChange={setBulkDeleteUsersCombinedOpen}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Remover usuários selecionados</DialogTitle>
            <DialogDescription>Pessoas perderão o acesso e dispositivos serão desconectadas.</DialogDescription>
          </DialogHeader>
          <div className="max-h-64 space-y-2 overflow-auto">
            {Array.from(usersSelection).slice(0, 5).map((id) => {
              const u = users.find((x) => x.id === id)
              if (!u) return null
              return (
                <div key={`users-del-${id}`} className="rounded-md bg-slate-100 px-3 py-2 text-sm">
                  {(u.name || u.email)} <span className="text-neutral-500">— {u.email}</span>
                </div>
              )
            })}
            {usersSelection.size > 5 ? (
              <div className="px-3 text-xs text-neutral-500">+ {usersSelection.size - 5} outros</div>
            ) : null}
          </div>
          <DialogFooter>
            <Button variant="outline" onClick={() => setBulkDeleteUsersCombinedOpen(false)} disabled={isBulkDeletingUsersCombined}>
              Cancelar
            </Button>
            <Button
              variant="destructive"
              disabled={isBulkDeletingUsersCombined}
              onClick={async () => {
                setIsBulkDeletingUsersCombined(true)
                try {
                  await performBulkDeleteUsersCombined(Array.from(usersSelection))
                  setUsersSelection(new Set())
                  setBulkDeleteUsersCombinedOpen(false)
                  toast.success("Remoção concluída")
                } catch (error) {
                  const message = error instanceof Error ? error.message : "Falha ao excluir selecionados"
                  toast.error(message)
                } finally {
                  setIsBulkDeletingUsersCombined(false)
                }
              }}
            >
              Excluir selecionados
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>


      <Sheet open={Boolean(editUser)} onOpenChange={(open) => (!open ? setEditUserId(null) : null)}>
        <SheetContent side="right" className="space-y-6 overflow-y-auto px-6 pb-10 sm:max-w-2xl">
          <SheetHeader className="px-0 pt-6">
            <SheetTitle>Editar usuário</SheetTitle>
            <SheetDescription>Atualize os dados cadastrais, papel e vínculo do colaborador.</SheetDescription>
          </SheetHeader>

          {editUser ? (
            <form onSubmit={handleSaveUser} className="space-y-6">
              {editingRestricted ? (
                <div className="rounded-md border border-amber-200 bg-amber-50 p-3 text-sm text-amber-700">
                  Você pode visualizar este perfil, mas apenas administradores podem alterá-lo.
                </div>
              ) : null}
              <div className="grid gap-4">
                <div className="grid gap-2">
                  <Label>Nome</Label>
                  <Input
                    value={editForm.name}
                    onChange={(event) => setEditForm((prev) => ({ ...prev, name: event.target.value }))}
                    placeholder="Nome completo"
                    disabled={isSavingUser || isMachineEditing || editingRestricted}
                    required
                  />
                </div>
                <div className="grid gap-2">
                  <Label>E-mail</Label>
                  <Input
                    value={editForm.email}
                    onChange={(event) => setEditForm((prev) => ({ ...prev, email: event.target.value }))}
                    type="email"
                    disabled={isSavingUser || isMachineEditing || editingRestricted}
                    required
                  />
                </div>
                <div className="grid gap-2">
                  <Label>Papel</Label>
                  <Select
                    value={editForm.role}
                    onValueChange={(value) => setEditForm((prev) => ({ ...prev, role: value as RoleOption }))}
                    disabled={isSavingUser || isMachineEditing || editingRestricted}
                  >
                    <SelectTrigger>
                      <SelectValue placeholder="Selecione" />
                    </SelectTrigger>
                    <SelectContent>
                      {selectableRoles.map((option) => (
                        <SelectItem key={option} value={option}>
                          {formatRole(option)}
                        </SelectItem>
                      ))}
                    </SelectContent>
                  </Select>
                </div>
                {/* Campo de espaço (tenant) removido */}
                <div className="grid gap-2">
                  <Label>Empresa vinculada</Label>
                  <Select
                    value={editForm.companyId ? editForm.companyId : NO_COMPANY_ID}
                    onValueChange={(value) =>
                      setEditForm((prev) => ({ ...prev, companyId: value === NO_COMPANY_ID ? "" : value }))
                    }
                    disabled={isSavingUser || editingRestricted}
                  >
                    <SelectTrigger>
                      <SelectValue placeholder="Selecione" />
                    </SelectTrigger>
                    <SelectContent>
                      {companyOptions.map((company) => (
                        <SelectItem key={company.id} value={company.id}>
                          {company.name}
                        </SelectItem>
                      ))}
                    </SelectContent>
                  </Select>
                  <p className="text-xs text-neutral-500">Essa seleção substitui o vínculo atual no portal do cliente.</p>
                </div>
                {(() => {
                  const r = coerceRole(editUser.role)
                  if (r === 'admin' || r === 'agent') return null
                  return (
                    <div className="grid gap-2">
                      <Label>Dispositivos vinculadas</Label>
                      {linkedMachinesForEditUser.length > 0 ? (
                        <ul className="divide-y divide-slate-200 rounded-md border border-slate-200 bg-slate-50/60">
                          {linkedMachinesForEditUser.map((m) => (
                            <li key={`linked-m-${m.id}`} className="flex items-center justify-between px-3 py-2 text-sm">
                              <span className="truncate">{m.hostname || m.id}</span>
                              <Button asChild size="sm" variant="ghost">
                                <Link href={`/admin/devices/${m.id}`}>Abrir</Link>
                              </Button>
                            </li>
                          ))}
                        </ul>
                      ) : (
                        <p className="text-xs text-neutral-500">Nenhuma dispositivo vinculada a este usuário.</p>
                      )}
                    </div>
                  )
                })()}
                {isMachineEditing ? (
                  <div className="rounded-lg border border-dashed border-slate-300 bg-slate-50 p-3 text-sm text-neutral-600">
                    Os ajustes detalhados de agentes de dispositivo são feitos em <Link href="/admin/devices" className="underline underline-offset-4">Admin ▸ Dispositivos</Link>.
                  </div>
                ) : (
                  <div className="rounded-lg border border-slate-200 bg-slate-50 p-4 text-sm text-neutral-700">
                    <div className="flex flex-wrap items-center justify-between gap-3">
                      <div>
                        <p className="font-medium text-neutral-900">Gerar nova senha</p>
                        <p className="text-xs text-neutral-500">Uma senha temporária será exibida abaixo. Compartilhe com o usuário e peça para trocá-la no primeiro acesso.</p>
                      </div>
                    <Button type="button" variant="outline" onClick={handleResetPassword} disabled={isResettingPassword}>
                      {isResettingPassword ? "Gerando..." : "Gerar senha"}
                    </Button>
                  </div>
                  {passwordPreview ? (
                      <div className="mt-3 flex flex-wrap items-center gap-3 rounded-md border border-slate-300 bg-white px-3 py-2">
                        <code className="text-sm font-semibold text-neutral-900">{passwordPreview}</code>
                        <Button
                          type="button"
                          variant="ghost"
                          size="sm"
                          onClick={() => navigator.clipboard.writeText(passwordPreview).then(() => toast.success("Senha copiada"))}
                        >
                          Copiar
                        </Button>
                      </div>
                    ) : null}
                  </div>
                )}
              </div>

              <SheetFooter className="flex flex-col gap-2 sm:flex-row sm:gap-3">
                <Button type="button" variant="outline" onClick={() => setEditUserId(null)} disabled={isSavingUser}>
                  Cancelar
                </Button>
                <Button type="submit" disabled={isSavingUser || isMachineEditing || editingRestricted} className="sm:ml-auto">
                  {isSavingUser ? "Salvando..." : "Salvar alterações"}
                </Button>
              </SheetFooter>
            </form>
          ) : null}
        </SheetContent>
      </Sheet>

      <Dialog
        open={deleteUserId !== null}
        onOpenChange={(open) => {
          if (!open) {
            setDeleteUserId(null)
          }
        }}
      >
        <DialogContent>
          <DialogHeader>
            <DialogTitle>
              {deleteTarget?.role === "machine" ? "Remover agente de dispositivo" : "Remover colaborador"}
            </DialogTitle>
            <DialogDescription>
              {deleteTarget?.role === "machine"
                ? "Revogar o acesso desconecta o aplicativo desktop e exige novo provisionamento."
                : "A remoção impede novos acessos, mas não afeta registros históricos de tickets."}
            </DialogDescription>
          </DialogHeader>
          <div className="space-y-2 text-sm text-neutral-600">
            <p>
              Confirme a exclusão de <span className="font-medium text-neutral-900">{deleteTarget?.name || deleteTarget?.email}</span>.
            </p>
            {deleteTarget?.role === "machine" ? (
              <p>
                A dispositivo correspondente perderá imediatamente o token ativo e voltará para a tela de provisionamento.
              </p>
            ) : (
              <p>Esse usuário não poderá mais acessar o painel até receber um novo convite.</p>
            )}
          </div>
          <DialogFooter>
            <Button variant="outline" onClick={() => setDeleteUserId(null)} disabled={isDeletingUser}>
              Cancelar
            </Button>
            <Button variant="destructive" onClick={handleDeleteUser} disabled={isDeletingUser}>
              {isDeletingUser
                ? deleteTarget?.role === "machine"
                  ? "Removendo agente..."
                  : "Removendo..."
                : deleteTarget?.role === "machine"
                  ? "Remover agente"
                  : "Remover"}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      <Dialog
        open={revokeDialogInviteId !== null}
        onOpenChange={(open) => {
          if (!open) {
            setRevokeDialogInviteId(null)
            setRevokingId(null)
          }
        }}
      >
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Revogar convite</DialogTitle>
            <DialogDescription>
              O link atual será invalidado imediatamente. Você pode gerar um novo convite a qualquer momento.
            </DialogDescription>
          </DialogHeader>
          <div className="space-y-2 text-sm text-neutral-600">
            <p>
              Deseja revogar o convite enviado para
              {" "}
              <span className="font-medium text-neutral-900">{revokeCandidate?.email}</span>?
            </p>
            <p className="text-xs text-neutral-500">Ação irreversível — o convidado verá o link expirado.</p>
          </div>
          <DialogFooter>
            <Button variant="outline" onClick={() => setRevokeDialogInviteId(null)} disabled={revokingId !== null}>
              Manter convite
            </Button>
            <Button
              variant="destructive"
              onClick={handleRevokeConfirmed}
              disabled={revokingId === revokeCandidate?.id}
            >
              {revokingId === revokeCandidate?.id ? "Revogando..." : "Revogar convite"}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      {/* Bulk actions */}
      <Dialog open={bulkDeleteTeamOpen} onOpenChange={setBulkDeleteTeamOpen}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Remover membros selecionados</DialogTitle>
            <DialogDescription>Revoga o acesso imediatamente. Registros históricos permanecem.</DialogDescription>
          </DialogHeader>
          <div className="max-h-64 space-y-2 overflow-auto">
            {selectedTeamUsers.slice(0, 5).map((u) => (
              <div key={`team-del-${u.id}`} className="rounded-md bg-slate-100 px-3 py-2 text-sm">
                {u.name || u.email} <span className="text-neutral-500">— {u.email}</span>
              </div>
            ))}
            {selectedTeamUsers.length > 5 ? (
              <div className="px-3 text-xs text-neutral-500">+ {selectedTeamUsers.length - 5} outros</div>
            ) : null}
          </div>
          <DialogFooter>
            <Button variant="outline" onClick={() => setBulkDeleteTeamOpen(false)} disabled={isBulkDeletingTeam}>
              Cancelar
            </Button>
            <Button
              variant="destructive"
              disabled={isBulkDeletingTeam}
              onClick={async () => {
                setIsBulkDeletingTeam(true)
                try {
                  await performBulkDeleteUsers(selectedTeamUsers.map((u) => u.id))
                  setTeamSelection(new Set())
                  setBulkDeleteTeamOpen(false)
                  toast.success("Remoção concluída")
                } catch (error) {
                  const message = error instanceof Error ? error.message : "Falha ao excluir selecionados"
                  toast.error(message)
                } finally {
                  setIsBulkDeletingTeam(false)
                }
              }}
            >
              Excluir selecionados
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      {/* Dialogs antigos removidos: ações em massa agora são unificadas no diálogo abaixo */}

      <Dialog open={bulkRevokeInvitesOpen} onOpenChange={setBulkRevokeInvitesOpen}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Revogar convites selecionados</DialogTitle>
            <DialogDescription>Os links serão invalidados imediatamente.</DialogDescription>
          </DialogHeader>
          <div className="max-h-64 space-y-2 overflow-auto">
            {selectedInvites.slice(0, 5).map((i) => (
              <div key={`invite-revoke-${i.id}`} className="rounded-md bg-slate-100 px-3 py-2 text-sm">
                {i.email} <span className="text-neutral-500">— {formatRole(i.role)}</span>
              </div>
            ))}
            {selectedInvites.length > 5 ? (
              <div className="px-3 text-xs text-neutral-500">+ {selectedInvites.length - 5} outros</div>
            ) : null}
          </div>
          <DialogFooter>
            <Button variant="outline" onClick={() => setBulkRevokeInvitesOpen(false)} disabled={isBulkRevokingInvites}>
              Cancelar
            </Button>
            <Button
              variant="destructive"
              disabled={isBulkRevokingInvites}
              onClick={async () => {
                setIsBulkRevokingInvites(true)
                try {
                  const ids = selectedInvites.filter((i) => i.status === "pending").map((i) => i.id)
                  await performBulkRevokeInvites(ids)
                  setInviteSelection(new Set())
                  setBulkRevokeInvitesOpen(false)
                  toast.success("Convites revogados")
                } catch (error) {
                  const message = error instanceof Error ? error.message : "Falha ao revogar convites"
                  toast.error(message)
                } finally {
                  setIsBulkRevokingInvites(false)
                }
              }}
            >
              Revogar selecionados
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </>
  )
}
