"use client"

import { useEffect, useMemo } from "react"
import { useQuery } from "convex/react"
import { format } from "date-fns"
import { ptBR } from "date-fns/locale"
import type { Id } from "@/convex/_generated/dataModel"
import {
  Area,
  AreaChart,
  Bar,
  BarChart,
  CartesianGrid,
  Cell,
  Label,
  Line,
  LineChart,
  Pie,
  PieChart,
  PolarAngleAxis,
  PolarGrid,
  PolarRadiusAxis,
  Radar,
  RadarChart,
  RadialBar,
  RadialBarChart,
  Tooltip as RechartsTooltip,
  XAxis,
  YAxis,
} from "recharts"
import sanitizeHtml from "sanitize-html"

import { api } from "@/convex/_generated/api"
import { DEFAULT_TENANT_ID } from "@/lib/constants"
import { useAuth } from "@/lib/auth-client"
import { getTicketPriorityLabel } from "@/lib/ticket-priority-style"
import { getTicketStatusChipClass, getTicketStatusLabel } from "@/lib/ticket-status-style"
import { cn } from "@/lib/utils"
import type { TicketQueueSummary } from "@/lib/schemas/ticket"
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "@/components/ui/card"
import { Badge } from "@/components/ui/badge"
import { Skeleton } from "@/components/ui/skeleton"
import {
  ChartConfig,
  ChartContainer,
  ChartLegend,
  ChartLegendContent,
  ChartTooltip,
  ChartTooltipContent,
} from "@/components/ui/chart"
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table"
import { TicketQueueSummaryCards } from "@/components/tickets/ticket-queue-summary"

const numberFormatter = new Intl.NumberFormat("pt-BR", { maximumFractionDigits: 1 })
const percentFormatter = new Intl.NumberFormat("pt-BR", { style: "percent", maximumFractionDigits: 1 })

const CHART_COLORS = ["var(--chart-1)", "var(--chart-2)", "var(--chart-3)", "var(--chart-4)", "var(--chart-5)"]
const DEFAULT_CHART_HEIGHT = 320
// Em modo apresentação o card já define a altura disponível; evitar valores fixos previne cortes.
const PRESENTATION_CHART_HEIGHT = 0
const TIMESTAMP_THRESHOLD = 1_000_000_000
const STATUS_CHIP_BASE_CLASS = "inline-flex items-center gap-2 rounded-full px-4 py-2 text-sm font-semibold transition"
const KNOWN_TICKET_STATUSES = new Set(["PENDING", "AWAITING_ATTENDANCE", "PAUSED", "RESOLVED"])

export type DashboardFilters = {
  range?: "7d" | "30d" | "90d" | "custom"
  from?: string | null
  to?: string | null
  companyId?: string | null
  queueId?: string | null
}

export type WidgetConfig = {
  type?: string
  title?: string
  description?: string
  dataSource?: {
    metricKey?: string
    params?: Record<string, unknown>
  }
  encoding?: {
    x?: string
    y?: Array<{ field: string; label?: string }>
    category?: string
    value?: string
    stacked?: boolean
    angle?: string
    radius?: string
  }
  options?: Record<string, unknown>
  columns?: Array<{ field: string; label: string }>
  content?: string
}

type TableColumnConfig = { field: string; label: string }

export type DashboardWidgetRecord = {
  id: Id<"dashboardWidgets">
  widgetKey: string
  type: string
  title: string | null
  config: WidgetConfig | Record<string, unknown>
}

type WidgetRendererProps = {
  widget: DashboardWidgetRecord
  filters: DashboardFilters
  mode?: "edit" | "view" | "tv" | "print"
  onReadyChange?: (ready: boolean) => void
}

type UseMetricDataArgs = {
  metricKey?: string | null
  params?: Record<string, unknown>
  enabled?: boolean
}

type MetricResult = {
  data: unknown
  meta: { kind: string; [key: string]: unknown } | null
  isLoading: boolean
  isError: boolean
}

function normalizeParams(raw?: Record<string, unknown>) {
  if (!raw) return undefined
  const next: Record<string, unknown> = {}
  for (const [key, value] of Object.entries(raw)) {
    if (value === undefined) continue
    if (value === null) continue
    if (typeof value === "string" && value.trim().length === 0) continue
    if (Array.isArray(value)) {
      const filtered = value.filter((entry) => entry !== undefined && entry !== null)
      if (filtered.length === 0) continue
      next[key] = filtered
      continue
    }
    next[key] = value
  }
  return Object.keys(next).length > 0 ? next : undefined
}

function mergeFilterParams(base: Record<string, unknown> | undefined, filters: DashboardFilters) {
  if (!filters) return base
  const merged: Record<string, unknown> = { ...(base ?? {}) }
  if (filters.range) {
    if (filters.range === "custom") {
      if (filters.from) merged.from = filters.from
      if (filters.to) merged.to = filters.to
      delete merged.range
    } else {
      merged.range = filters.range
      delete merged.from
      delete merged.to
    }
  }
  if (filters.companyId && filters.companyId !== "all") {
    merged.companyId = filters.companyId
  } else if (filters.companyId === "all") {
    delete merged.companyId
  }
  if (filters.queueId) {
    merged.queueId = filters.queueId
  }
  return merged
}

function useMetricData({ metricKey, params, enabled = true }: UseMetricDataArgs): MetricResult {
  const { session, convexUserId, isStaff } = useAuth()
  const tenantId = session?.user.tenantId ?? DEFAULT_TENANT_ID
  const shouldFetch = Boolean(enabled && metricKey && isStaff && convexUserId)
  const normalized = useMemo(() => normalizeParams(params), [params])
  const result = useQuery(
    api.metrics.run,
    shouldFetch
      ? ({
          tenantId,
          viewerId: convexUserId as Id<"users">,
          metricKey: metricKey as string,
          params: normalized,
        } as const)
      : "skip",
  ) as { data: unknown; meta: { kind: string; [key: string]: unknown } } | undefined
  const isLoading = shouldFetch && result === undefined
  const meta = result?.meta ?? null
  const isError = Boolean(meta && meta.kind === "error")
  return {
    data: result?.data,
    meta,
    isLoading,
    isError,
  }
}

function normalizeWidgetConfig(widget: DashboardWidgetRecord): WidgetConfig {
  const raw = widget.config
  if (raw && typeof raw === "object") {
    return { type: widget.type, ...raw } as WidgetConfig
  }
  return { type: widget.type, title: widget.title ?? undefined }
}

function needsMetricData(type: string) {
  return type !== "text"
}

function formatDateLabel(value: unknown) {
  if (typeof value === "number") {
    return format(new Date(value), "dd MMM", { locale: ptBR })
  }
  if (typeof value === "string") {
    const trimmed = value.trim()
    if (/^\d{4}-\d{2}-\d{2}$/.test(trimmed)) {
      const date = new Date(trimmed + "T00:00:00Z")
      if (!Number.isNaN(date.getTime())) {
        return format(date, "dd MMM", { locale: ptBR })
      }
    }
    return trimmed
  }
  return String(value ?? "")
}

function parseNumeric(value: unknown): number | null {
  if (typeof value === "number" && Number.isFinite(value)) return value
  if (typeof value === "string") {
    const parsed = Number(value)
    if (Number.isFinite(parsed)) return parsed
  }
  return null
}

type ValueFormatterKind = "number" | "percent"

function formatMetricValue(value: unknown, format: ValueFormatterKind = "number") {
  const numeric = parseNumeric(value)
  if (numeric === null) return "—"
  return format === "percent" ? percentFormatter.format(numeric) : numberFormatter.format(numeric)
}

function resolveChartOptions(
  config: WidgetConfig,
  defaults: { indicator: "line" | "dot" | "dashed" },
): {
  showLegend: boolean
  showTooltip: boolean
  indicator: "line" | "dot" | "dashed"
  valueFormatter: ValueFormatterKind
} {
  const options = (config.options ?? {}) as Record<string, unknown>
  const showLegend = options.legend !== false
  const showTooltip = options.tooltip !== false
  const indicator =
    typeof options.indicator === "string" && (options.indicator === "line" || options.indicator === "dot" || options.indicator === "dashed")
      ? (options.indicator as "line" | "dot" | "dashed")
      : defaults.indicator
  const valueFormatter: ValueFormatterKind = options.valueFormatter === "percent" ? "percent" : "number"
  return { showLegend, showTooltip, indicator, valueFormatter }
}

export function WidgetRenderer({ widget, filters, mode = "edit", onReadyChange }: WidgetRendererProps) {
  const config = normalizeWidgetConfig(widget)
  const widgetType = (config.type ?? widget.type ?? "text").toLowerCase()
  const title = config.title ?? widget.title ?? "Widget"
  const description = config.description
  const mergedParams = mergeFilterParams(config.dataSource?.params, filters)
  const metric = useMetricData({
    metricKey: config.dataSource?.metricKey,
    params: mergedParams,
    enabled: needsMetricData(widgetType),
  })
  const trendMetric = useMetricData({
    metricKey: typeof config.options?.trend === "string" ? (config.options.trend as string) : undefined,
    params: mergedParams,
    enabled: widgetType === "kpi" && Boolean(config.options?.trend),
  })

  useEffect(() => {
    if (!needsMetricData(widgetType)) {
      onReadyChange?.(true)
      return
    }
    if (widgetType === "kpi" && config.options?.trend) {
      onReadyChange?.(!metric.isLoading && !trendMetric.isLoading && !metric.isError && !trendMetric.isError)
    } else {
      onReadyChange?.(!metric.isLoading && !metric.isError)
    }
  }, [
    widgetType,
    config.options?.trend,
    metric.isLoading,
    metric.isError,
    trendMetric.isLoading,
    trendMetric.isError,
    onReadyChange,
  ])

  const isLoading = metric.isLoading || (widgetType === "kpi" && Boolean(config.options?.trend) && trendMetric.isLoading)
  const isError = metric.isError
  const resolvedTitle = title

  if (isError) {
    return (
      <Card className="h-full border-destructive/50 bg-destructive/5">
        <CardHeader>
          <CardTitle className="text-destructive">{resolvedTitle}</CardTitle>
          {description ? <CardDescription>{description}</CardDescription> : null}
        </CardHeader>
        <CardContent className="text-sm text-destructive">
          Não foi possível carregar esta métrica. Verifique a configuração.
        </CardContent>
      </Card>
    )
  }

  switch (widgetType) {
    case "kpi":
      return renderKpi({
        title: resolvedTitle,
        description,
        metric,
        trend: trendMetric,
        mode,
      })
    case "bar":
      return renderBarChart({
        title: resolvedTitle,
        description,
        metric,
        config,
        mode,
      })
    case "line":
      return renderLineChart({
        title: resolvedTitle,
        description,
        metric,
        config,
        mode,
      })
    case "area":
      return renderAreaChart({
        title: resolvedTitle,
        description,
        metric,
        config,
        mode,
      })
    case "pie":
      return renderPieChart({
        title: resolvedTitle,
        description,
        metric,
        config,
        mode,
      })
    case "radar":
      return renderRadarChart({
        title: resolvedTitle,
        description,
        metric,
        config,
        mode,
      })
    case "gauge":
      return renderGauge({
        title: resolvedTitle,
        description,
        metric,
        config,
        mode,
      })
    case "table":
      return renderTable({
        title: resolvedTitle,
        description,
        metric,
        config,
        isLoading,
        mode,
      })
    case "queue-summary":
      return renderQueueSummary({
        title: resolvedTitle,
        description,
        metric,
        isLoading,
      })
    case "text":
    default:
      return renderText({
        title: resolvedTitle,
        description,
        content: config.content ?? "",
      })
  }
}

type WidgetCardProps = {
  title: string
  description?: string
  children: React.ReactNode
  isLoading?: boolean
}

function WidgetCard({ title, description, children, isLoading }: WidgetCardProps) {
  return (
    <Card className="group flex h-full flex-col rounded-2xl border border-border/60 bg-gradient-to-br from-white via-white to-slate-100 shadow-sm transition hover:-translate-y-0.5 hover:border-slate-300 hover:shadow-lg">
      <CardHeader className="flex-none pb-3">
        <CardTitle className="text-base font-semibold">{title}</CardTitle>
        {description ? <CardDescription>{description}</CardDescription> : null}
      </CardHeader>
      <CardContent className="flex-1 overflow-visible pb-4 pt-0">
        {isLoading ? (
          <Skeleton className="h-full min-h-[240px] w-full rounded-xl animate-pulse" />
        ) : (
          <div className="h-full">{children}</div>
        )}
      </CardContent>
    </Card>
  )
}

function renderKpi({
  title,
  description,
  metric,
  trend,
  mode,
}: {
  title: string
  description?: string
  metric: MetricResult
  trend: MetricResult
  mode: "edit" | "view" | "tv" | "print"
}) {
  const data = metric.data as { value?: number; atRisk?: number } | null
  const value = parseNumeric(data?.value) ?? 0
  const atRisk = parseNumeric(data?.atRisk) ?? 0
  const trendValue = parseNumeric((trend.data as { value?: number } | null)?.value)
  const delta = trendValue !== null ? value - trendValue : null
  const isTv = mode === "tv"
  return (
    <Card
      className={cn(
        "flex h-full flex-col rounded-2xl border bg-gradient-to-br shadow-sm transition hover:-translate-y-0.5 hover:border-slate-300 hover:shadow-xl",
        isTv
          ? "border-slate-400/60 from-slate-900 via-slate-800 to-slate-700 text-white"
          : "border-slate-200 from-white via-white to-slate-100 text-neutral-900"
      )}
    >
      <CardHeader className="flex-none pb-1">
        <CardDescription className="text-xs uppercase tracking-wide text-muted-foreground">
          {description ?? "Indicador chave"}
        </CardDescription>
        <CardTitle className={cn("text-2xl font-semibold", isTv ? "text-4xl" : "")}>{title}</CardTitle>
      </CardHeader>
      <CardContent className="flex-1 space-y-3">
        <div className={cn("font-semibold text-4xl", isTv ? "text-6xl" : "text-4xl")}>{numberFormatter.format(value)}</div>
        <div className={cn("flex flex-wrap items-center gap-2 text-sm text-muted-foreground", isTv ? "text-slate-200" : "")}>
          <Badge
            variant={atRisk > 0 ? "destructive" : "secondary"}
            className={cn(
              "rounded-full px-3 py-1 text-xs",
              atRisk > 0 ? "" : "border-none bg-white/70 text-foreground"
            )}
          >
            {atRisk > 0 ? `${numberFormatter.format(atRisk)} em risco` : "Todos no prazo"}
          </Badge>
          {delta !== null ? (
            <span className={cn("font-medium", delta >= 0 ? "text-emerald-600" : "text-destructive")}>
              {delta >= 0 ? "+" : ""}
              {numberFormatter.format(delta)} vs período anterior
            </span>
          ) : null}
        </div>
      </CardContent>
    </Card>
  )
}

function renderBarChart({
  title,
  description,
  metric,
  config,
  mode,
}: {
  title: string
  description?: string
  metric: MetricResult
  config: WidgetConfig
  mode: WidgetRendererProps["mode"]
}) {
  const xKey = config.encoding?.x ?? "date"
  const series = Array.isArray(config.encoding?.y) ? config.encoding?.y ?? [] : []
  const chartData = Array.isArray(metric.data) ? (metric.data as Array<Record<string, unknown>>) : []
  const chartConfig = series.reduce<Record<string, { label?: string; color?: string }>>((acc, serie, index) => {
    acc[serie.field] = {
      label: serie.label ?? serie.field,
      color: CHART_COLORS[index % CHART_COLORS.length],
    }
    return acc
  }, {})
  const { showLegend, showTooltip, indicator, valueFormatter } = resolveChartOptions(config, { indicator: "dot" })
  const tooltipValueFormatter = (value: unknown) => formatMetricValue(value, valueFormatter)
  const yAxisTickFormatter =
    valueFormatter === "percent" ? (value: number) => percentFormatter.format(value) : undefined
  const allowDecimals = valueFormatter === "percent"
  const isPresentation = mode === "tv" || mode === "print"
  const minHeight = isPresentation ? PRESENTATION_CHART_HEIGHT : DEFAULT_CHART_HEIGHT
  const legendPadClass = isPresentation ? "pb-8" : "pb-6"

  return (
    <WidgetCard title={title} description={description} isLoading={metric.isLoading}>
      {chartData.length === 0 ? (
        <EmptyState />
      ) : (
        <ChartContainer
          config={chartConfig as ChartConfig}
          className={cn(
            "group/chart h-full w-full px-2",
            legendPadClass,
            "[&_.recharts-legend-wrapper]:px-2 [&_.recharts-legend-wrapper]:pb-1",
            "[&_.recharts-default-legend]:flex [&_.recharts-default-legend]:flex-wrap [&_.recharts-default-legend]:justify-center",
          )}
          style={{ minHeight, height: "100%", overflow: "visible" }}
        >
          <BarChart data={chartData} accessibilityLayer>
            <CartesianGrid vertical={false} strokeDasharray="3 3" />
            <XAxis
              dataKey={xKey}
              tickLine={false}
              axisLine={false}
              tickMargin={8}
              minTickGap={24}
              tickFormatter={formatDateLabel}
            />
            <YAxis allowDecimals={allowDecimals} tickFormatter={yAxisTickFormatter} />
            {showTooltip ? (
              <ChartTooltip
                cursor={false}
                content={<ChartTooltipContent indicator={indicator} valueFormatter={(value) => tooltipValueFormatter(value)} />}
              />
            ) : null}
            {showLegend ? (
              <ChartLegend
                content={<ChartLegendContent className="flex flex-wrap justify-center gap-3 px-2 pb-1" />}
              />
            ) : null}
            {series.map((serie, index) => (
              <Bar
                key={serie.field}
                dataKey={serie.field}
                fill={`var(--color-${serie.field})`}
                radius={6}
                stackId={config.encoding?.stacked ? "stack" : undefined}
                animationDuration={400}
              />
            ))}
          </BarChart>
        </ChartContainer>
      )}
    </WidgetCard>
  )
}

function renderLineChart({
  title,
  description,
  metric,
  config,
  mode,
}: {
  title: string
  description?: string
  metric: MetricResult
  config: WidgetConfig
  mode: WidgetRendererProps["mode"]
}) {
  const xKey = config.encoding?.x ?? "date"
  const series = Array.isArray(config.encoding?.y) ? config.encoding?.y ?? [] : []
  const chartData = Array.isArray(metric.data) ? (metric.data as Array<Record<string, unknown>>) : []
  const chartConfig = series.reduce<Record<string, { label?: string; color?: string }>>((acc, serie, index) => {
    acc[serie.field] = {
      label: serie.label ?? serie.field,
      color: CHART_COLORS[index % CHART_COLORS.length],
    }
    return acc
  }, {})
  const { showLegend, showTooltip, indicator, valueFormatter } = resolveChartOptions(config, { indicator: "line" })
  const tooltipValueFormatter = (value: unknown) => formatMetricValue(value, valueFormatter)
  const allowDecimals = valueFormatter === "percent"
  const yAxisTickFormatter =
    valueFormatter === "percent" ? (value: number) => percentFormatter.format(value) : undefined
  const isPresentation = mode === "tv" || mode === "print"
  const minHeight = isPresentation ? PRESENTATION_CHART_HEIGHT : DEFAULT_CHART_HEIGHT
  const legendPadClass = isPresentation ? "pb-8" : "pb-6"

  return (
    <WidgetCard title={title} description={description} isLoading={metric.isLoading}>
      {chartData.length === 0 ? (
        <EmptyState />
      ) : (
        <ChartContainer
          config={chartConfig as ChartConfig}
          className={cn(
            "group/chart h-full w-full px-2",
            legendPadClass,
            "[&_.recharts-legend-wrapper]:px-2 [&_.recharts-legend-wrapper]:pb-1",
            "[&_.recharts-default-legend]:flex [&_.recharts-default-legend]:flex-wrap [&_.recharts-default-legend]:justify-center",
          )}
          style={{ minHeight, height: "100%", overflow: "visible" }}
        >
          <LineChart data={chartData} accessibilityLayer>
            <CartesianGrid strokeDasharray="3 3" />
            <XAxis dataKey={xKey} tickFormatter={formatDateLabel} />
            <YAxis allowDecimals={allowDecimals} tickFormatter={yAxisTickFormatter} />
            {showTooltip ? (
              <ChartTooltip
                cursor={false}
                content={<ChartTooltipContent indicator={indicator} valueFormatter={(value) => tooltipValueFormatter(value)} />}
              />
            ) : null}
            {showLegend ? (
              <ChartLegend
                content={<ChartLegendContent className="flex flex-wrap justify-center gap-3 px-2 pb-1" />}
              />
            ) : null}
            {series.map((serie, index) => (
              <Line
                key={serie.field}
                type="monotone"
                dataKey={serie.field}
                stroke={`var(--color-${serie.field})`}
                strokeWidth={2}
                dot={{ r: 3 }}
                animationDuration={400}
              />
            ))}
          </LineChart>
        </ChartContainer>
      )}
    </WidgetCard>
  )
}

function renderAreaChart({
  title,
  description,
  metric,
  config,
  mode,
}: {
  title: string
  description?: string
  metric: MetricResult
  config: WidgetConfig
  mode: WidgetRendererProps["mode"]
}) {
  const xKey = config.encoding?.x ?? "date"
  const series = Array.isArray(config.encoding?.y) ? config.encoding?.y ?? [] : []
  const chartData = Array.isArray(metric.data) ? (metric.data as Array<Record<string, unknown>>) : []
  const stacked = Boolean(config.encoding?.stacked)
  const chartConfig = series.reduce<Record<string, { label?: string; color?: string }>>((acc, serie, index) => {
    acc[serie.field] = {
      label: serie.label ?? serie.field,
      color: CHART_COLORS[index % CHART_COLORS.length],
    }
    return acc
  }, {})
  const { showLegend, showTooltip, indicator, valueFormatter } = resolveChartOptions(config, { indicator: "line" })
  const tooltipValueFormatter = (value: unknown) => formatMetricValue(value, valueFormatter)
  const allowDecimals = valueFormatter === "percent"
  const yAxisTickFormatter =
    valueFormatter === "percent" ? (value: number) => percentFormatter.format(value) : undefined
  const isPresentation = mode === "tv" || mode === "print"
  const minHeight = isPresentation ? PRESENTATION_CHART_HEIGHT : DEFAULT_CHART_HEIGHT
  const legendPadClass = isPresentation ? "pb-8" : "pb-6"

  return (
    <WidgetCard title={title} description={description} isLoading={metric.isLoading}>
      {chartData.length === 0 ? (
        <EmptyState />
      ) : (
        <ChartContainer
          config={chartConfig as ChartConfig}
          className={cn(
            "group/chart h-full w-full px-2",
            legendPadClass,
            "[&_.recharts-legend-wrapper]:px-2 [&_.recharts-legend-wrapper]:pb-1",
            "[&_.recharts-default-legend]:flex [&_.recharts-default-legend]:flex-wrap [&_.recharts-default-legend]:justify-center",
          )}
          style={{ minHeight, height: "100%", overflow: "visible" }}
        >
          <AreaChart data={chartData} accessibilityLayer>
            <defs>
              {series.map((serie, index) => (
                <linearGradient key={serie.field} id={`fill-${serie.field}`} x1="0" y1="0" x2="0" y2="1">
                  <stop offset="5%" stopColor={`var(--color-${serie.field})`} stopOpacity={0.8} />
                  <stop offset="95%" stopColor={`var(--color-${serie.field})`} stopOpacity={0.1} />
                </linearGradient>
              ))}
            </defs>
            <CartesianGrid vertical={false} strokeDasharray="3 3" />
            <XAxis dataKey={xKey} tickFormatter={formatDateLabel} />
            <YAxis allowDecimals={allowDecimals} tickFormatter={yAxisTickFormatter} />
            {showTooltip ? (
              <ChartTooltip
                cursor={false}
                content={<ChartTooltipContent indicator={indicator} valueFormatter={(value) => tooltipValueFormatter(value)} />}
              />
            ) : null}
            {showLegend ? (
              <ChartLegend
                content={<ChartLegendContent className="flex flex-wrap justify-center gap-3 px-2 pb-1" />}
              />
            ) : null}
            {series.map((serie, index) => (
              <Area
                key={serie.field}
                type="natural"
                dataKey={serie.field}
                fill={`url(#fill-${serie.field})`}
                stroke={`var(--color-${serie.field})`}
                stackId={stacked ? "stack" : undefined}
                strokeWidth={2}
                animationDuration={400}
              />
            ))}
          </AreaChart>
        </ChartContainer>
      )}
    </WidgetCard>
  )
}

function renderPieChart({
  title,
  description,
  metric,
  config,
  mode,
}: {
  title: string
  description?: string
  metric: MetricResult
  config: WidgetConfig
  mode: WidgetRendererProps["mode"]
}) {
  const categoryKey = config.encoding?.category ?? "name"
  const valueKey = config.encoding?.value ?? "value"
  const chartData = Array.isArray(metric.data) ? (metric.data as Array<Record<string, unknown>>) : []
  const { showLegend, showTooltip, indicator, valueFormatter } = resolveChartOptions(config, { indicator: "dot" })
  const tooltipValueFormatter = (value: unknown) => formatMetricValue(value, valueFormatter)
  const isPresentation = mode === "tv" || mode === "print"
  const minHeight = isPresentation ? PRESENTATION_CHART_HEIGHT : DEFAULT_CHART_HEIGHT
  const legendPadClass = isPresentation ? "pb-8" : "pb-6"
  return (
    <WidgetCard title={title} description={description} isLoading={metric.isLoading}>
      {chartData.length === 0 ? (
        <EmptyState />
      ) : (
        <ChartContainer
          config={chartData.reduce<Record<string, { label?: string; color?: string }>>((acc, item, index) => {
            const key = String(item[categoryKey] ?? index)
            acc[key] = { label: key, color: CHART_COLORS[index % CHART_COLORS.length] }
            return acc
          }, {}) as ChartConfig}
          className={cn(
            "group/chart flex h-full w-full items-center justify-center px-2",
            legendPadClass,
            "[&_.recharts-legend-wrapper]:px-2 [&_.recharts-legend-wrapper]:pb-1",
            "[&_.recharts-default-legend]:flex [&_.recharts-default-legend]:flex-wrap [&_.recharts-default-legend]:justify-center",
          )}
          style={{ minHeight, height: "100%", overflow: "visible" }}
        >
          <PieChart>
            {showTooltip ? (
              <ChartTooltip
                cursor={false}
                content={<ChartTooltipContent hideLabel indicator={indicator} valueFormatter={(value) => tooltipValueFormatter(value)} />}
              />
            ) : null}
            <Pie
              data={chartData}
              dataKey={valueKey}
              nameKey={categoryKey}
              innerRadius={55}
              outerRadius={110}
              strokeWidth={5}
            >
              {chartData.map((entry, index) => (
                <Cell key={index} fill={CHART_COLORS[index % CHART_COLORS.length]} />
              ))}
            </Pie>
            {showLegend ? (
              <ChartLegend
                content={<ChartLegendContent className="flex flex-wrap justify-center gap-3 px-2 pb-1" />}
              />
            ) : null}
          </PieChart>
        </ChartContainer>
      )}
    </WidgetCard>
  )
}

function renderRadarChart({
  title,
  description,
  metric,
  config,
  mode,
}: {
  title: string
  description?: string
  metric: MetricResult
  config: WidgetConfig
  mode: WidgetRendererProps["mode"]
}) {
  const angleKey = config.encoding?.angle ?? "label"
  const radiusKey = config.encoding?.radius ?? "value"
  const chartData = Array.isArray(metric.data) ? (metric.data as Array<Record<string, unknown>>) : []
  const { showLegend, showTooltip, indicator, valueFormatter } = resolveChartOptions(config, { indicator: "line" })
  const tooltipValueFormatter = (value: unknown) => formatMetricValue(value, valueFormatter)
  const isPresentation = mode === "tv" || mode === "print"
  const minHeight = isPresentation ? PRESENTATION_CHART_HEIGHT : DEFAULT_CHART_HEIGHT
  const legendPadClass = isPresentation ? "pb-8" : "pb-6"
  return (
    <WidgetCard title={title} description={description} isLoading={metric.isLoading}>
      {chartData.length === 0 ? (
        <EmptyState />
      ) : (
        <ChartContainer
          config={{ [radiusKey]: { label: radiusKey, color: "var(--chart-1)" } }}
          className={cn(
            "group/chart flex h-full w-full items-center justify-center px-2",
            legendPadClass,
            "[&_.recharts-legend-wrapper]:px-2 [&_.recharts-legend-wrapper]:pb-1",
            "[&_.recharts-default-legend]:flex [&_.recharts-default-legend]:flex-wrap [&_.recharts-default-legend]:justify-center",
          )}
          style={{ minHeight, height: "100%", overflow: "visible" }}
        >
          <RadarChart data={chartData} accessibilityLayer>
            <PolarGrid />
            <PolarAngleAxis dataKey={angleKey} />
            <PolarRadiusAxis />
            {showTooltip ? (
              <ChartTooltip
                cursor={false}
                content={<ChartTooltipContent indicator={indicator} valueFormatter={(value) => tooltipValueFormatter(value)} />}
              />
            ) : null}
            {showLegend ? (
              <ChartLegend
                content={<ChartLegendContent className="flex flex-wrap justify-center gap-3 px-2 pb-1" />}
              />
            ) : null}
            <Radar
              dataKey={radiusKey}
              stroke="var(--chart-1)"
              fill="var(--chart-1)"
              fillOpacity={0.4}
            />
          </RadarChart>
        </ChartContainer>
      )}
    </WidgetCard>
  )
}

function renderGauge({
  title,
  description,
  metric,
  config,
  mode,
}: {
  title: string
  description?: string
  metric: MetricResult
  config: WidgetConfig
  mode: WidgetRendererProps["mode"]
}) {
  const raw = metric.data as { value?: number; total?: number; resolved?: number } | null
  const value = parseNumeric(raw?.value) ?? 0
  const display = Math.max(0, Math.min(1, value))
  const isPresentation = mode === "tv" || mode === "print"
  const minHeight = isPresentation ? PRESENTATION_CHART_HEIGHT : DEFAULT_CHART_HEIGHT
  const legendPadClass = isPresentation ? "pb-8" : "pb-6"
  return (
    <WidgetCard title={title} description={description} isLoading={metric.isLoading}>
      <ChartContainer
        config={{ value: { label: "SLA", color: "var(--chart-1)" } }}
        className={cn(
          "group/chart flex h-full w-full items-center justify-center px-2",
          legendPadClass,
          "[&_.recharts-legend-wrapper]:px-2 [&_.recharts-legend-wrapper]:pb-1",
          "[&_.recharts-default-legend]:flex [&_.recharts-default-legend]:flex-wrap [&_.recharts-default-legend]:justify-center",
        )}
        style={{ minHeight, height: "100%", overflow: "visible" }}
      >
        <RadialBarChart
          startAngle={180}
          endAngle={0}
          innerRadius={60}
          outerRadius={110}
          data={[{ name: "SLA", value: display }]}
        >
          <RadialBar background dataKey="value" cornerRadius={5} fill="var(--color-value)" />
          <RechartsTooltip
            cursor={false}
            content={<ChartTooltipContent hideLabel valueFormatter={(val) => percentFormatter.format(Number(val ?? 0))} />}
          />
          <Label
            content={({ viewBox }) => {
              if (!viewBox || !("cx" in viewBox) || !("cy" in viewBox)) return null
              return (
                <text x={viewBox.cx} y={viewBox.cy} textAnchor="middle" dominantBaseline="middle">
                  <tspan x={viewBox.cx} y={(viewBox.cy ?? 0) - 8} className="fill-foreground text-3xl font-semibold">
                    {percentFormatter.format(display)}
                  </tspan>
                  <tspan x={viewBox.cx} y={(viewBox.cy ?? 0) + 16} className="fill-muted-foreground text-sm">
                    Cumprimento
                  </tspan>
                </text>
              )
            }}
          />
        </RadialBarChart>
      </ChartContainer>
    </WidgetCard>
  )
}

function renderTable({
  title,
  description,
  metric,
  config,
  isLoading,
  mode,
}: {
  title: string
  description?: string
  metric: MetricResult
  config: WidgetConfig
  isLoading: boolean
  mode: WidgetRendererProps["mode"]
}) {
  const columns: TableColumnConfig[] = Array.isArray(config.columns) && config.columns.length > 0
    ? (config.columns as TableColumnConfig[])
    : [
        { field: "subject", label: "Assunto" },
        { field: "status", label: "Status" },
        { field: "updatedAt", label: "Atualizado em" },
      ]
  const columnsToRender = isRecentTicketsTable(config)
    ? columns.filter((column) => !isPriorityColumn(column))
    : columns
  const rows = Array.isArray(metric.data) ? (metric.data as Array<Record<string, unknown>>) : []
  const isPresentation = mode === "tv" || mode === "print"
  const containerClass = cn(
    "flex h-full flex-col overflow-hidden rounded-xl border border-border/60 bg-white/80",
    isPresentation ? "min-h-[320px]" : "min-h-[260px]",
  )
  const scrollClass = cn(
    "overflow-x-hidden overflow-y-auto",
    isPresentation ? "max-h-none" : "max-h-[360px]",
  )
  return (
    <WidgetCard title={title} description={description} isLoading={isLoading}>
      {rows.length === 0 ? (
        <EmptyState />
      ) : (
        <div className={containerClass}>
          <div className={scrollClass}>
            <Table className="min-w-full table-fixed">
              <TableHeader>
                <TableRow>
                  {columnsToRender.map((column) => (
                    <TableHead key={column.field} className="whitespace-nowrap">
                      {column.label}
                    </TableHead>
                  ))}
                </TableRow>
              </TableHeader>
              <TableBody>
                {rows.map((row, index) => (
                  <TableRow key={index} className="border-b border-border/60 transition hover:bg-muted/40">
                    {columnsToRender.map((column) => {
                      const cellValue = row[column.field as keyof typeof row]
                      return (
                        <TableCell key={column.field} className="whitespace-normal break-words">
                          {renderTableCellValue(cellValue, column)}
                        </TableCell>
                      )
                    })}
                  </TableRow>
                ))}
              </TableBody>
            </Table>
          </div>
        </div>
      )}
    </WidgetCard>
  )
}

function renderQueueSummary({
  title,
  description,
  metric,
  isLoading,
}: {
  title: string
  description?: string
  metric: MetricResult
  isLoading: boolean
}) {
  const queues = Array.isArray(metric.data) ? (metric.data as TicketQueueSummary[]) : []
  return (
    <WidgetCard title={title} description={description} isLoading={isLoading}>
      {queues.length === 0 ? (
        <EmptyState />
      ) : (
        <div className="pb-1">
          <TicketQueueSummaryCards queues={queues} layout="compact" />
        </div>
      )}
    </WidgetCard>
  )
}

function renderTableCellValue(value: unknown, column?: TableColumnConfig) {
  if (value === null || value === undefined) {
    return "—"
  }
  const enriched = renderTicketTableCell(value, column)
  if (enriched) {
    return enriched
  }
  if (isStatusColumn(column)) {
    return getTicketStatusLabel(value as string)
  }
  if (isPriorityColumn(column)) {
    return getTicketPriorityLabel(value as string)
  }
  if (value instanceof Date) {
    const formatted = tryFormatDate(value)
    if (formatted) return formatted
  }
  if (typeof value === "number") {
    if (isLikelyTimestampNumber(value, column)) {
      const formatted = tryFormatDate(value)
      if (formatted) return formatted
    }
    return numberFormatter.format(value)
  }
  if (typeof value === "string") {
    if (isLikelyTimestampString(value, column)) {
      const formatted = tryFormatDate(value)
      if (formatted) return formatted
    }
    return value
  }
  if (typeof value === "boolean") {
    return value ? "Sim" : "Não"
  }
  if (Array.isArray(value)) {
    return value.join(", ")
  }
  if (typeof value === "object") {
    try {
      return JSON.stringify(value)
    } catch {
      return "—"
    }
  }
  return String(value)
}

function renderTicketTableCell(value: unknown, column?: TableColumnConfig) {
  if (!column) return null
  if (isReferenceColumn(column)) {
    const reference = typeof value === "number" || typeof value === "string" ? String(value) : null
    return (
      <Badge className="rounded-full border border-slate-200 bg-white px-3 py-1.5 text-xs font-semibold text-neutral-700">
        {reference ? `#${reference}` : "—"}
      </Badge>
    )
  }
  if (isStatusColumn(column) && isTicketStatusValue(value)) {
    return (
      <span className={cn(STATUS_CHIP_BASE_CLASS, getTicketStatusChipClass(String(value)))}>
        {getTicketStatusLabel(String(value))}
      </span>
    )
  }
  return null
}

function tryFormatDate(value: number | string | Date): string | null {
  const date = value instanceof Date ? value : new Date(value)
  if (Number.isNaN(date.getTime())) {
    return null
  }
  return format(date, "dd/MM/yyyy HH:mm", { locale: ptBR })
}

function isReferenceColumn(column?: TableColumnConfig) {
  if (!column) return false
  const field = column.field.toLowerCase()
  const label = column.label.toLowerCase()
  return field === "reference" || field === "ref" || label.includes("ref")
}

function isRecentTicketsTable(config: WidgetConfig) {
  return config?.dataSource?.metricKey === "tickets.awaiting_table"
}

function isStatusColumn(column?: TableColumnConfig) {
  if (!column) return false
  const field = column.field.toLowerCase()
  const label = column.label.toLowerCase()
  return field === "status" || label.includes("status") || label.includes("situação")
}

function isPriorityColumn(column?: TableColumnConfig) {
  if (!column) return false
  const field = column.field.toLowerCase()
  const label = column.label.toLowerCase()
  return field === "priority" || label.includes("prioridade")
}

function isTicketStatusValue(value: unknown): value is string {
  if (typeof value !== "string") return false
  return KNOWN_TICKET_STATUSES.has(value.toUpperCase())
}

function hasDateHint(column?: TableColumnConfig) {
  if (!column) return false
  const field = column.field.toLowerCase()
  const label = column.label.toLowerCase()
  return (
    field.endsWith("at") ||
    field.includes("date") ||
    field.includes("time") ||
    field.includes("due") ||
    label.includes("data") ||
    label.includes("hora") ||
    label.includes("atualiz") ||
    label.includes("criad") ||
    label.includes("resolvido") ||
    label.includes("prazo")
  )
}

function isLikelyTimestampNumber(value: number, column?: TableColumnConfig) {
  if (!Number.isFinite(value) || value <= 0) return false
  return value >= TIMESTAMP_THRESHOLD || hasDateHint(column)
}

function isLikelyTimestampString(value: string, column?: TableColumnConfig) {
  if (/^\d{4}-\d{2}-\d{2}T/.test(value) || /^\d{4}-\d{2}-\d{2}$/.test(value)) {
    return true
  }
  if (/^\d+$/.test(value)) {
    if (value.length >= 10) return true
    return hasDateHint(column)
  }
  if (hasDateHint(column)) {
    const parsed = Date.parse(value)
    return Number.isFinite(parsed)
  }
  return false
}

function renderText({
  title,
  description,
  content,
}: {
  title: string
  description?: string
  content: string
}) {
  const sanitized = sanitizeHtml(content, {
    allowedTags: ["b", "i", "strong", "em", "u", "p", "br", "ul", "ol", "li", "span"],
    allowedAttributes: { span: ["style"] },
  })
  return (
    <Card className="group flex h-full flex-col rounded-2xl border border-border/60 bg-gradient-to-br from-white via-white to-slate-100 shadow-sm transition hover:-translate-y-0.5 hover:border-slate-300 hover:shadow-lg">
      <CardHeader className="flex-none">
        <CardTitle className="text-base font-semibold">{title}</CardTitle>
        {description ? <CardDescription>{description}</CardDescription> : null}
      </CardHeader>
      <CardContent className="flex-1 pt-0">
        <div className="prose max-w-none rounded-xl bg-white/70 p-4 text-sm leading-relaxed text-muted-foreground shadow-inner transition group-hover:bg-white [&_ol]:list-decimal [&_ul]:list-disc">
          <div
            dangerouslySetInnerHTML={{
              __html:
                sanitized ||
                "<p>Adicione destaques, insights ou instruções para contextualizar os dados apresentados.</p>",
            }}
          />
        </div>
      </CardContent>
    </Card>
  )
}

function EmptyState() {
  return (
    <div className="flex h-full min-h-[160px] w-full flex-col items-center justify-center rounded-xl border-2 border-dashed border-slate-300 bg-slate-100 px-6 text-center text-sm font-medium text-slate-700 transition hover:border-slate-400 hover:bg-slate-200/70">
      Sem dados disponíveis para os filtros atuais.
    </div>
  )
}

export { useMetricData }
