import { cache } from "react";
import { getSessionClientId } from "@/lib/auth";
import { connectDB } from "@/lib/db";
import { Client } from "@/models/Client";
import { Position } from "@/models/Position";
import { PERMISSIONS, type Permission } from "@/lib/permissions";

// Mitarbeiter sind normale Client-Accounts mit role "staff" — ein Login für
// beides (Kunde + Admin), statt eines separaten env-basierten Admin-Zugangs.
// Ersetzt den früheren Phase-2-Übergangs-Login (separates Cookie, feste
// ADMIN_USERNAME/ADMIN_PASSWORD) — dieselbe Session (rakku_session) trägt
// jetzt beide Rollen.
//
// Mit react `cache()` memoisiert: viele Team-API-Routen rufen isAdminSession()
// UND (mehrfach) hasPermission()/getAllPermissions() innerhalb derselben
// Anfrage auf (z. B. documentsList.ts prüft bis zu 6 Kategorien nacheinander)
// — ohne Memoisierung war das vorher pro Aufruf ein eigener DB-Roundtrip.
// `cache()` dedupliziert gleiche Aufrufe innerhalb einer Anfrage automatisch,
// ohne die aufrufenden Routen anfassen zu müssen.
export const isAdminSession = cache(async (): Promise<boolean> => {
  const clientId = await getSessionClientId();
  if (!clientId) return false;
  await connectDB();
  const client = await Client.findById(clientId).select("role").lean();
  return client?.role === "staff";
});

// Feingranulare Berechtigung zusätzlich zu isAdminSession() prüfen. Rechte
// hängen an der zugewiesenen Position (Stelle), nicht am Mitarbeiter direkt —
// so werden sie einmal pro Position statt pro Person gepflegt. Staff ohne
// zugewiesene Position, oder deren Position kein Array gesetzt hat, gilt
// bewusst als voll berechtigt (Sicherheitsnetz gegen versehentliche
// Selbstaussperrung, z. B. für frisch beförderte Mitarbeiter oder neu
// angelegte Positionen) — erst ein explizit gesetztes Array grenzt ein.
export async function hasPermission(permission: Permission): Promise<boolean> {
  const all = await getAllPermissions();
  return all[permission];
}

// Für die Nav-Leiste: alle Berechtigungen in einem Rutsch statt einer
// Datenbankabfrage pro Link. Ebenfalls memoisiert (siehe isAdminSession
// oben) — hasPermission() ruft das bei jedem einzelnen Check auf, teils
// mehrfach pro Anfrage.
export const getAllPermissions = cache(async (): Promise<Record<Permission, boolean>> => {
  const none = Object.fromEntries(PERMISSIONS.map((p) => [p, false])) as Record<Permission, boolean>;
  const clientId = await getSessionClientId();
  if (!clientId) return none;
  await connectDB();
  const client = await Client.findById(clientId).select("role positionId").lean();
  if (client?.role !== "staff") return none;

  const all = Object.fromEntries(PERMISSIONS.map((p) => [p, true])) as Record<Permission, boolean>;
  if (!client.positionId) return all;
  const position = await Position.findById(client.positionId).select("permissions").lean();
  if (!position || !position.permissions) return all;
  const granted = new Set(position.permissions);
  return Object.fromEntries(PERMISSIONS.map((p) => [p, granted.has(p)])) as Record<Permission, boolean>;
});
