import type { ActivityEvent } from "./types";

export interface KubernetesLifecycleObject {
  uid: string; resourceVersion: string; kind: "Job" | "Pod"; namespace: string; name: string;
  nodeName?: string; buildKey?: string; sessionId?: string; createdAt?: string; startedAt?: string;
  phase?: string; finishedAt?: string; reason?: string;
}

function event(object: KubernetesLifecycleObject, transition: string, ts: string, severity: ActivityEvent["severity"]): ActivityEvent {
  return {
    id: `kubernetes:${object.uid}:${transition}:${object.resourceVersion}`,
    ts, category: object.buildKey ? "buildbox" : "service", source: "kubernetes", actor: "system", severity,
    title: `${object.kind} ${object.namespace}/${object.name} ${transition}`,
    ...(object.nodeName ? { host: object.nodeName } : {}), ...(object.sessionId ? { session: object.sessionId } : {}),
    detail: { namespace: object.namespace, kind: object.kind, uid: object.uid, workloadUid: object.uid, workloadName: object.name,
      resourceVersion: object.resourceVersion, transition, ...(object.buildKey ? { buildKey: object.buildKey } : {}),
      ...(object.phase ? { phase: object.phase } : {}), ...(object.reason ? { reason: object.reason } : {}) },
    dedupeKey: `kubernetes:${object.uid}:${transition}`,
  };
}

export function lifecycleTransitions(previous: Map<string, KubernetesLifecycleObject>, current: KubernetesLifecycleObject[], observedAt: string): ActivityEvent[] {
  const events: ActivityEvent[] = [];
  const next = new Map(current.map((object) => [object.uid, object]));
  for (const object of current) {
    const before = previous.get(object.uid);
    if (!before && object.kind === "Job") events.push(event(object, "accepted", object.createdAt ?? observedAt, "info"));
    if (object.kind === "Pod" && object.nodeName && !before?.nodeName) events.push(event(object, "scheduled", observedAt, "info"));
    if (object.startedAt && !before?.startedAt) events.push(event(object, "started", object.startedAt, "info"));
    const terminal = object.phase === "Succeeded" ? "completed" : object.phase === "Failed" ? "failed" : undefined;
    const priorTerminal = before?.phase === "Succeeded" || before?.phase === "Failed";
    if (terminal && !priorTerminal) events.push(event(object, terminal, object.finishedAt ?? observedAt, terminal === "failed" ? "error" : "notice"));
  }
  for (const object of previous.values()) if (!next.has(object.uid)) events.push(event(object, "deleted", observedAt, "notice"));
  return events;
}
