"use client"

import { useCallback, useEffect, useMemo, useState } from "react"
import { useQuery } from "convex/react"
import { Bar, BarChart, CartesianGrid, XAxis } from "recharts"

import { api } from "@/convex/_generated/api"
import type { Id } from "@/convex/_generated/dataModel"
import { useAuth } from "@/lib/auth-client"
import { DEFAULT_TENANT_ID } from "@/lib/constants"
import { usePersistentCompanyFilter } from "@/lib/use-company-filter"
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
import { ReportsFilterToolbar } from "@/components/reports/report-filter-toolbar"
import { SearchableCombobox, type SearchableComboboxOption } from "@/components/ui/searchable-combobox"
import { ChartContainer, ChartTooltip, ChartTooltipContent } from "@/components/ui/chart"
import { formatDateDM, formatHoursCompact } from "@/lib/utils"
import { Skeleton } from "@/components/ui/skeleton"
import { DEVICE_INVENTORY_COLUMN_METADATA, type DeviceInventoryColumnConfig } from "@/lib/device-inventory-columns"
import { Button } from "@/components/ui/button"
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog"
import { Checkbox } from "@/components/ui/checkbox"
import { Progress } from "@/components/ui/progress"
import { Spinner } from "@/components/ui/spinner"
import { toast } from "sonner"

type MachineCategoryDailyItem = {
  date: string
  machineId: string | null
  machineHostname: string | null
  companyId: string | null
  companyName: string | null
  categoryId: string | null
  categoryName: string
  total: number
}

type MachineCategoryReportData = {
  rangeDays: number
  items: MachineCategoryDailyItem[]
}

type MachineHoursItem = {
  machineId: string
  machineHostname: string | null
  companyId: string | null
  companyName: string | null
  internalMs: number
  externalMs: number
  totalMs: number
}

type MachineHoursResponse = {
  rangeDays: number
  items: MachineHoursItem[]
}

type DeviceFieldOption = {
  id: Id<"deviceFields">
  key: string
  label: string
}

type ColumnOption = {
  key: string
  label: string
  group: "base" | "custom"
}

const DEFAULT_DEVICE_COLUMN_KEYS = DEVICE_INVENTORY_COLUMN_METADATA.filter((meta) => meta.default !== false).map((meta) => meta.key)

export function MachineCategoryReport() {
  const [timeRange, setTimeRange] = useState<"90d" | "30d" | "7d" | "365d" | "all">("30d")
  const [companyId, setCompanyId] = usePersistentCompanyFilter("all")
  const [dateFrom, setDateFrom] = useState<string | null>(null)
  const [dateTo, setDateTo] = useState<string | null>(null)
  const { session, convexUserId, isStaff } = useAuth()
  const tenantId = session?.user.tenantId ?? DEFAULT_TENANT_ID

  const canView = Boolean(isStaff)
  const enabled = Boolean(canView && convexUserId)
  const dateRangeFilters = useMemo(() => {
    const filters: { dateFrom?: string; dateTo?: string } = {}
    if (dateFrom) filters.dateFrom = dateFrom
    if (dateTo) filters.dateTo = dateTo
    return filters
  }, [dateFrom, dateTo])

  const data = useQuery(
    api.reports.ticketsByMachineAndCategory,
    enabled
      ? ({
          tenantId,
          viewerId: convexUserId as Id<"users">,
          range: timeRange,
          companyId: companyId === "all" ? undefined : (companyId as Id<"companies">),
          ...dateRangeFilters,
        } as const)
      : "skip"
  ) as MachineCategoryReportData | undefined

  const companies = useQuery(
    api.companies.list,
    enabled ? { tenantId, viewerId: convexUserId as Id<"users"> } : "skip"
  ) as Array<{ id: Id<"companies">; name: string }> | undefined

  const companyOptions = useMemo<SearchableComboboxOption[]>(() => {
    const base: SearchableComboboxOption[] = [{ value: "all", label: "Todas as empresas" }]
    if (!companies || companies.length === 0) {
      return base
    }
    const sorted = [...companies].sort((a, b) => a.name.localeCompare(b.name, "pt-BR"))
    return [
      base[0],
      ...sorted.map((company) => ({
        value: company.id,
        label: company.name,
      })),
    ]
  }, [companies])

  const items = useMemo(() => data?.items ?? [], [data])

  const machinesRaw = useQuery(
    api.devices.listByTenant,
    enabled
      ? ({
          tenantId,
          includeMetadata: false,
        } as const)
      : "skip"
  ) as Array<{ id: string; hostname?: string | null; companyId?: string | null; displayName?: string | null }> | undefined

  const users = useQuery(
    api.users.listCustomers,
    enabled
      ? ({
          tenantId,
          viewerId: convexUserId as Id<"users">,
        } as const)
      : "skip"
  ) as Array<{ id: Id<"users">; name: string | null; email: string; companyId?: Id<"companies"> | null }> | undefined

  const deviceFields = useQuery(
    api.deviceFields.listForTenant,
    enabled
      ? ({
          tenantId,
          viewerId: convexUserId as Id<"users">,
        } as const)
      : "skip"
  ) as DeviceFieldOption[] | undefined

  const machineOptions = useMemo<SearchableComboboxOption[]>(() => {
    const base: SearchableComboboxOption[] = [{ value: "all", label: "Todas as máquinas" }]
    if (!machinesRaw || machinesRaw.length === 0) return base
    const filtered = machinesRaw.filter((machine) => {
      if (!machine) return false
      if (companyId === "all") return true
      return String(machine.companyId ?? "") === String(companyId)
    })
    const mapped = filtered
      .map((machine) => {
        const id = String((machine as { id?: string; _id?: string }).id ?? (machine as { _id?: string })._id ?? "")
        const hostname =
          (machine.hostname ?? machine.displayName ?? "")?.toString().trim() || `Máquina ${id.slice(0, 8)}`
        return { value: id, label: hostname }
      })
      .sort((a, b) => a.label.localeCompare(b.label, "pt-BR"))
    return [base[0], ...mapped]
  }, [machinesRaw, companyId])

  const userOptions = useMemo<SearchableComboboxOption[]>(() => {
    const base: SearchableComboboxOption[] = [{ value: "all", label: "Todos os usuários" }]
    if (!users || users.length === 0) return base
    const filtered = users.filter((user) => {
      if (!user) return false
      if (companyId === "all") return true
      return String(user.companyId ?? "") === String(companyId)
    })
    const mapped = filtered
      .map((user) => {
        const label = (user.name ?? user.email).trim()
        return { value: String(user.id), label }
      })
      .sort((a, b) => a.label.localeCompare(b.label, "pt-BR"))
    return [base[0], ...mapped]
  }, [users, companyId])

  const [selectedMachineId, setSelectedMachineId] = useState<string>("all")
  const [selectedUserId, setSelectedUserId] = useState<string>("all")
  const [isExportDialogOpen, setIsExportDialogOpen] = useState(false)
  const [isExporting, setIsExporting] = useState(false)
  const [exportProgress, setExportProgress] = useState(0)
  const [exportError, setExportError] = useState<string | null>(null)
  const [selectedColumnKeys, setSelectedColumnKeys] = useState<string[]>(() => [...DEFAULT_DEVICE_COLUMN_KEYS])

  const baseColumnOptions = useMemo<ColumnOption[]>(
    () =>
      DEVICE_INVENTORY_COLUMN_METADATA.map((meta) => ({
        key: meta.key,
        label: meta.label,
        group: "base" as const,
      })),
    []
  )

  const customColumnOptions = useMemo<ColumnOption[]>(() => {
    if (!deviceFields || deviceFields.length === 0) return []
    return deviceFields
      .map((field) => ({
        key: `custom:${field.key}`,
        label: field.label,
        group: "custom" as const,
      }))
      .sort((a, b) => a.label.localeCompare(b.label, "pt-BR"))
  }, [deviceFields])

  const columnOptionsMap = useMemo(() => {
    const entries = [...baseColumnOptions, ...customColumnOptions]
    return new Map(entries.map((option) => [option.key, option]))
  }, [baseColumnOptions, customColumnOptions])

  const orderedColumnKeys = useMemo(
    () => [...baseColumnOptions.map((option) => option.key), ...customColumnOptions.map((option) => option.key)],
    [baseColumnOptions, customColumnOptions]
  )

  const selectedColumnConfigs = useMemo<DeviceInventoryColumnConfig[]>(() => {
    const selection = new Set(selectedColumnKeys)
    return orderedColumnKeys
      .filter((key) => selection.has(key))
      .map((key) => {
        const option = columnOptionsMap.get(key)
        return {
          key,
          label: option && option.group === "custom" ? option.label : undefined,
        }
      })
  }, [columnOptionsMap, orderedColumnKeys, selectedColumnKeys])

  const selectedColumnCount = selectedColumnConfigs.length

  const hours = useQuery(
    api.reports.hoursByMachine,
    enabled && selectedMachineId !== "all"
      ? ({
          tenantId,
          viewerId: convexUserId as Id<"users">,
          range: timeRange,
          companyId: companyId === "all" ? undefined : (companyId as Id<"companies">),
          machineId: selectedMachineId !== "all" ? (selectedMachineId as Id<"machines">) : undefined,
          userId: selectedUserId !== "all" ? (selectedUserId as Id<"users">) : undefined,
          ...dateRangeFilters,
        } as const)
      : "skip"
  ) as MachineHoursResponse | undefined

  const totals = useMemo(
    () =>
      items.reduce(
        (acc, item) => {
          acc.totalTickets += item.total
          acc.machines.add(item.machineId ?? item.machineHostname ?? "sem-maquina")
          acc.categories.add(item.categoryName)
          return acc
        },
        {
          totalTickets: 0,
          machines: new Set<string>(),
          categories: new Set<string>(),
        }
      ),
    [items]
  )

  const dailySeries = useMemo(
    () => {
      const map = new Map<string, number>()
      for (const item of items) {
        const current = map.get(item.date) ?? 0
        map.set(item.date, current + item.total)
      }
      return Array.from(map.entries())
        .map(([date, total]) => ({ date, total }))
        .sort((a, b) => a.date.localeCompare(b.date))
    },
    [items]
  )

  const tableRows = useMemo(
    () =>
      [...items].sort((a, b) => {
        if (a.date !== b.date) return b.date.localeCompare(a.date)
        const machineA = (a.machineHostname ?? "").toLowerCase()
        const machineB = (b.machineHostname ?? "").toLowerCase()
        if (machineA !== machineB) return machineA.localeCompare(machineB)
        return a.categoryName.localeCompare(b.categoryName, "pt-BR")
      }),
    [items]
  )

  const exportableMachineIds = useMemo(() => {
    const set = new Set<string>()
    for (const item of items) {
      if (item.machineId) {
        set.add(String(item.machineId))
      }
    }
    return Array.from(set)
  }, [items])

  const handleToggleColumn = useCallback((key: string, checked: boolean) => {
    setSelectedColumnKeys((prev) => {
      if (checked) {
        if (prev.includes(key)) return prev
        return [...prev, key]
      }
      return prev.filter((column) => column !== key)
    })
  }, [])

  const handleResetColumns = useCallback(() => {
    setSelectedColumnKeys([...DEFAULT_DEVICE_COLUMN_KEYS])
  }, [])

  const handleSelectAllColumns = useCallback(() => {
    setSelectedColumnKeys([...orderedColumnKeys])
  }, [orderedColumnKeys])

  const handleOpenExportDialog = useCallback(() => {
    if (exportableMachineIds.length === 0) {
      toast.warning("Nenhuma máquina com identificador válido para exportar neste período.")
      return
    }
    setExportError(null)
    setIsExportDialogOpen(true)
  }, [exportableMachineIds.length])

  const handleExportDialogOpenChange = useCallback(
    (open: boolean) => {
      if (!open && isExporting) return
      setIsExportDialogOpen(open)
      if (!open) {
        setExportProgress(0)
        setExportError(null)
      }
    },
    [isExporting]
  )

  const buildExportSearchParams = useCallback(() => {
    const params = new URLSearchParams()
    params.set("range", timeRange)
    if (companyId !== "all") params.set("companyId", companyId)
    if (selectedMachineId !== "all") params.set("machineId", selectedMachineId)
    if (selectedUserId !== "all") params.set("userId", selectedUserId)
    if (dateFrom) params.set("dateFrom", dateFrom)
    if (dateTo) params.set("dateTo", dateTo)
    return params
  }, [companyId, dateFrom, dateTo, selectedMachineId, selectedUserId, timeRange])

  const handleConfirmExport = useCallback(async () => {
    if (exportableMachineIds.length === 0) {
      setExportError("Não há máquinas disponíveis para exportar.")
      return
    }
    if (selectedColumnConfigs.length === 0) {
      setExportError("Selecione ao menos uma coluna para exportar.")
      return
    }
    const params = buildExportSearchParams()
    params.set("columns", JSON.stringify(selectedColumnConfigs))
    const qs = params.toString()
    const url = `/api/reports/machine-category.xlsx${qs ? `?${qs}` : ""}`

    setIsExporting(true)
    setExportError(null)
    setExportProgress(5)

    try {
      const response = await fetch(url)
      if (!response.ok) {
        throw new Error(`Export failed with status ${response.status}`)
      }

      const contentLengthHeader = response.headers.get("Content-Length")
      const totalBytes = contentLengthHeader ? parseInt(contentLengthHeader, 10) : Number.NaN
      const hasLength = Number.isFinite(totalBytes) && totalBytes > 0
      const disposition = response.headers.get("Content-Disposition")
      const filenameMatch = disposition?.match(/filename="?([^";]+)"?/i)
      const filename = filenameMatch?.[1] ?? `machine-category-${new Date().toISOString().slice(0, 10)}.xlsx`

      let blob: Blob
      if (!response.body || typeof response.body.getReader !== "function") {
        blob = await response.blob()
        setExportProgress(100)
      } else {
        const reader = response.body.getReader()
        const chunks: ArrayBuffer[] = []
        let received = 0
        while (true) {
          const { value, done } = await reader.read()
          if (done) break
          if (value) {
            const chunk = value.buffer.slice(value.byteOffset, value.byteOffset + value.byteLength)
            chunks.push(chunk)
            received += value.length
            if (hasLength) {
              const percent = Math.min(99, Math.round((received / totalBytes) * 100))
              setExportProgress(percent)
            } else {
              setExportProgress((prev) => (prev >= 95 ? prev : prev + 5))
            }
          }
        }
        blob = new Blob(chunks, { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" })
        setExportProgress(100)
      }

      const downloadUrl = window.URL.createObjectURL(blob)
      const link = document.createElement("a")
      link.href = downloadUrl
      link.download = filename
      document.body.appendChild(link)
      link.click()
      link.remove()
      window.URL.revokeObjectURL(downloadUrl)

      toast.success("Planilha gerada com sucesso.")
      setIsExporting(false)
      setIsExportDialogOpen(false)
    } catch (error) {
      console.error("Failed to export machine category worksheet", error)
      setExportProgress(0)
      setIsExporting(false)
      setExportError("Não foi possível gerar a planilha. Tente novamente.")
    }
  }, [buildExportSearchParams, exportableMachineIds.length, selectedColumnConfigs])

  if (!canView) {
    return (
      <Card className="border-slate-200">
        <CardHeader>
          <CardTitle className="text-lg font-semibold text-neutral-900">Máquinas x categorias</CardTitle>
          <CardDescription className="text-neutral-600">
            Este relatório está disponível apenas para a equipe interna.
          </CardDescription>
        </CardHeader>
      </Card>
    )
  }

  if (!data) {
    return (
      <div className="space-y-6">
        <Skeleton className="h-16 rounded-2xl" />
        <Skeleton className="h-64 rounded-2xl" />
        <Skeleton className="h-80 rounded-2xl" />
      </div>
    )
  }

  return (
    <div className="space-y-6">
      <ReportsFilterToolbar
        className="w-full"
        companyId={companyId}
        onCompanyChange={(value) => setCompanyId(value)}
        companyOptions={companyOptions}
        timeRange={timeRange}
        onTimeRangeChange={(value) => {
          setTimeRange(value)
          setDateFrom(null)
          setDateTo(null)
        }}
        dateFrom={dateFrom}
        dateTo={dateTo}
        onDateRangeChange={({ from, to }) => {
          setDateFrom(from)
          setDateTo(to)
        }}
        allowExtendedRanges
        onExportClick={handleOpenExportDialog}
        isExporting={isExporting}
      />

      <Card className="border-slate-200">
        <CardHeader>
          <CardTitle className="text-sm font-semibold text-neutral-900">
            Filtro detalhado por máquina e usuário
          </CardTitle>
          <CardDescription className="text-neutral-600">
            Refine os dados para uma máquina específica e, opcionalmente, para um colaborador da empresa selecionada.
          </CardDescription>
        </CardHeader>
        <CardContent>
          <div className="grid gap-4 md:grid-cols-3">
            <div className="space-y-3">
              <span className="text-xs font-semibold uppercase tracking-wide text-neutral-500">
                Máquina
              </span>
              <SearchableCombobox
                value={selectedMachineId}
                onValueChange={(value) => setSelectedMachineId(value ?? "all")}
                options={machineOptions}
                placeholder="Todas as máquinas"
                triggerClassName="h-10 w-full rounded-2xl border border-slate-300 bg-white px-3 text-sm font-medium text-neutral-800"
              />
            </div>
            <div className="space-y-3">
              <span className="text-xs font-semibold uppercase tracking-wide text-neutral-500">
                Usuário (solicitante)
              </span>
              <SearchableCombobox
                value={selectedUserId}
                onValueChange={(value) => setSelectedUserId(value ?? "all")}
                options={userOptions}
                placeholder="Todos os usuários"
                triggerClassName="h-10 w-full rounded-2xl border border-slate-300 bg-white px-3 text-sm font-medium text-neutral-800"
              />
            </div>
            <div className="space-y-1">
              <span className="text-xs font-semibold uppercase tracking-wide text-neutral-500">
                Contexto
              </span>
              <p className="text-xs text-neutral-500">
                Combine os filtros acima com o período selecionado para analisar o histórico daquela máquina.
              </p>
            </div>
          </div>
        </CardContent>
      </Card>

      {selectedMachineId !== "all" ? (
        <Card className="border-slate-200">
          <CardHeader>
            <CardTitle className="text-lg font-semibold text-neutral-900">
              Histórico da máquina selecionada
            </CardTitle>
            <CardDescription className="text-neutral-600">
              Distribuição de categorias e horas trabalhadas na máquina filtrada, dentro do período selecionado.
            </CardDescription>
          </CardHeader>
          <CardContent className="space-y-4">
            <div className="grid gap-4 md:grid-cols-3">
              {(() => {
                const machineItems = items.filter(
                  (item) =>
                    item.machineId === selectedMachineId ||
                    (selectedMachineId === "all" && item.machineId !== null),
                )
                const totalTickets = machineItems.reduce((acc, item) => acc + item.total, 0)
                const hoursItem = (hours?.items ?? []).find(
                  (entry) => entry.machineId === selectedMachineId,
                )
                const internalHours = hoursItem ? hoursItem.internalMs / 3_600_000 : 0
                const externalHours = hoursItem ? hoursItem.externalMs / 3_600_000 : 0
                const totalHours = hoursItem ? hoursItem.totalMs / 3_600_000 : 0

                const companyLabel =
                  hoursItem?.companyName ??
                  machineItems[0]?.companyName ??
                  (companyId === "all" ? "Várias empresas" : null)

                return (
                  <>
                    <div className="space-y-1 rounded-2xl border border-slate-200 bg-white px-4 py-3 shadow-sm">
                      <p className="text-xs font-semibold uppercase tracking-wide text-neutral-500">
                        Chamados da máquina
                      </p>
                      <p className="text-2xl font-semibold text-neutral-900">{totalTickets}</p>
                    </div>
                    <div className="space-y-1 rounded-2xl border border-slate-200 bg-white px-4 py-3 shadow-sm">
                      <p className="text-xs font-semibold uppercase tracking-wide text-neutral-500">
                        Horas totais
                      </p>
                      <p className="text-xl font-semibold text-neutral-900">
                        {totalHours > 0 ? formatHoursCompact(totalHours) : "0h"}
                      </p>
                      <p className="text-xs text-neutral-500">
                        Internas: {formatHoursCompact(internalHours)} · Externas:{" "}
                        {formatHoursCompact(externalHours)}
                      </p>
                    </div>
                    <div className="space-y-1 rounded-2xl border border-slate-200 bg-white px-4 py-3 shadow-sm">
                      <p className="text-xs font-semibold uppercase tracking-wide text-neutral-500">
                        Empresa
                      </p>
                      <p className="text-sm font-semibold text-neutral-900">
                        {companyLabel ?? "Sem empresa"}
                      </p>
                    </div>
                  </>
                )
              })()}
            </div>

            {(() => {
              const perCategory = new Map<string, { categoryName: string; total: number }>()
              for (const item of items) {
                if (item.machineId !== selectedMachineId) continue
                if (selectedUserId !== "all" && selectedUserId) {
                  // user filter já é aplicado na query de backend; não precisamos revalidar aqui
                }
                const key = item.categoryName || "Sem categoria"
                const current = perCategory.get(key) ?? { categoryName: key, total: 0 }
                current.total += item.total
                perCategory.set(key, current)
              }
              const rows = Array.from(perCategory.values()).sort((a, b) => b.total - a.total)

              if (rows.length === 0) {
                return (
                  <p className="rounded-lg border border-dashed border-slate-200 p-4 text-sm text-neutral-500">
                    Nenhuma categoria encontrada para a combinação de filtros atual.
                  </p>
                )
              }

              return (
                <div className="overflow-hidden rounded-2xl border border-slate-200">
                  <table className="w-full text-sm">
                    <thead className="bg-slate-50 text-xs uppercase tracking-wide text-neutral-500">
                      <tr>
                        <th className="px-4 py-3 text-left">Categoria</th>
                        <th className="px-4 py-3 text-right">Chamados</th>
                      </tr>
                    </thead>
                    <tbody>
                      {rows.map((row) => (
                        <tr key={row.categoryName} className="border-t border-slate-100">
                          <td className="px-4 py-2 text-neutral-800">{row.categoryName}</td>
                          <td className="px-4 py-2 text-right font-semibold text-neutral-900">
                            {row.total}
                          </td>
                        </tr>
                      ))}
                    </tbody>
                  </table>
                </div>
              )
            })()}
          </CardContent>
        </Card>
      ) : null}

      <div className="grid gap-4 md:grid-cols-3">
        <Card className="border-slate-200">
          <CardHeader>
            <CardTitle className="text-xs font-semibold uppercase tracking-wide text-neutral-500">
              Chamados analisados
            </CardTitle>
            <CardDescription className="text-neutral-600">
              Total de tickets com máquina vinculada no período.
            </CardDescription>
          </CardHeader>
          <CardContent className="text-3xl font-semibold text-neutral-900">
            {totals.totalTickets}
          </CardContent>
        </Card>
        <Card className="border-slate-200">
          <CardHeader>
            <CardTitle className="text-xs font-semibold uppercase tracking-wide text-neutral-500">
              Máquinas únicas
            </CardTitle>
            <CardDescription className="text-neutral-600">
              Quantidade de dispositivos diferentes com chamados no período.
            </CardDescription>
          </CardHeader>
          <CardContent className="text-3xl font-semibold text-neutral-900">
            {totals.machines.size}
          </CardContent>
        </Card>
        <Card className="border-slate-200">
          <CardHeader>
            <CardTitle className="text-xs font-semibold uppercase tracking-wide text-neutral-500">
              Categorias
            </CardTitle>
            <CardDescription className="text-neutral-600">
              Categorias distintas associadas aos tickets dessas máquinas.
            </CardDescription>
          </CardHeader>
          <CardContent className="text-3xl font-semibold text-neutral-900">
            {totals.categories.size}
          </CardContent>
        </Card>
      </div>

      <Card className="border-slate-200">
        <CardHeader>
          <CardTitle className="text-lg font-semibold text-neutral-900">
            Volume diário por máquina (total)
          </CardTitle>
          <CardDescription className="text-neutral-600">
            Quantidade de chamados com máquina vinculada, somando todas as categorias, por dia.
          </CardDescription>
        </CardHeader>
        <CardContent>
          {dailySeries.length === 0 ? (
            <p className="rounded-lg border border-dashed border-slate-200 p-6 text-sm text-neutral-500">
              Nenhum ticket com máquina vinculada foi encontrado para o período selecionado.
            </p>
          ) : (
            <ChartContainer config={{}} className="aspect-auto h-[260px] w-full">
              <BarChart data={dailySeries} margin={{ top: 8, left: 20, right: 20, bottom: 32 }}>
                <CartesianGrid vertical={false} />
                <XAxis
                  dataKey="date"
                  tickLine={false}
                  axisLine={false}
                  tickMargin={8}
                  minTickGap={24}
                  tickFormatter={(value) => formatDateDM(new Date(String(value)))}
                />
                <ChartTooltip
                  content={
                    <ChartTooltipContent
                      className="w-[180px]"
                      labelFormatter={(value) => formatDateDM(new Date(String(value)))}
                    />
                  }
                />
                <Bar dataKey="total" fill="var(--chart-1)" radius={[4, 4, 0, 0]} name="Chamados" />
              </BarChart>
            </ChartContainer>
          )}
        </CardContent>
      </Card>

      <Card className="border-slate-200">
        <CardHeader>
          <CardTitle className="text-lg font-semibold text-neutral-900">
            Detalhamento diário por máquina e categoria
          </CardTitle>
          <CardDescription className="text-neutral-600">
            Cada linha representa o total de chamados abertos em uma data específica, agrupados por
            máquina e categoria.
          </CardDescription>
        </CardHeader>
        <CardContent>
          {tableRows.length === 0 ? (
            <p className="rounded-lg border border-dashed border-slate-200 p-6 text-sm text-neutral-500">
              Nenhum ticket com máquina vinculada foi encontrado para o período selecionado.
            </p>
          ) : (
            <div className="overflow-hidden rounded-2xl border border-slate-200">
              <table className="w-full text-sm">
                <thead className="bg-slate-50 text-xs uppercase tracking-wide text-neutral-500">
                  <tr>
                    <th className="px-4 py-3 text-left">Data</th>
                    <th className="px-4 py-3 text-left">Máquina</th>
                    <th className="px-4 py-3 text-left">Empresa</th>
                    <th className="px-4 py-3 text-left">Categoria</th>
                    <th className="px-4 py-3 text-right">Chamados</th>
                  </tr>
                </thead>
                <tbody>
                  {tableRows.map((row, index) => {
                    const machineLabel =
                      row.machineHostname && row.machineHostname.trim().length > 0
                        ? row.machineHostname
                        : "Sem hostname"
                    const companyLabel = row.companyName ?? "Sem empresa"
                    return (
                      <tr key={`${row.date}-${machineLabel}-${row.categoryName}-${index}`} className="border-t border-slate-100">
                        <td className="px-4 py-2 text-neutral-800">
                          {formatDateDM(new Date(`${row.date}T00:00:00Z`))}
                        </td>
                        <td className="px-4 py-2 text-neutral-800">{machineLabel}</td>
                        <td className="px-4 py-2 text-neutral-700">{companyLabel}</td>
                        <td className="px-4 py-2 text-neutral-700">{row.categoryName}</td>
                        <td className="px-4 py-2 text-right font-semibold text-neutral-900">{row.total}</td>
                      </tr>
                    )
                  })}
                </tbody>
              </table>
            </div>
          )}
        </CardContent>
      </Card>

      <Dialog open={isExportDialogOpen} onOpenChange={handleExportDialogOpenChange}>
        <DialogContent className="max-w-2xl">
          <DialogHeader>
            <DialogTitle>Exportar XLSX — Máquinas x categorias</DialogTitle>
            <DialogDescription>
              Personalize quais campos das máquinas aparecerão na planilha complementar de inventário. Os filtros aplicados neste relatório serão respeitados.
            </DialogDescription>
          </DialogHeader>
          <div className="space-y-5">
            <div className="rounded-2xl border border-slate-200 bg-slate-50/70 px-4 py-3 text-sm text-neutral-700">
              Máquinas encontradas:{" "}
              <span className="font-semibold text-neutral-900">{exportableMachineIds.length}</span>
              {selectedMachineId !== "all" ? (
                <span className="ml-1 text-xs text-neutral-500">(apenas a máquina filtrada será exportada)</span>
              ) : null}
            </div>
            <div className="flex flex-wrap items-center justify-between gap-2">
              <p className="text-sm font-semibold text-neutral-900">Colunas selecionadas: {selectedColumnCount}</p>
              <div className="flex items-center gap-2">
                <Button type="button" variant="ghost" size="sm" onClick={handleSelectAllColumns} disabled={isExporting} className="gap-2">
                  Selecionar todas
                </Button>
                <Button type="button" variant="ghost" size="sm" onClick={handleResetColumns} disabled={isExporting} className="gap-2">
                  Restaurar padrão
                </Button>
              </div>
            </div>
            <div className="space-y-4 max-h-[420px] overflow-y-auto pr-1">
              <div className="space-y-2">
                <p className="text-xs font-semibold uppercase tracking-wide text-neutral-500">Colunas padrão</p>
                <div className="grid gap-3 sm:grid-cols-2">
                  {baseColumnOptions.map((column) => {
                    const checked = selectedColumnKeys.includes(column.key)
                    return (
                      <label key={column.key} className="flex items-center gap-2 text-sm text-neutral-800">
                        <Checkbox
                          checked={checked}
                          onCheckedChange={(value) => handleToggleColumn(column.key, value === true || value === "indeterminate")}
                          disabled={isExporting}
                        />
                        <span>{column.label}</span>
                      </label>
                    )
                  })}
                </div>
              </div>
              {customColumnOptions.length > 0 ? (
                <div className="space-y-2">
                  <p className="text-xs font-semibold uppercase tracking-wide text-neutral-500">Campos personalizados</p>
                  <div className="grid gap-3 sm:grid-cols-2">
                    {customColumnOptions.map((column) => {
                      const checked = selectedColumnKeys.includes(column.key)
                      return (
                        <label key={column.key} className="flex items-center gap-2 text-sm text-neutral-800">
                          <Checkbox
                            checked={checked}
                            onCheckedChange={(value) => handleToggleColumn(column.key, value === true || value === "indeterminate")}
                            disabled={isExporting}
                          />
                          <span>{column.label}</span>
                        </label>
                      )
                    })}
                  </div>
                </div>
              ) : null}
            </div>
            {isExporting ? (
              <div className="space-y-2 rounded-xl border border-slate-200 bg-white/80 px-4 py-3">
                <div className="flex items-center justify-between text-sm font-medium text-neutral-700">
                  <span>Gerando planilha...</span>
                  <span>{Math.min(100, Math.max(0, Math.round(exportProgress)))}%</span>
                </div>
                <Progress value={exportProgress} className="h-2" />
              </div>
            ) : null}
            {exportError ? <p className="text-sm text-destructive">{exportError}</p> : null}
          </div>
          <DialogFooter className="gap-2">
            <Button type="button" variant="outline" onClick={() => handleExportDialogOpenChange(false)} disabled={isExporting}>
              Cancelar
            </Button>
            <Button
              type="button"
              onClick={handleConfirmExport}
              disabled={isExporting || selectedColumnCount === 0 || exportableMachineIds.length === 0}
              className="gap-2"
            >
              {isExporting ? (
                <>
                  <Spinner className="mr-2 size-4" />
                  Exportando...
                </>
              ) : (
                "Exportar XLSX"
              )}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </div>
  )
}
