"use server";

import { revalidatePath } from "next/cache";
import { connectDB } from "@/lib/db";
import { Client } from "@/models/Client";
import { SensitiveDataAccessLog } from "@/models/SensitiveDataAccessLog";
import { getSessionClientId } from "@/lib/auth";
import { hasPermission } from "@/lib/adminAuth";
import { encryptSensitive, decryptSensitive } from "@/lib/encryption";

// Zugriff strikt auf: die betroffene Person selbst ODER jemand mit der
// eigenen, engen Berechtigung "payroll_sensitive_data" - explizite
// Sicherheitsanforderung (Personalsystem, 24.09.2026), auch ein normaler
// Admin mit z. B. "hr" allein darf hier NICHT ran.
async function checkAccess(targetClientId: string): Promise<{ viewerId: string; isSelf: boolean } | null> {
  const viewerId = await getSessionClientId();
  if (!viewerId) return null;
  const isSelf = viewerId === targetClientId;
  if (isSelf) return { viewerId, isSelf };
  if (await hasPermission("payroll_sensitive_data")) return { viewerId, isSelf: false };
  return null;
}

type SensitiveDataResult = { error?: string; iban?: string; socialSecurityNumber?: string; taxId?: string };

// Bewusst nur auf Anfrage (Button-Klick im UI) statt beim Seitenaufruf schon
// automatisch zu entschlüsseln + auszuliefern - sonst wäre das
// "viewed"-Audit-Log auch weniger aussagekräftig (jeder Seitenaufruf würde
// sonst als "angesehen" gelten, nicht nur ein bewusster Klick).
export async function getSensitiveDataAction(clientId: string): Promise<SensitiveDataResult> {
  const access = await checkAccess(clientId);
  if (!access) return { error: "Keine Berechtigung." };

  await connectDB();
  const client = await Client.findById(clientId).select("encryptedIban encryptedSocialSecurityNumber encryptedTaxId").lean();
  if (!client) return { error: "Nicht gefunden." };

  if (!access.isSelf) {
    await SensitiveDataAccessLog.create({ clientId, accessedByClientId: access.viewerId, action: "viewed" });
  }

  return {
    iban: decryptSensitive(client.encryptedIban),
    socialSecurityNumber: decryptSensitive(client.encryptedSocialSecurityNumber),
    taxId: decryptSensitive(client.encryptedTaxId),
  };
}

export async function setSensitiveDataAction(clientId: string, formData: FormData): Promise<{ error?: string; success?: boolean }> {
  const access = await checkAccess(clientId);
  if (!access) return { error: "Keine Berechtigung." };

  await connectDB();
  await Client.findByIdAndUpdate(clientId, {
    encryptedIban: encryptSensitive(String(formData.get("iban") || "").trim()),
    encryptedSocialSecurityNumber: encryptSensitive(String(formData.get("socialSecurityNumber") || "").trim()),
    encryptedTaxId: encryptSensitive(String(formData.get("taxId") || "").trim()),
  });
  // Anders als beim Ansehen IMMER geloggt, auch bei einer Selbstbearbeitung -
  // eine Änderung ist bei Finanzdaten grundsätzlich audit-relevant.
  await SensitiveDataAccessLog.create({ clientId, accessedByClientId: access.viewerId, action: "edited" });

  revalidatePath(`/de/admin/team/${clientId}`);
  revalidatePath("/de/account/profile");
  return { success: true };
}

// Nur für die Admin-Ansicht (payroll_sensitive_data) - wer hat wann auf
// diese Daten zugegriffen/sie geändert.
export async function getSensitiveDataAuditLogAction(clientId: string) {
  if (!(await hasPermission("payroll_sensitive_data"))) return [];
  await connectDB();
  const entries = await SensitiveDataAccessLog.find({ clientId }).sort({ createdAt: -1 }).limit(20).lean();
  const byIds = await Client.find({ _id: { $in: entries.map((e) => String(e.accessedByClientId)) } }).select("name").lean();
  const nameById = new Map(byIds.map((c) => [String(c._id), c.name]));
  return entries.map((e) => ({
    id: String(e._id),
    action: e.action,
    byName: nameById.get(String(e.accessedByClientId)) || "—",
    at: e.createdAt.toISOString(),
  }));
}
