// Zentrale Daten-Hooks (TanStack Query). Kapseln lib/api.ts und liefern Caching,
// Dedup (gleicher queryKey = eine Anfrage über alle Views), Retry und Polling.
// Mutations invalidieren gezielt die betroffenen Keys, statt manuell neu zu laden.

import { useQuery, useQueryClient, type QueryClient } from "@tanstack/react-query"
import {
  api,
  type AgentStatus,
  type AuftragsbuchResp,
  type ChronikResp,
  type ConnectResp,
  type ConnectHealth,
  type DiscoverResp,
  type DraftsResp,
  type GroupsResp,
  type HermesBrainResp,
  type Health,
  type IdeenLogResp,
  type IdeenResp,
  type Job,
  type Memory,
  type MemoryGraph,
  type ModelsResp,
  type Reminder,
  type RoutingResp,
  type RoutingPolicyMeta,
  type ServicesResp,
  type SystemStatus,
  type TokenStats,
  type UpdatesResp,
  type VoiceTraceResp,
  type WissenResp,
  type ZeitmaschineResp,
} from "./api"

// Zentrale Query-Keys (eine Quelle der Wahrheit für invalidate).
export const qk = {
  health: ["health"] as const,
  systemStatus: ["system-status"] as const,
  services: ["services"] as const,
  models: ["models"] as const,
  groups: ["groups"] as const,
  routing: ["routing"] as const,
  routingPolicy: ["routing-policy"] as const,
  jobs: ["jobs"] as const,
  tokenStats: ["token-stats"] as const,
  agentStatus: ["agent-status"] as const,
  hermesBrain: ["hermes-brain"] as const,
  updates: ["updates"] as const,
  discover: ["discover"] as const,
  drafts: (target?: string) => ["drafts", target ?? ""] as const,
  connect: (params?: string) => ["connect", params ?? ""] as const,
  connectHealth: ["connect-health"] as const,
  memory: (q?: string, category?: string) => ["memory", q ?? "", category ?? ""] as const,
  memoryGraph: ["memory-graph"] as const,
  voiceTrace: ["voice-trace"] as const,
  auftragsbuch: ["auftragsbuch"] as const,
  ideen: ["ideen"] as const,
  chronik: ["chronik"] as const,
  wissen: ["wissen"] as const,
  zeitmaschine: ["zeitmaschine"] as const,
  reminders: ["reminders"] as const,
}

// ── Polling-Takte ────────────────────────────────────────────────────────────
// EINE Stelle für alle Intervalle. Regel: Die Live-Graphen (System/Token) takten
// schnell, alles andere gemächlich — Mutationen invalidieren ohnehin gezielt,
// Polling ist nur das Sicherheitsnetz. Komponenten übergeben KEINE eigenen
// Intervalle mehr (mehrere Beobachter = kleinstes Intervall gewinnt).
const TAKT = {
  graph: 3_000,        // Live-Graphen im Cockpit (System, Token-Durchsatz)
  schnell: 8_000,      // „fühlt sich live an": Modelle, Voice-Trace, Auftragsbuch
  normal: 10_000,      // Dienste, Routing, Agent-Status, Health
  gemuetlich: 30_000,  // Chronik, Ideen
  traege: 60_000,      // Updates-Check, Reminders, Zeitmaschine, HF-Abfragen
} as const

// Auftragsbuch: Vorschlags-Inbox (Branches + Skill-Kandidaten). Pollt, damit laufende
// Annahme-Läufe (Status aus der JSON-Datei des Runners) live sichtbar werden.
export const useAuftragsbuch = (refetchInterval: number = TAKT.schnell) =>
  useQuery({
    queryKey: qk.auftragsbuch,
    queryFn: () => api<AuftragsbuchResp>("/api/auftragsbuch"),
    refetchInterval,
  })

// Ideen-Queue (natives Hermes-Kanban): das Backend cached ~15 s, öfter pollen lohnt nicht.
export const useIdeen = (refetchInterval: number = TAKT.gemuetlich) =>
  useQuery({
    queryKey: qk.ideen,
    queryFn: () => api<IdeenResp>("/api/ideen"),
    refetchInterval,
  })

// Ideen-Log (Live Worker Log): pollt nur solange Idee triage/running UND offen
export const useIdeenLog = (id: string, enabled: boolean = false) =>
  useQuery({
    queryKey: ["ideen-log", id],
    queryFn: () => api<IdeenLogResp>(`/api/ideen/${id}/log`),
    enabled,
    refetchInterval: 4000, // alle ~4s
    staleTime: 0,
  })

export const useChronik = (limit = 150, refetchInterval: number = TAKT.gemuetlich) =>
  useQuery({
    queryKey: qk.chronik,
    queryFn: () => api<ChronikResp>(`/api/chronik?limit=${limit}`),
    refetchInterval,
    select: (d) => d.items ?? [],
  })

export const useWissen = () =>
  useQuery({ queryKey: qk.wissen, queryFn: () => api<WissenResp>("/api/wissen") })

export const useZeitmaschine = (refetchInterval: number = TAKT.traege) =>
  useQuery({
    queryKey: qk.zeitmaschine,
    queryFn: () => api<ZeitmaschineResp>("/api/zeitmaschine"),
    refetchInterval,
  })

export const useReminders = (refetchInterval: number = TAKT.traege) =>
  useQuery({
    queryKey: qk.reminders,
    queryFn: () => api<{ items: Reminder[] }>("/api/reminders"),
    refetchInterval,
    select: (d) => d.items ?? [],
  })

// Per-Turn-Latenz-Trace (letzte N Voice/Lucy-Turns mit Stufen-Breakdown).
export const useVoiceTrace = (limit = 12, refetchInterval: number = TAKT.schnell) =>
  useQuery({
    queryKey: qk.voiceTrace,
    queryFn: () => api<VoiceTraceResp>(`/api/voice/trace?limit=${limit}`),
    refetchInterval,
    select: (d) => d.turns ?? [],
  })

export const useMemoryGraph = (enabled = true) =>
  useQuery({
    queryKey: qk.memoryGraph,
    queryFn: () => api<MemoryGraph>("/api/memory/graph"),
    enabled,
  })

export const useHealth = () =>
  useQuery({ queryKey: qk.health, queryFn: () => api<Health>("/api/health"), refetchInterval: TAKT.normal })

export const useSystemStatus = (refetchInterval: number = TAKT.graph) =>
  useQuery({ queryKey: qk.systemStatus, queryFn: () => api<SystemStatus>("/api/system/status"), refetchInterval })

export const useServices = (refetchInterval: number = TAKT.normal) =>
  useQuery({ queryKey: qk.services, queryFn: () => api<ServicesResp>("/api/system/services"), refetchInterval })

export const useModels = (refetchInterval: number = TAKT.schnell) =>
  useQuery({ queryKey: qk.models, queryFn: () => api<ModelsResp>("/api/models"), refetchInterval })

export const useGroups = (refetchInterval: number = TAKT.normal) =>
  useQuery({ queryKey: qk.groups, queryFn: () => api<GroupsResp>("/api/groups"), refetchInterval })

export const useRouting = (refetchInterval: number = TAKT.normal) =>
  useQuery({ queryKey: qk.routing, queryFn: () => api<RoutingResp>("/api/routing"), refetchInterval })

export const useRoutingPolicy = () =>
  useQuery({ queryKey: qk.routingPolicy, queryFn: () => api<RoutingPolicyMeta>("/api/routing/policy") })

// Jobs (Downloads) takten etwas schneller, damit Fortschritts-Balken flüssig wirken.
export const useJobs = (refetchInterval = 3_000) =>
  useQuery({
    queryKey: qk.jobs,
    queryFn: () => api<{ jobs: Job[] }>("/api/jobs"),
    refetchInterval,
    select: (d) => d.jobs ?? [],
  })

export const useTokenStats = (refetchInterval: number = TAKT.graph) =>
  useQuery({ queryKey: qk.tokenStats, queryFn: () => api<TokenStats>("/api/system/token-stats"), refetchInterval })

export const useAgentStatus = (refetchInterval: number = TAKT.normal) =>
  useQuery({ queryKey: qk.agentStatus, queryFn: () => api<AgentStatus>("/api/agent/status"), refetchInterval })

// Agent-Hirn (Hermes) + bestes NousResearch-Update. Selten pollen (HF-Abfrage).
export const useHermesBrain = (refetchInterval: number = TAKT.traege) =>
  useQuery({ queryKey: qk.hermesBrain, queryFn: () => api<HermesBrainResp>("/api/agent/brain"), refetchInterval })

// Updates-Check ist teuer (apt/git auf der Box) — träge pollen reicht völlig.
export const useUpdates = (refetchInterval: number = TAKT.traege) =>
  useQuery({ queryKey: qk.updates, queryFn: () => api<UpdatesResp>("/api/maintenance/updates"), refetchInterval })

export const useDiscover = () =>
  useQuery({ queryKey: qk.discover, queryFn: () => api<DiscoverResp>("/api/discover") })

// Verfügbare Spec-Draft-Modelle + Vocab-Kompatibilität zum Ziel-Modell (GGUF-Pfad).
export const useDrafts = (target?: string) =>
  useQuery({
    queryKey: qk.drafts(target),
    queryFn: () => api<DraftsResp>(`/api/models/drafts?target=${encodeURIComponent(target ?? "")}`),
    enabled: !!target,
  })

export const useConnect = (params?: string) =>
  useQuery({
    queryKey: qk.connect(params),
    queryFn: () => api<ConnectResp>(params ? `/api/connect?${params}` : "/api/connect"),
  })

// Live-Status der zwei Leitungen (Gateway + Gedächtnis) — alle 15s aktualisiert.
export const useConnectHealth = () =>
  useQuery({
    queryKey: qk.connectHealth,
    queryFn: () => api<ConnectHealth>("/api/connect/health"),
    refetchInterval: 15000,
  })

export const useMemory = (opts?: { q?: string; category?: string; limit?: number }) =>
  useQuery({
    queryKey: qk.memory(opts?.q, opts?.category),
    queryFn: () => {
      const p = new URLSearchParams()
      if (opts?.q) p.set("q", opts.q)
      if (opts?.category) p.set("category", opts.category)
      return api<Memory[]>(`/api/memory?${p}`)
    },
    select: (d) => (opts?.limit ? d.slice(0, opts.limit) : d),
  })

/** Nach Mutationen die betroffenen Listen-Queries neu ziehen. */
export function invalidate(qc: QueryClient, ...keys: readonly unknown[][]) {
  for (const key of keys) qc.invalidateQueries({ queryKey: key })
}

export { useQueryClient }
