"use client"

import { useMemo, useState } from "react"
import { type ColumnDef, getCoreRowModel, useReactTable } from "@tanstack/react-table"
import type { FlowAnalyticsDto, FlowBreakdownRow, FlowEntityCard, FlowPathRow, FlowTalkerDto } from "@mmapp/contracts/traffic-flow"
import { ArrowDownIcon, ArrowUpIcon, GitBranchIcon, GlobeIcon, LayersIcon, NetworkIcon, RouteIcon, ShieldIcon, UsersIcon } from "lucide-react"
import { Badge } from "@/components/reui/badge"
import { KpiStatGrid, type KpiStatItem } from "@/components/reui-kit/kpi-stat-grid"
import { TrafficRxTxChart } from "@/components/reui-kit/traffic-rx-tx-chart"
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
import { Switch } from "@/components/ui/switch"
import { Label } from "@/components/ui/label"
import { DataGridShell } from "@/components/data-grids/shared/data-grid-shell"
import {
  DATA_GRID_CELL_PAD,
  DATA_GRID_CELL_PAD_FIRST,
  DATA_GRID_CELL_PAD_LAST,
} from "@/components/data-grids/shared/data-grid-layout"
import { TrafficFlowsDataGrid } from "@/components/data-grids/traffic-flows-data-grid"
import { FlowTrafficMap } from "@/components/traffic/flow-traffic-map"
import { StatusDot } from "@/components/status-dot"
import { Flag } from "@/components/flag"
import { fmtRate } from "@/lib/fmt-rate"
import { cn } from "@/lib/utils"

function formatBytes(n: number): string {
  if (n >= 1_000_000_000) return `${(n / 1_000_000_000).toFixed(2)} ГБ`
  if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)} МБ`
  if (n >= 1000) return `${(n / 1000).toFixed(1)} КБ`
  return `${n} Б`
}

const RANGE_KEYS = ["5m", "15m", "1h", "4h", "24h", "30d"] as const
const RANGE_LABELS: Record<string, string> = {
  "5m": "5м",
  "15m": "15м",
  "1h": "1ч",
  "4h": "4ч",
  "24h": "24ч",
  "30d": "месяц",
}

function MiniAreaChart({ rx, tx, height = 44 }: { rx: number[]; tx: number[]; height?: number }) {
  const W = 300
  const H = height
  const maxVal = Math.max(...rx, ...tx, 1) * 1.1
  const xAt = (i: number) => (rx.length <= 1 ? 0 : (i / (rx.length - 1)) * W)
  const yAt = (v: number) => H - (v / maxVal) * H
  const area = (arr: number[]) => {
    const pts = arr.map((v, i) => `${xAt(i).toFixed(1)},${yAt(v).toFixed(1)}`).join(" L ")
    return `M 0,${H} L ${pts} L ${W},${H} Z`
  }
  const line = (arr: number[]) => arr.map((v, i) => `${xAt(i).toFixed(1)},${yAt(v).toFixed(1)}`).join(" ")
  return (
    <svg viewBox={`0 0 ${W} ${H}`} className="w-full h-11" preserveAspectRatio="none">
      <path d={area(rx)} fill="var(--chart-rx)" fillOpacity="0.15" />
      <polyline points={line(rx)} fill="none" stroke="var(--chart-rx)" strokeWidth="1.5" />
      {tx.some((v) => v > 0) ? (
        <polyline points={line(tx)} fill="none" stroke="var(--chart-tx)" strokeWidth="1.5" />
      ) : null}
    </svg>
  )
}

export function FlowEntityCardView({
  card,
  selected,
  onClick,
}: {
  card: FlowEntityCard
  selected: boolean
  onClick: () => void
}) {
  return (
    <button
      type="button"
      onClick={onClick}
      className={cn(
        "text-left w-full rounded-lg border p-3 transition-colors hover:bg-muted/50",
        selected ? "border-primary bg-primary/5" : "border-border bg-card",
        card.status === "offline" && "opacity-60",
      )}
    >
      <div className="flex items-center justify-between gap-2 mb-2">
        <div className="flex items-center gap-1.5 min-w-0">
          <StatusDot status={card.status} />
          <span className="text-xs font-medium truncate">{card.name}</span>
        </div>
        <span className="text-[10px] font-mono text-muted-foreground shrink-0 flex items-center gap-1">
          {card.country !== "UN" ? <Flag code={card.country} /> : null}
          {card.site}
        </span>
      </div>
      <MiniAreaChart rx={card.rxSeries} tx={card.txSeries} />
      <div className="flex justify-between mt-2 gap-2">
        <div className="flex items-center gap-1 text-[11px]">
          <ArrowDownIcon className="size-3 text-success" />
          <span className="font-mono font-medium text-success">{fmtRate(card.rxNow)}</span>
        </div>
        <div className="flex items-center gap-1 text-[11px]">
          <ArrowUpIcon className="size-3 text-info" />
          <span className="font-mono font-medium text-info">{fmtRate(card.txNow)}</span>
        </div>
        <div className="flex items-center gap-0.5 text-[10px] text-muted-foreground">
          <GitBranchIcon className="size-3" />{card.sessions}
        </div>
      </div>
    </button>
  )
}

type SessionFilter = {
  kind: "application" | "category" | "service" | "asn" | "country" | "protocol" | "source" | "destination" | "iface" | "client" | "en"
  value: string
  label: string
}

function talkerMatchesFilter(row: FlowTalkerDto, filter: SessionFilter): boolean {
  switch (filter.kind) {
    case "application": return row.application === filter.value
    case "category": return row.category === filter.value
    case "service": return row.service === filter.value
    case "asn": return String(row.dstAsn ?? "") === filter.value
    case "country": return row.dstCountry === filter.value
    case "protocol": return row.protoName === filter.value
    case "source": return row.src === filter.value
    case "destination": return row.dst === filter.value
    case "iface": return row.inIface === filter.value
    case "client": return (row.clientId || "unknown") === filter.value
    case "en": return (row.enId || "") === filter.value
  }
}

function FlowBreakdownGrid({
  rows,
  empty,
  country,
  onPick,
}: {
  rows: FlowBreakdownRow[]
  empty?: string
  country?: boolean
  onPick?: (row: FlowBreakdownRow) => void
}) {
  const columns = useMemo<ColumnDef<FlowBreakdownRow>[]>(
    () => [
      {
        id: "label",
        accessorKey: "label",
        header: () => <span className="text-xs font-medium text-muted-foreground">Имя</span>,
        cell: ({ row }) => (
          <div className="flex min-w-0 flex-col gap-1">
            <span className="flex items-center gap-1.5 text-sm font-medium truncate">
              {country ? <Flag code={row.original.id} /> : null}
              {row.original.label}
            </span>
            <div className="h-1 rounded-full bg-muted overflow-hidden">
              <div
                className="h-full bg-primary"
                style={{ width: `${Math.min(100, row.original.percent)}%` }}
              />
            </div>
          </div>
        ),
        meta: { headerClassName: DATA_GRID_CELL_PAD_FIRST, cellClassName: DATA_GRID_CELL_PAD_FIRST },
      },
      {
        id: "share",
        accessorKey: "percent",
        header: () => <span className="text-xs font-medium text-muted-foreground">Доля</span>,
        cell: ({ row }) => (
          <span className="text-xs tabular-nums">{row.original.percent.toFixed(1)}%</span>
        ),
        meta: { headerClassName: DATA_GRID_CELL_PAD, cellClassName: DATA_GRID_CELL_PAD },
      },
      {
        id: "rate",
        accessorFn: (r) => r.bps,
        header: () => <span className="text-xs font-medium text-muted-foreground">Скорость</span>,
        cell: ({ row }) => (
          <span className="text-xs tabular-nums">{fmtRate(row.original.bps / 1_000_000)}</span>
        ),
        meta: { headerClassName: DATA_GRID_CELL_PAD, cellClassName: DATA_GRID_CELL_PAD },
      },
      {
        id: "bytes",
        accessorKey: "bytes",
        header: () => <span className="text-xs font-medium text-muted-foreground">Байты</span>,
        cell: ({ row }) => (
          <span className="text-xs tabular-nums">{formatBytes(row.original.bytes)}</span>
        ),
        meta: { headerClassName: DATA_GRID_CELL_PAD_LAST, cellClassName: DATA_GRID_CELL_PAD_LAST },
      },
    ],
    [country],
  )

  const table = useReactTable({
    data: rows,
    columns,
    getCoreRowModel: getCoreRowModel(),
    getRowId: (row) => row.id,
  })

  return (
    <DataGridShell
      table={table}
      recordCount={rows.length}
      emptyMessage={empty ?? "Нет данных за период"}
      onRowClick={onPick}
    />
  )
}

function FlowPathsGrid({
  rows,
  empty,
  onPick,
}: {
  rows: FlowPathRow[]
  empty?: string
  onPick?: (row: FlowPathRow) => void
}) {
  const columns = useMemo<ColumnDef<FlowPathRow>[]>(
    () => [
      {
        id: "client",
        accessorKey: "clientName",
        header: () => <span className="text-xs font-medium text-muted-foreground">Клиент</span>,
        cell: ({ row }) => <span className="text-sm font-medium">{row.original.clientName}</span>,
        meta: { headerClassName: DATA_GRID_CELL_PAD_FIRST, cellClassName: DATA_GRID_CELL_PAD_FIRST },
      },
      {
        id: "ifaces",
        accessorKey: "ifaces",
        header: () => <span className="text-xs font-medium text-muted-foreground">Ifaces</span>,
        cell: ({ row }) => <span className="font-mono text-xs text-muted-foreground">{row.original.ifaces}</span>,
        meta: { headerClassName: DATA_GRID_CELL_PAD, cellClassName: DATA_GRID_CELL_PAD },
      },
      {
        id: "jh",
        accessorKey: "serverName",
        header: () => <span className="text-xs font-medium text-muted-foreground">JH</span>,
        cell: ({ row }) => <span className="text-xs">{row.original.serverName}</span>,
        meta: { headerClassName: DATA_GRID_CELL_PAD, cellClassName: DATA_GRID_CELL_PAD },
      },
      {
        id: "in",
        accessorKey: "inIface",
        header: () => <span className="text-xs font-medium text-muted-foreground">In</span>,
        cell: ({ row }) => <span className="font-mono text-xs">{row.original.inIface}</span>,
        meta: { headerClassName: DATA_GRID_CELL_PAD, cellClassName: DATA_GRID_CELL_PAD },
      },
      {
        id: "en",
        accessorKey: "enName",
        header: () => <span className="text-xs font-medium text-muted-foreground">EN</span>,
        cell: ({ row }) => <span className="text-xs">{row.original.enName || "—"}</span>,
        meta: { headerClassName: DATA_GRID_CELL_PAD, cellClassName: DATA_GRID_CELL_PAD },
      },
      {
        id: "dst",
        accessorKey: "dst",
        header: () => <span className="text-xs font-medium text-muted-foreground">Dest</span>,
        cell: ({ row }) => (
          <span className="flex min-w-0 flex-col gap-0.5 text-xs">
            <span className="font-mono">{row.original.dst}</span>
            <span className="text-[10px] text-muted-foreground truncate">
              {[row.original.category, row.original.service].filter(Boolean).join(" · ")}
            </span>
          </span>
        ),
        meta: { headerClassName: DATA_GRID_CELL_PAD, cellClassName: DATA_GRID_CELL_PAD },
      },
      {
        id: "rate",
        accessorFn: (r) => r.bps,
        header: () => <span className="text-xs font-medium text-muted-foreground">Скорость</span>,
        cell: ({ row }) => <span className="text-xs tabular-nums">{fmtRate(row.original.bps / 1_000_000)}</span>,
        meta: { headerClassName: DATA_GRID_CELL_PAD, cellClassName: DATA_GRID_CELL_PAD },
      },
      {
        id: "bytes",
        accessorKey: "bytes",
        header: () => <span className="text-xs font-medium text-muted-foreground">Байты</span>,
        cell: ({ row }) => <span className="text-xs tabular-nums">{formatBytes(row.original.bytes)}</span>,
        meta: { headerClassName: DATA_GRID_CELL_PAD_LAST, cellClassName: DATA_GRID_CELL_PAD_LAST },
      },
    ],
    [],
  )

  const table = useReactTable({
    data: rows,
    columns,
    getCoreRowModel: getCoreRowModel(),
    getRowId: (row) => row.id,
  })

  return (
    <DataGridShell
      table={table}
      recordCount={rows.length}
      emptyMessage={empty ?? "Нет путей"}
      onRowClick={onPick}
    />
  )
}

export function FlowAnalyticsDetail({
  card,
  analytics,
  range,
  onRange,
  selectedIface,
  onIface,
  dedup,
  onDedup,
  excludeMesh,
  onExcludeMesh,
  excludeOverlay,
  onExcludeOverlay,
  liveHint,
  emptyHint,
}: {
  card: FlowEntityCard | null
  analytics: FlowAnalyticsDto | null
  range: string
  onRange: (r: string) => void
  selectedIface: string
  onIface: (name: string) => void
  dedup: boolean
  onDedup: (value: boolean) => void
  excludeMesh: boolean
  onExcludeMesh: (value: boolean) => void
  excludeOverlay: boolean
  onExcludeOverlay: (value: boolean) => void
  liveHint?: string
  emptyHint?: string
}) {
  const [slice, setSlice] = useState("applications")
  const [sessionFilter, setSessionFilter] = useState<SessionFilter | null>(null)
  const rxNow = analytics ? analytics.bpsNow / 1_000_000 : (card?.rxNow ?? 0)
  const bytes = analytics?.bytes ?? card?.bytes ?? 0
  const sessionRows = (analytics?.conversationsList ?? []).filter((row) =>
    sessionFilter ? talkerMatchesFilter(row, sessionFilter) : true,
  )

  function pickBreakdown(kind: SessionFilter["kind"], row: FlowBreakdownRow) {
    setSessionFilter({ kind, value: row.id, label: row.label })
    setSlice("sessions")
  }

  if (!card) {
    return (
      <p className="text-sm text-muted-foreground py-8 text-center">
        Выберите сервер или клиента слева
      </p>
    )
  }

  return (
    <>
      <div className="flex items-start justify-between mb-3 gap-3">
        <div className="flex items-center gap-2 flex-wrap min-w-0">
          <StatusDot status={card.status} />
          <h2 className="text-base font-semibold truncate">{card.name}</h2>
          <span className="text-xs font-mono bg-muted px-1.5 py-0.5 rounded flex items-center gap-1">
            {card.country !== "UN" ? <Flag code={card.country} /> : null}
            {card.site}
          </span>
        </div>
        <div className="flex items-center gap-3 shrink-0">
          <div className="flex items-center gap-2">
            <Switch
              id="flow-dedup"
              checked={dedup}
              onCheckedChange={onDedup}
            />
            <Label htmlFor="flow-dedup" className="text-xs text-muted-foreground whitespace-nowrap">
              Без дублей
            </Label>
          </div>
          <div className="flex items-center gap-2">
            <Switch
              id="flow-exclude-overlay"
              checked={excludeOverlay}
              onCheckedChange={onExcludeOverlay}
            />
            <Label htmlFor="flow-exclude-overlay" className="text-xs text-muted-foreground whitespace-nowrap">
              Без overlay
            </Label>
          </div>
          <div className="flex items-center gap-2">
            <Switch
              id="flow-exclude-mesh"
              checked={excludeMesh}
              onCheckedChange={onExcludeMesh}
            />
            <Label htmlFor="flow-exclude-mesh" className="text-xs text-muted-foreground whitespace-nowrap">
              Без mesh
            </Label>
          </div>
          <div className="flex gap-1">
            {RANGE_KEYS.map((r) => (
              <button
                key={r}
                type="button"
                onClick={() => onRange(r)}
                className={cn(
                  "h-7 px-2 text-xs rounded border transition-colors",
                  range === r
                    ? "border-primary bg-primary/10 text-primary font-medium"
                    : "border-border text-muted-foreground hover:text-foreground",
                )}
              >
                {RANGE_LABELS[r]}
              </button>
            ))}
          </div>
        </div>
      </div>

      {analytics?.ifaces && analytics.ifaces.length > 0 ? (
        <div className="mb-3 pb-3 border-b">
          <div className="flex items-center gap-2 flex-wrap">
            <span className="text-[11px] text-muted-foreground mr-1">Интерфейс:</span>
            <button
              type="button"
              onClick={() => onIface("__all__")}
              className={cn(
                "inline-flex items-center gap-1 rounded-full border px-2.5 py-0.5 text-[10px] font-medium transition-all",
                selectedIface === "__all__"
                  ? "bg-foreground text-background border-foreground"
                  : "border-border text-muted-foreground hover:text-foreground hover:border-foreground/40",
              )}
            >
              Все
            </button>
            {analytics.ifaces.map((iface) => {
              const active = selectedIface === iface.name
              return (
                <button
                  key={`${iface.name}:${iface.index}`}
                  type="button"
                  onClick={() => onIface(iface.name)}
                  className={cn(
                    "inline-flex items-center gap-1.5 rounded-full border px-2.5 py-0.5 text-[10px] font-medium transition-all",
                    active
                      ? "bg-foreground text-background border-foreground"
                      : "border-border text-muted-foreground hover:text-foreground hover:border-foreground/40",
                  )}
                >
                  {iface.name}
                </button>
              )
            })}
          </div>
          <p className="text-[10px] text-muted-foreground mt-1.5">по iface, без дедупа</p>
        </div>
      ) : null}

      <TrafficRxTxChart
        rx={analytics?.rxSeries ?? card.rxSeries}
        tx={analytics?.txSeries ?? card.txSeries}
        range={range}
      />

      <div className="mt-4 pt-4 border-t">
        <KpiStatGrid
          aria-label="Скорость потоков"
          items={([
            {
              id: "bps-now",
              label: "Скорость сейчас",
              value: fmtRate(rxNow),
              hint: liveHint,
              icon: <ArrowDownIcon className="size-4" />,
              iconClassName: "text-success",
            },
            {
              id: "bytes",
              label: "Payload",
              value: formatBytes(bytes),
              hint: "inner IPFIX",
              icon: <ArrowUpIcon className="size-4" />,
              iconClassName: "text-info",
            },
            {
              id: "overlay",
              label: "JH↔EN overlay",
              value: fmtRate((analytics?.bpsOverlay ?? 0) / 1_000_000),
              hint: analytics?.bytesOverlay ? formatBytes(analytics.bytesOverlay) : undefined,
              icon: <ShieldIcon className="size-4" />,
              iconClassName: "text-warning",
            },
            {
              id: "wire",
              label: "Wire GRE",
              value: fmtRate((analytics?.bpsWire ?? 0) / 1_000_000),
              hint: "счётчик iface",
              icon: <RouteIcon className="size-4" />,
              iconClassName: "text-primary",
            },
            ...(!excludeMesh
              ? [{
                  id: "mesh",
                  label: "Mesh",
                  value: formatBytes(analytics?.bytesMesh ?? 0),
                  hint: "клиент↔клиент",
                  icon: <NetworkIcon className="size-4" />,
                  iconClassName: "text-muted-foreground",
                }]
              : []),
            {
              id: "flows",
              label: "Сессии",
              value: String(analytics?.conversations ?? card.sessions),
              hint: analytics?.conversationsRaw != null && analytics.conversationsRaw !== analytics.conversations
                ? `до дедупа ${analytics.conversationsRaw}`
                : undefined,
              icon: <GitBranchIcon className="size-4" />,
              iconClassName: "text-warning",
            },
            {
              id: "uniq",
              label: "Уник. src / dst",
              value: `${analytics?.uniqueSrc ?? 0} / ${analytics?.uniqueDst ?? 0}`,
              icon: <UsersIcon className="size-4" />,
              iconClassName: "text-muted-foreground",
            },
            {
              id: "category",
              label: "Топ категория",
              value: analytics?.topCategory ?? "—",
              icon: <LayersIcon className="size-4" />,
              iconClassName: "text-primary",
            },
          ] satisfies KpiStatItem[])}
        />
      </div>

      <div className="mt-4 pt-4 border-t flex flex-col gap-3">
        <div className="flex items-center justify-between gap-2">
          <p className="text-xs text-muted-foreground">Аналитика потребления</p>
          {analytics?.live ? <Badge variant="success-light" size="sm">live</Badge> : null}
        </div>
        <Tabs value={slice} onValueChange={(v) => setSlice(String(v))} className="gap-3">
          <TabsList variant="line" className="flex flex-wrap h-auto">
            <TabsTrigger value="applications">Приложения</TabsTrigger>
            <TabsTrigger value="categories">Категории</TabsTrigger>
            <TabsTrigger value="services">Сервисы</TabsTrigger>
            <TabsTrigger value="asns">ASN</TabsTrigger>
            <TabsTrigger value="countries">Страны</TabsTrigger>
            <TabsTrigger value="map">Карта</TabsTrigger>
            <TabsTrigger value="protocols">Протоколы</TabsTrigger>
            <TabsTrigger value="sources">Источники</TabsTrigger>
            <TabsTrigger value="destinations">Назначения</TabsTrigger>
            <TabsTrigger value="paths">Пути</TabsTrigger>
            <TabsTrigger value="sessions">Сессии</TabsTrigger>
            <TabsTrigger value="interfaces">Интерфейсы</TabsTrigger>
          </TabsList>
          <TabsContent value="applications">
            <FlowBreakdownGrid rows={analytics?.applications ?? []} onPick={(row) => pickBreakdown("application", row)} />
          </TabsContent>
          <TabsContent value="categories">
            <FlowBreakdownGrid rows={analytics?.categories ?? []} onPick={(row) => pickBreakdown("category", row)} />
          </TabsContent>
          <TabsContent value="services">
            <FlowBreakdownGrid rows={analytics?.services ?? []} onPick={(row) => pickBreakdown("service", row)} />
          </TabsContent>
          <TabsContent value="asns">
            <FlowBreakdownGrid rows={analytics?.asns ?? []} onPick={(row) => pickBreakdown("asn", row)} />
          </TabsContent>
          <TabsContent value="countries">
            <FlowBreakdownGrid rows={analytics?.countries ?? []} country onPick={(row) => pickBreakdown("country", row)} />
          </TabsContent>
          <TabsContent value="map">
            <FlowTrafficMap
              edges={analytics?.mapEdges ?? []}
              onSelectCountry={(iso) => {
                setSessionFilter({ kind: "country", value: iso, label: iso })
                setSlice("sessions")
              }}
            />
          </TabsContent>
          <TabsContent value="protocols">
            <FlowBreakdownGrid rows={analytics?.protocols ?? []} onPick={(row) => pickBreakdown("protocol", row)} />
          </TabsContent>
          <TabsContent value="sources">
            <FlowBreakdownGrid rows={analytics?.sources ?? []} onPick={(row) => pickBreakdown("source", row)} />
          </TabsContent>
          <TabsContent value="destinations">
            <FlowBreakdownGrid rows={analytics?.destinations ?? []} onPick={(row) => pickBreakdown("destination", row)} />
          </TabsContent>
          <TabsContent value="paths">
            <FlowPathsGrid
              rows={analytics?.paths ?? []}
              empty="Нет путей за период"
              onPick={(row) => {
                setSessionFilter({
                  kind: "client",
                  value: row.clientId,
                  label: `${row.clientName} → ${row.enName || row.dst}`,
                })
                setSlice("sessions")
              }}
            />
          </TabsContent>
          <TabsContent value="sessions">
            {sessionFilter ? (
              <div className="flex items-center gap-2 mb-2">
                <GlobeIcon className="size-3.5 text-muted-foreground" />
                <Badge variant="secondary" size="sm">Фильтр: {sessionFilter.label}</Badge>
                <button
                  type="button"
                  className="text-xs text-primary"
                  onClick={() => setSessionFilter(null)}
                >
                  сбросить
                </button>
              </div>
            ) : null}
            <TrafficFlowsDataGrid
              rows={sessionRows}
              emptyHint={emptyHint ?? "Нет сессий по выбранному фильтру"}
            />
          </TabsContent>
          <TabsContent value="interfaces">
            <FlowBreakdownGrid
              rows={analytics?.interfaces ?? []}
              empty="Нет данных по интерфейсам"
              onPick={(row) => pickBreakdown("iface", row)}
            />
          </TabsContent>
        </Tabs>
      </div>
    </>
  )
}
