"use client";

import { useQuery } from "@tanstack/react-query";
import { useMemo, useState } from "react";
import { Skeleton } from "@/components/ui/skeleton";
import { Badge } from "@/components/ui/badge";
import { PlayerAvatar } from "@/components/PlayerAvatar";
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "@/components/ui/card";

type MetricEntry = {
  ts: string;
  tps: number;
  ramUsedMB: number;
  ramTotalMB: number;
  cpuPercent: number;
  playersOnline: number;
  players?: string[];
};

function UptimeRing({ percent, size = 64 }: { percent: number; size?: number }) {
  const r = size / 2 - 5;
  const c = 2 * Math.PI * r;
  const off = c * (1 - percent / 100);
  const color =
    percent >= 95 ? "#4ade80" : percent >= 80 ? "#facc15" : "#f87171";
  return (
    <svg width={size} height={size} viewBox={`0 0 ${size} ${size}`} aria-label={`Uptime ${percent.toFixed(0)}%`}>
      <circle
        cx={size / 2}
        cy={size / 2}
        r={r}
        stroke="currentColor"
        strokeOpacity="0.15"
        strokeWidth="5"
        fill="none"
      />
      <circle
        cx={size / 2}
        cy={size / 2}
        r={r}
        stroke={color}
        strokeWidth="5"
        strokeLinecap="round"
        strokeDasharray={c}
        strokeDashoffset={off}
        fill="none"
        transform={`rotate(-90 ${size / 2} ${size / 2})`}
      />
      <text
        x="50%"
        y="50%"
        textAnchor="middle"
        dominantBaseline="middle"
        className="fill-foreground"
        fontSize={size * 0.28}
        fontWeight="700"
      >
        {Math.round(percent)}%
      </text>
    </svg>
  );
}

function Sparkline({
  data,
  color,
  max,
  height = 80,
  label,
  unit,
  currentValue,
  peakIndex,
  peakLabel,
}: {
  data: number[];
  color: string;
  max?: number;
  height?: number;
  label: string;
  unit: string;
  currentValue: string;
  peakIndex?: number;
  peakLabel?: string;
}) {
  if (data.length < 2) {
    return (
      <div className="rounded-lg bg-muted p-4">
        <div className="flex items-baseline justify-between mb-2">
          <div>
            <p className="text-xs text-muted-foreground">{label}</p>
            <p className="text-lg font-bold">
              {currentValue}
              <span className="text-xs text-muted-foreground ml-1">{unit}</span>
            </p>
          </div>
        </div>
        <Skeleton className="w-full" style={{ height }} />
        <p className="text-xs text-muted-foreground mt-2">Collecting data...</p>
      </div>
    );
  }

  const { pathD, areaD, w, peakXY } = useMemo(() => {
    const dataMax = max || Math.max(...data, 1);
    const width = 300;
    const coords = data.map((v, i) => {
      const x = (i / (data.length - 1)) * width;
      const y = height - (v / dataMax) * (height - 10) - 5;
      return { x, y };
    });
    const pts = coords.map((c) => `${c.x},${c.y}`);
    const p = `M${pts.join(" L")}`;
    const peak =
      typeof peakIndex === "number" && peakIndex >= 0 && peakIndex < coords.length
        ? coords[peakIndex]
        : null;
    return {
      pathD: p,
      areaD: `${p} L${width},${height} L0,${height} Z`,
      w: width,
      peakXY: peak,
    };
  }, [data, max, height, peakIndex]);

  return (
    <div className="rounded-lg bg-muted p-4">
      <div className="flex items-baseline justify-between mb-2">
        <div>
          <p className="text-xs text-muted-foreground">{label}</p>
          <p className="text-lg font-bold">
            {currentValue}
            <span className="text-xs text-muted-foreground ml-1">{unit}</span>
          </p>
        </div>
      </div>
      <svg viewBox={`0 0 ${w} ${height}`} className="w-full" preserveAspectRatio="none">
        <defs>
          <linearGradient id={`grad-${label}`} x1="0" y1="0" x2="0" y2="1">
            <stop offset="0%" stopColor={color} stopOpacity="0.3" />
            <stop offset="100%" stopColor={color} stopOpacity="0" />
          </linearGradient>
        </defs>
        <path d={areaD} fill={`url(#grad-${label})`} />
        <path d={pathD} fill="none" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
        {peakXY && (
          <>
            <circle cx={peakXY.x} cy={peakXY.y} r={3.5} fill={color} />
            <circle cx={peakXY.x} cy={peakXY.y} r={6} fill={color} fillOpacity="0.25" />
          </>
        )}
      </svg>
      {peakLabel && (
        <p className="text-[10px] text-muted-foreground mt-1 tabular-nums">
          peak {peakLabel}
        </p>
      )}
    </div>
  );
}

export function Analytics() {
  const [hours, setHours] = useState(6);

  const { data: metrics = [] } = useQuery<MetricEntry[]>({
    queryKey: ["analytics", hours],
    queryFn: () =>
      fetch(`/api/analytics?hours=${hours}`).then((r) => r.json()),
    refetchInterval: 60_000,
    staleTime: 30_000,
  });

  const latest = metrics.length > 0 ? metrics[metrics.length - 1] : null;

  const { uptimePct, peakPlayers, peakIndex, onlineNow } = useMemo(() => {
    if (metrics.length === 0) {
      return { uptimePct: 0, peakPlayers: 0, peakIndex: -1, onlineNow: [] as string[] };
    }
    const alive = metrics.filter((m) => m.tps > 0 || m.playersOnline > 0).length;
    const pct = (alive / metrics.length) * 100;
    let peak = -Infinity;
    let idx = -1;
    metrics.forEach((m, i) => {
      if (m.playersOnline > peak) {
        peak = m.playersOnline;
        idx = i;
      }
    });
    const online =
      (latest?.players?.filter((p): p is string => typeof p === "string" && p.length > 0)) || [];
    return { uptimePct: pct, peakPlayers: peak, peakIndex: idx, onlineNow: online };
  }, [metrics, latest]);

  const ranges = [
    { label: "1h", value: 1 },
    { label: "6h", value: 6 },
    { label: "24h", value: 24 },
  ];

  return (
    <Card>
      <CardHeader>
        <div className="flex flex-col sm:flex-row sm:items-center justify-between gap-2">
          <div>
            <CardTitle>Server Analytics</CardTitle>
            <CardDescription>
              {metrics.length} data points
            </CardDescription>
          </div>
          <div className="flex gap-1 bg-muted p-1 rounded-lg w-fit shrink-0">
            {ranges.map((r) => (
              <button
                key={r.value}
                onClick={() => setHours(r.value)}
                className={`px-3 py-1 rounded-md text-xs font-medium transition ${
                  hours === r.value
                    ? "bg-background text-foreground shadow-sm"
                    : "text-muted-foreground hover:text-foreground"
                }`}
              >
                {r.label}
              </button>
            ))}
          </div>
        </div>
      </CardHeader>
      <CardContent className="space-y-4">
        {metrics.length > 0 && (
          <div className="flex items-center gap-4 flex-wrap rounded-lg bg-muted p-3">
            <div className="flex items-center gap-3">
              <UptimeRing percent={uptimePct} />
              <div>
                <p className="text-xs text-muted-foreground">Uptime</p>
                <p className="text-sm font-semibold">
                  {uptimePct.toFixed(1)}%{" "}
                  <span className="text-xs text-muted-foreground">
                    over last {hours}h
                  </span>
                </p>
              </div>
            </div>
            <div className="h-10 w-px bg-border hidden sm:block" />
            <div>
              <p className="text-xs text-muted-foreground">Peak players</p>
              <p className="text-sm font-semibold tabular-nums">
                {peakPlayers >= 0 ? peakPlayers : 0}
              </p>
            </div>
            <div className="h-10 w-px bg-border hidden sm:block" />
            <div className="flex-1 min-w-0">
              <p className="text-xs text-muted-foreground mb-1">
                Online now ({onlineNow.length})
              </p>
              {onlineNow.length === 0 ? (
                <p className="text-sm text-muted-foreground">—</p>
              ) : (
                <div className="flex flex-wrap gap-1.5">
                  {onlineNow.slice(0, 8).map((name) => (
                    <Badge
                      key={name}
                      variant="secondary"
                      className="gap-1.5 text-xs px-1.5 py-0.5 font-normal"
                    >
                      <PlayerAvatar name={name} size={14} />
                      {name}
                    </Badge>
                  ))}
                  {onlineNow.length > 8 && (
                    <Badge variant="secondary" className="text-xs px-1.5 py-0.5">
                      +{onlineNow.length - 8}
                    </Badge>
                  )}
                </div>
              )}
            </div>
          </div>
        )}
        <div className="grid grid-cols-1 md:grid-cols-2 gap-3">
          <Sparkline
            data={metrics.map((m) => m.tps)}
            color="#4ade80"
            max={22}
            label="TPS"
            unit=""
            currentValue={latest ? latest.tps.toFixed(1) : "-"}
          />
          <Sparkline
            data={metrics.map((m) => m.ramUsedMB)}
            color="#60a5fa"
            label="RAM"
            unit="MB"
            currentValue={
              latest ? `${(latest.ramUsedMB / 1024).toFixed(1)} GB` : "-"
            }
          />
          <Sparkline
            data={metrics.map((m) => m.cpuPercent)}
            color="#f59e0b"
            max={100}
            label="CPU"
            unit="%"
            currentValue={latest ? latest.cpuPercent.toFixed(0) : "-"}
          />
          <Sparkline
            data={metrics.map((m) => m.playersOnline)}
            color="#a78bfa"
            label="Players"
            unit=""
            currentValue={latest ? latest.playersOnline.toString() : "0"}
            peakIndex={peakPlayers > 0 ? peakIndex : undefined}
            peakLabel={peakPlayers > 0 ? peakPlayers.toString() : undefined}
          />
        </div>
      </CardContent>
    </Card>
  );
}
