"use client"

import { useMemo, useState } from "react"
import { type ColumnDef, getCoreRowModel, useReactTable } from "@tanstack/react-table"
import type { FlowMapEdge } from "@mmapp/contracts/traffic-flow"
import { Frame, FramePanel } from "@/components/reui/frame"
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 { Flag } from "@/components/flag"
import { fmtRate } from "@/lib/fmt-rate"

const W = 640
const H = 280
const STROKES = [
  "var(--chart-1)",
  "var(--chart-2)",
  "var(--chart-3)",
  "var(--color-success)",
  "var(--chart-5)",
]

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} Б`
}

function FlowTrafficMap({
  edges,
  onSelectCountry,
}: {
  edges: FlowMapEdge[]
  onSelectCountry?: (country: string) => void
}) {
  const [hover, setHover] = useState<string | null>(null)

  const layout = useMemo(() => {
    const sources = [...new Map(edges.map((e) => [e.fromId, e])).values()]
    const dests = [...new Map(edges.map((e) => [e.toCountry, e])).values()]
    const srcY = (i: number) => sources.length <= 1 ? H / 2 : 36 + (i * (H - 72)) / Math.max(1, sources.length - 1)
    const dstY = (i: number) => dests.length <= 1 ? H / 2 : 36 + (i * (H - 72)) / Math.max(1, dests.length - 1)
    const srcPos = new Map(sources.map((s, i) => [s.fromId, { x: 88, y: srcY(i), label: s.fromLabel, country: s.fromCountry }]))
    const dstPos = new Map(dests.map((d, i) => [d.toCountry, { x: 552, y: dstY(i), country: d.toCountry }]))
    const maxBytes = Math.max(...edges.map((e) => e.bytes), 1)
    return { srcPos, dstPos, maxBytes }
  }, [edges])

  const columns = useMemo<ColumnDef<FlowMapEdge>[]>(
    () => [
      {
        id: "from",
        accessorKey: "fromLabel",
        header: () => <span className="text-xs font-medium text-muted-foreground">Источник</span>,
        cell: ({ row }) => (
          <span className="flex items-center gap-1.5 text-sm">
            {row.original.fromCountry && row.original.fromCountry !== "UN"
              ? <Flag code={row.original.fromCountry} />
              : null}
            {row.original.fromLabel}
          </span>
        ),
        meta: { headerClassName: DATA_GRID_CELL_PAD_FIRST, cellClassName: DATA_GRID_CELL_PAD_FIRST },
      },
      {
        id: "to",
        accessorKey: "toCountry",
        header: () => <span className="text-xs font-medium text-muted-foreground">Назначение</span>,
        cell: ({ row }) => (
          <span className="flex items-center gap-1.5 text-sm">
            {/^[a-z]{2}$/i.test(row.original.toCountry)
              ? <Flag code={row.original.toCountry} />
              : null}
            {row.original.toCountry}
            {row.original.toAsn ? <span className="font-mono text-[10px] text-muted-foreground">AS{row.original.toAsn}</span> : null}
          </span>
        ),
        meta: { headerClassName: DATA_GRID_CELL_PAD, cellClassName: DATA_GRID_CELL_PAD },
      },
      {
        id: "cat",
        accessorKey: "category",
        header: () => <span className="text-xs font-medium text-muted-foreground">Категория</span>,
        cell: ({ row }) => <span className="text-xs">{row.original.category}</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: edges,
    columns,
    getCoreRowModel: getCoreRowModel(),
    getRowId: (row, i) => `${row.fromId}-${row.toCountry}-${i}`,
  })

  if (!edges.length) {
    return (
      <p className="text-sm text-muted-foreground py-8 text-center">
        Страны подтянутся из кэша RIPEstat
      </p>
    )
  }

  return (
    <div className="flex flex-col gap-3">
      <Frame>
        <FramePanel className="p-3">
          <svg viewBox={`0 0 ${W} ${H}`} className="w-full h-[220px]" role="img" aria-label="Карта потоков откуда куда">
            {edges.map((e, i) => {
              const from = layout.srcPos.get(e.fromId)
              const to = layout.dstPos.get(e.toCountry)
              if (!from || !to) return null
              const id = `${e.fromId}-${e.toCountry}`
              const midX = (from.x + to.x) / 2
              const d = `M ${from.x} ${from.y} C ${midX} ${from.y}, ${midX} ${to.y}, ${to.x} ${to.y}`
              const sw = 1.25 + 7 * (e.bytes / layout.maxBytes)
              const active = hover === id
              return (
                <path
                  key={id}
                  d={d}
                  fill="none"
                  stroke={STROKES[i % STROKES.length]}
                  strokeWidth={active ? sw + 1.5 : sw}
                  strokeOpacity={active ? 1 : 0.72}
                  className="cursor-pointer"
                  onMouseEnter={() => setHover(id)}
                  onMouseLeave={() => setHover(null)}
                  onClick={() => onSelectCountry?.(e.toCountry)}
                >
                  <title>
                    {`${e.fromLabel} → ${e.toCountry} · ${e.category} · ${formatBytes(e.bytes)}`}
                  </title>
                </path>
              )
            })}
            {[...layout.srcPos.values()].map((n) => (
              <g key={`s-${n.label}`}>
                <circle cx={n.x} cy={n.y} r="7" className="fill-primary" />
                <text x={n.x - 14} y={n.y + 4} textAnchor="end" className="fill-foreground text-[11px]">
                  {n.label}
                </text>
              </g>
            ))}
            {[...layout.dstPos.values()].map((n) => (
              <g key={`d-${n.country}`}>
                <circle cx={n.x} cy={n.y} r="7" className="fill-chart-2" />
                <text x={n.x + 14} y={n.y + 4} className="fill-foreground text-[11px]">
                  {n.country}
                </text>
              </g>
            ))}
          </svg>
          {hover ? (
            <p className="text-[11px] text-muted-foreground mt-1">
              Нажмите дугу, чтобы отфильтровать сессии по стране назначения
            </p>
          ) : null}
        </FramePanel>
      </Frame>
      <DataGridShell
        table={table}
        recordCount={edges.length}
        emptyMessage="Нет рёбер с известной страной"
        onRowClick={(row) => onSelectCountry?.(row.toCountry)}
      />
    </div>
  )
}

export { FlowTrafficMap }
