import { useEffect, useRef, useSyncExternalStore } from "react"
import { useSystemStatus, useTokenStats } from "@/lib/queries"

export type SysSample = { t: number; cpu: number; ram: number; gpu: number | null; disk: number | null }
export type RateSample = { t: number; prompt: number; completion: number }

const MAX_POINTS = 40   // bei 3s-Poll ~2 Min Live-Verlauf

// Modul-globaler Verlauf: überlebt Mount/Unmount (Tab-Wechsel) → Graphen starten nie leer.
let sysHist: SysSample[] = []
let tokHist: RateSample[] = []
const listeners = new Set<() => void>()
const emit = () => listeners.forEach((l) => l())

function subscribe(l: () => void) {
  listeners.add(l)
  return () => { listeners.delete(l) }
}

export function pushSys(s: SysSample) { sysHist = [...sysHist, s].slice(-MAX_POINTS); emit() }
export function pushTok(s: RateSample) { tokHist = [...tokHist, s].slice(-MAX_POINTS); emit() }

export const useSysHistory = () => useSyncExternalStore(subscribe, () => sysHist)
export const useTokHistory = () => useSyncExternalStore(subscribe, () => tokHist)

/** Immer-laufender Sammler (in App eingehängt, also stets gemountet): füttert den
 * Store bei jedem Poll — unabhängig davon, welcher Tab gerade sichtbar ist. */
export function useMetricsFeeder() {
  const { data: sys, dataUpdatedAt: sysAt } = useSystemStatus()
  const { data: ts, dataUpdatedAt: tsAt } = useTokenStats()
  const prevTok = useRef<{ p: number; c: number; t: number } | null>(null)

  useEffect(() => {
    if (!sys) return
    pushSys({
      t: Date.now(),
      cpu: sys.cpu?.percent ?? 0,
      ram: sys.ram?.percent ?? 0,
      gpu: sys.gpu?.busy_percent ?? null,
      disk: sys.disk?.percent ?? null,
    })
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [sysAt])

  useEffect(() => {
    if (!ts) return
    const now = Date.now()
    const p = ts.prompt_tokens, c = ts.completion_tokens
    if (prevTok.current) {
      const dt = Math.max((now - prevTok.current.t) / 1000, 0.001)
      pushTok({
        t: now,
        prompt: Math.max(0, (p - prevTok.current.p) / dt),
        completion: Math.max(0, (c - prevTok.current.c) / dt),
      })
    }
    prevTok.current = { p, c, t: now }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [tsAt])
}
