import crypto from "crypto";
import { connectDB } from "@/lib/db";
import { SystemLog, type SystemLogLevel, type SystemLogSource } from "@/models/SystemLog";

type LogInput = {
  level?: SystemLogLevel;
  source?: SystemLogSource;
  message: string;
  stack?: string;
  digest?: string;
  route?: string;
  method?: string;
  statusCode?: number | null;
  actorId?: string | null;
  context?: Record<string, unknown>;
};

function fingerprint(message: string, stack: string) {
  const firstFrame = (stack.split("\n").find((l) => l.trim().startsWith("at ")) || "").trim();
  return crypto.createHash("sha1").update(`${message}\n${firstFrame}`).digest("hex").slice(0, 40);
}

// Der Logger darf NIE selbst werfen — ein Fehler beim Fehler-Loggen würde
// sonst die eigentliche Fehlerseite verschlucken. Alles in try/catch,
// Konsole als letzter Ausweg.
export async function logSystem(input: LogInput): Promise<void> {
  try {
    await connectDB();
    const message = String(input.message || "Unbekannter Fehler").slice(0, 2000);
    const stack = String(input.stack || "").slice(0, 12000);
    const actorId = input.actorId && /^[a-f0-9]{24}$/i.test(input.actorId) ? input.actorId : null;
    await SystemLog.create({
      level: input.level || "error",
      source: input.source || "render",
      message,
      stack,
      digest: (input.digest || "").slice(0, 120),
      route: (input.route || "").slice(0, 400),
      method: (input.method || "").slice(0, 16),
      statusCode: input.statusCode ?? null,
      actorId,
      fingerprint: fingerprint(message, stack),
      context: input.context && typeof input.context === "object" ? input.context : {},
    });
  } catch (err) {
    console.error("[systemLog] Eintrag konnte nicht gespeichert werden:", err);
  }
}
