import { Fuel, ShieldAlert, Check } from "lucide-react"
import { useGovernor } from "@/lib/queries"
import type { GovernorRun } from "@/lib/api"

// ── Token-Wächter („Tankuhr mit Handbremse") ────────────────────────────────
// Zeigt in Klartext, wie voll die laufende Coding-Sitzung ist. Zwei Marken:
//   Soft  = ab hier bittet der Governor um einen Savepoint (Sitzung sauber beenden)
//   Hart  = ab hier antwortet er selbst und lässt das Modell gar nicht mehr ran
// Die Zeile „Schätzung vs. Wahrheit" ist der Ehrlichkeits-Nachweis: bis 25.07. lag der
// Governor bei werkzeugdichten Agenten um Faktor 3 daneben, weil er Werkzeug-Schemata
// nicht mitzählte. Jetzt lernt er aus den echten prompt_tokens jeder Antwort.

const fmtNum = (n: number | null | undefined) =>
  n == null ? "–" : n.toLocaleString("de-DE")

function ago(ts: number): string {
  const s = Math.max(0, Date.now() / 1000 - ts)
  if (s < 60) return `vor ${Math.round(s)} s`
  if (s < 3600) return `vor ${Math.round(s / 60)} min`
  return `vor ${Math.round(s / 3600)} h`
}

const ACTION_META: Record<string, { label: string; tone: string }> = {
  passthrough: { label: "frei", tone: "text-emerald-400" },
  defer: { label: "wartet", tone: "text-amber-400" },
  soft: { label: "Savepoint", tone: "text-amber-400" },
  hard: { label: "STOPP", tone: "text-rose-400" },
}

/** Abweichung Schätzung↔Wahrheit in Prozent — der Ehrlichkeits-Messwert. */
function drift(run: GovernorRun | undefined): number | null {
  if (!run?.est || !run?.exact) return null
  return ((run.est - run.exact) / run.exact) * 100
}

export function GovernorCard() {
  const { data } = useGovernor()

  if (!data?.reachable) {
    return (
      <div className="mc-card p-5">
        <div className="flex items-center gap-2">
          <Fuel className="h-4.5 w-4.5 text-muted-foreground" />
          <h2 className="text-sm font-semibold uppercase tracking-wide text-foreground">Token-Wächter</h2>
        </div>
        <div className="mt-3 text-xs text-muted-foreground">
          Nicht erreichbar. Die Coding-Sitzungen laufen dann ohne Sitzungs-Bremse.
          <div className="mt-1 font-mono text-[10px] text-muted-foreground/60">
            {data?.error ?? "keine Antwort von :8100"}
          </div>
        </div>
      </div>
    )
  }

  const soft = data.soft ?? 0
  const hard = data.hard ?? null
  const runs = data.recent ?? []
  // Nur echte Bau-Läufe füllen die Tankuhr; Lucys Gespräche sind ausgenommen.
  const lastBuild = runs.find((r) => !(data.exempt_models ?? []).includes(r.model))
  const füllung = lastBuild?.exact ?? lastBuild?.est ?? 0
  const skala = Math.max(hard ?? soft * 1.2, soft * 1.2, füllung)
  const pct = Math.min(100, (füllung / skala) * 100)
  const abw = drift(runs.find((r) => r.est != null && r.exact != null))
  const c = data.counters

  const tone =
    hard && füllung >= hard ? "bg-rose-500"
      : füllung >= soft ? "bg-amber-500"
        : "bg-emerald-500"

  return (
    <div className="mc-card p-5">
      <div className="mb-3 flex items-start justify-between gap-3">
        <div>
          <div className="flex items-center gap-2">
            <Fuel className="h-4.5 w-4.5 text-primary" />
            <h2 className="text-sm font-semibold uppercase tracking-wide text-foreground">Token-Wächter</h2>
            <span className="ml-1 inline-flex items-center gap-1 text-[10px] font-medium text-muted-foreground/70">
              <span className="h-1.5 w-1.5 rounded-full bg-emerald-500 animate-pulse" /> live
            </span>
          </div>
          <div className="mt-2 flex items-baseline gap-2">
            <span className="font-space text-3xl font-bold tracking-tight tabular-nums text-foreground">
              {fmtNum(füllung)}
            </span>
            <span className="text-xs text-muted-foreground">
              Tokens in der letzten Bau-Anfrage
            </span>
          </div>
        </div>
        <div className="shrink-0 pt-1 text-right">
          <div className="text-[11px] font-semibold uppercase tracking-wider text-amber-400">
            Savepoint ab {fmtNum(soft)}
          </div>
          {hard != null && (
            <div className="text-[11px] font-semibold uppercase tracking-wider text-rose-400">
              Stopp ab {fmtNum(hard)}
            </div>
          )}
        </div>
      </div>

      {/* Tankuhr */}
      <div className="relative h-3 overflow-hidden rounded-sm bg-muted/25">
        <div className={`h-full ${tone} transition-all`} style={{ width: `${pct}%` }} />
        <div
          className="absolute inset-y-0 w-px bg-amber-400/80"
          style={{ left: `${Math.min(100, (soft / skala) * 100)}%` }}
          title={`Savepoint-Marke ${fmtNum(soft)}`}
        />
        {hard != null && (
          <div
            className="absolute inset-y-0 w-px bg-rose-400/80"
            style={{ left: `${Math.min(100, (hard / skala) * 100)}%` }}
            title={`Harter Stopp ${fmtNum(hard)}`}
          />
        )}
      </div>

      {/* Zählerstand */}
      <div className="mt-3 grid grid-cols-4 gap-2 text-center">
        {[
          { k: "Anfragen", v: fmtNum(c?.chat) },
          { k: "Savepoints", v: fmtNum(c?.soft) },
          { k: "Stopps", v: fmtNum(c?.hard) },
          { k: "Tokens ges.", v: fmtNum(c?.tokens_prompt) },
        ].map((x) => (
          <div key={x.k} className="rounded-sm bg-muted/20 py-1.5">
            <div className="font-mono text-sm font-semibold tabular-nums text-foreground">{x.v}</div>
            <div className="text-[10px] uppercase tracking-wider text-muted-foreground/70">{x.k}</div>
          </div>
        ))}
      </div>

      {/* Ehrlichkeits-Nachweis */}
      {abw != null && (
        <div className="mt-3 flex items-center gap-2 rounded-sm bg-muted/15 px-2.5 py-1.5">
          {Math.abs(abw) < 15
            ? <Check className="h-3.5 w-3.5 shrink-0 text-emerald-400" />
            : <ShieldAlert className="h-3.5 w-3.5 shrink-0 text-amber-400" />}
          <span className="text-[11px] text-muted-foreground">
            Schätzung lag{" "}
            <span className={Math.abs(abw) < 15 ? "font-semibold text-emerald-400" : "font-semibold text-amber-400"}>
              {abw > 0 ? "+" : ""}{abw.toFixed(1)} %
            </span>{" "}
            neben der Wahrheit — er kalibriert sich aus jeder Antwort selbst nach.
          </span>
        </div>
      )}

      {/* Letzte Läufe */}
      {runs.length > 0 && (
        <div className="mt-3 space-y-1">
          {runs.slice(0, 5).map((r, i) => {
            const m = ACTION_META[r.action] ?? { label: r.action, tone: "text-muted-foreground" }
            return (
              <div key={`${r.t}-${i}`} className="flex items-center gap-2 text-[11px]">
                <span className="w-14 shrink-0 text-right font-mono text-[10px] text-muted-foreground/60">{ago(r.t)}</span>
                <span className="w-20 shrink-0 truncate font-medium text-foreground">{r.model || "?"}</span>
                <span className="flex-1 font-mono tabular-nums text-muted-foreground">
                  {fmtNum(r.exact ?? r.est)}
                  {r.exact != null && r.est != null && (
                    <span className="text-muted-foreground/50"> (geschätzt {fmtNum(r.est)})</span>
                  )}
                </span>
                <span className={`shrink-0 font-semibold ${m.tone}`}>{m.label}</span>
              </div>
            )
          })}
        </div>
      )}

      <div className="mt-3 border-t border-border/30 pt-2 text-[10px] leading-relaxed text-muted-foreground/70">
        Alle Coding-Agenten laufen durch den Wächter (:8100). Lucys Alltagsmodelle sind
        ausgenommen — ein Gespräch ist keine Bau-Sitzung und wird nie unterbrochen.
      </div>
    </div>
  )
}
