"use client"

import { useEffect, useMemo, useState, type ReactNode } from "react"
import { Activity, Filter, HeartPulse, Server } from "lucide-react"

import { Badge } from "@/components/reui/badge"
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"
import { cn } from "@/lib/utils"
import { useDataSource } from "@/lib/data-source"
import { filters, pingProbes, servers } from "@/lib/data"
import type { SidebarCountsDto } from "@/lib/sidebar-badges"
import { resolveApiUrl, requestJson } from "@/shared/api/http-client"

type MonitorMetric = {
  id: string
  label: string
  value: string
  unit: string
  percent: number
  icon: ReactNode
  tone: "success" | "warning" | "destructive" | "info"
  alert: boolean
}

type HealthDto = {
  status?: string
}

function toneColor(tone: MonitorMetric["tone"]) {
  switch (tone) {
    case "success":
      return "var(--color-success)"
    case "warning":
      return "var(--color-warning)"
    case "destructive":
      return "var(--color-destructive)"
    default:
      return "var(--color-info)"
  }
}

function MetricBar({ percent, color }: { percent: number; color: string }) {
  return (
    <div className="bg-muted h-1 w-full overflow-hidden rounded-full">
      <div
        className="h-full rounded-full"
        style={{
          width: `${Math.min(100, Math.max(0, percent))}%`,
          backgroundColor: color,
        }}
      />
    </div>
  )
}

function MetricCell({ metric }: { metric: MonitorMetric }) {
  const color = toneColor(metric.tone)
  return (
    <div className="flex flex-col gap-2 p-3">
      <div className="flex items-center justify-between gap-1">
        <div className="flex min-w-0 items-center gap-1.5">
          <div
            className="flex size-5 shrink-0 items-center justify-center rounded-md"
            style={{ backgroundColor: `${color}18`, color }}
          >
            {metric.icon}
          </div>
          <span className="text-muted-foreground truncate text-[11px]">{metric.label}</span>
        </div>
        <span className="shrink-0 text-xs font-semibold tabular-nums" style={{ color }}>
          {metric.value}
          <span className="text-muted-foreground ml-0.5 text-[10px] font-normal">{metric.unit}</span>
        </span>
      </div>
      <MetricBar percent={metric.percent} color={color} />
    </div>
  )
}

/** Live system monitor popover — app-shell-7. @see https://reui.io/preview/base/app-shell-7 */
export function SystemMonitorPopover() {
  const { mode, backendUrl, prefsHydrated } = useDataSource()
  const [healthOk, setHealthOk] = useState<boolean | null>(null)
  const [counts, setCounts] = useState<SidebarCountsDto | null>(null)

  useEffect(() => {
    if (!prefsHydrated) return
    if (mode !== "live") {
      setHealthOk(true)
      setCounts({
        servers: servers.length,
        filterRules: filters.length,
        uptimeProbes: pingProbes.length,
        uptimeSpeedProbes: 0,
        monitoringItems: pingProbes.length,
        recursiveRoutes: 0,
      })
      return
    }

    let cancelled = false
    const load = async () => {
      try {
        const [hRes, counts] = await Promise.all([
          fetch(resolveApiUrl(backendUrl, "/health"), { signal: AbortSignal.timeout(3000) }),
          requestJson<SidebarCountsDto>(backendUrl, "/api/sidebar-counts"),
        ])
        if (cancelled) return
        if (hRes.ok) {
          const json = (await hRes.json()) as HealthDto
          setHealthOk(json.status === "ok")
        } else {
          setHealthOk(false)
        }
        setCounts(counts)
      } catch {
        if (!cancelled) {
          setHealthOk(false)
          setCounts(null)
        }
      }
    }
    void load()
    const id = window.setInterval(load, 30_000)
    return () => {
      cancelled = true
      window.clearInterval(id)
    }
  }, [mode, backendUrl, prefsHydrated])

  const serversCount = counts?.servers ?? 0
  const filtersCount = counts?.filterRules ?? 0
  const monitoringCount = counts?.monitoringItems ?? 0
  const apiOk = healthOk === true

  const metrics = useMemo<MonitorMetric[]>(
    () => [
      {
        id: "api",
        label: "API",
        value: healthOk == null ? "…" : apiOk ? "OK" : "—",
        unit: "",
        percent: apiOk ? 100 : 20,
        icon: <Activity className="size-3" aria-hidden />,
        tone: apiOk ? "success" : "destructive",
        alert: healthOk === false,
      },
      {
        id: "servers",
        label: "Серверы",
        value: String(serversCount),
        unit: "шт.",
        percent: Math.min(100, Math.max(12, serversCount * 8)),
        icon: <Server className="size-3" aria-hidden />,
        tone: serversCount > 0 ? "success" : "warning",
        alert: false,
      },
      {
        id: "filters",
        label: "Фильтры",
        value: String(filtersCount),
        unit: "шт.",
        percent: Math.min(100, Math.max(12, filtersCount * 5)),
        icon: <Filter className="size-3" aria-hidden />,
        tone: "info",
        alert: false,
      },
      {
        id: "uptime",
        label: "Мониторинг",
        value: String(monitoringCount),
        unit: "шт.",
        percent: Math.min(100, Math.max(12, monitoringCount * 8)),
        icon: <HeartPulse className="size-3" aria-hidden />,
        tone: monitoringCount > 0 ? "success" : "warning",
        alert: false,
      },
    ],
    [apiOk, filtersCount, healthOk, monitoringCount, serversCount],
  )

  const spiking = metrics.some((m) => m.alert)

  return (
    <Popover>
      <PopoverTrigger
        render={
          <button
            type="button"
            aria-label="Монитор системы"
            className={cn(
              "relative inline-flex h-8 items-center gap-1.5 rounded-md border px-2 transition-colors outline-none",
              "border-border hover:bg-accent focus-visible:ring-2 focus-visible:ring-ring",
            )}
          />
        }
      >
        <span className="relative flex size-3.5 items-center justify-center">
          <Activity
            aria-hidden
            className={cn(
              "size-3.5 transition-colors",
              spiking ? "text-destructive" : "text-muted-foreground",
            )}
          />
          {spiking ? (
            <span className="bg-destructive/25 absolute inset-0 animate-ping rounded-full" aria-hidden />
          ) : null}
        </span>
        <span className="text-foreground hidden text-xs font-medium sm:inline">Система</span>
        <Badge
          variant={spiking ? "destructive-light" : "success-light"}
          size="xs"
          className="h-4 px-1.5 text-[10px]"
        >
          {spiking ? "Внимание" : "Норма"}
        </Badge>
      </PopoverTrigger>

      <PopoverContent align="end" sideOffset={8} className="flex w-80 flex-col gap-0! p-0!">
        <div className="border-border flex items-center justify-between border-b px-3 py-2.5">
          <span className="text-foreground text-xs font-medium">Монитор MikrotikManager</span>
          <span className="text-muted-foreground text-[11px] tabular-nums">
            {new Date().toLocaleTimeString("ru-RU")}
          </span>
        </div>
        <div className="grid grid-cols-2">
          {metrics.map((metric, i) => (
            <div
              key={metric.id}
              className={cn(
                i % 2 === 1 && "border-border border-l",
                i >= 2 && "border-border border-t",
              )}
            >
              <MetricCell metric={metric} />
            </div>
          ))}
        </div>
        <div className="border-border text-muted-foreground border-t px-3 py-2 text-[11px]">
          Источник:{" "}
          <span className="text-foreground font-medium">
            {mode === "live" ? "API" : "мок"}
          </span>
        </div>
      </PopoverContent>
    </Popover>
  )
}
