import prisma from '../lib/prisma.js';
import fs from 'fs';
import path from 'path';
import { assertValidDocumentPath } from '../utils/sanitize.js';

/**
 * Vollmachten für einen Kunden abrufen (wer darf diesen Kunden einsehen?)
 */
export async function getAuthorizationsForCustomer(customerId: number) {
  return prisma.representativeAuthorization.findMany({
    where: { customerId },
    include: {
      representative: {
        select: { id: true, customerNumber: true, firstName: true, lastName: true },
      },
    },
    orderBy: { createdAt: 'desc' },
  });
}

/**
 * Vollmachten die ein Vertreter erhalten hat (welche Kunden darf er einsehen?)
 */
export async function getAuthorizationsForRepresentative(representativeId: number) {
  return prisma.representativeAuthorization.findMany({
    where: { representativeId },
    include: {
      customer: {
        select: { id: true, customerNumber: true, firstName: true, lastName: true },
      },
    },
    orderBy: { createdAt: 'desc' },
  });
}

/**
 * Prüft ob ein Vertreter eine Vollmacht für einen Kunden hat
 */
export async function hasAuthorization(customerId: number, representativeId: number): Promise<boolean> {
  const auth = await prisma.representativeAuthorization.findUnique({
    where: {
      customerId_representativeId: { customerId, representativeId },
    },
  });

  return auth?.isGranted === true;
}

/**
 * Vollmacht erteilen oder aktualisieren
 */
export async function grantAuthorization(
  customerId: number,
  representativeId: number,
  data: { source?: string; documentPath?: string; notes?: string }
) {
  // Pentest 26.7 (Defense-in-Depth): documentPath nur als /uploads/<safe>.
  assertValidDocumentPath(data.documentPath, 'documentPath');
  return prisma.representativeAuthorization.upsert({
    where: {
      customerId_representativeId: { customerId, representativeId },
    },
    update: {
      isGranted: true,
      grantedAt: new Date(),
      withdrawnAt: null,
      source: data.source,
      documentPath: data.documentPath ?? undefined,
      notes: data.notes ?? undefined,
    },
    create: {
      customerId,
      representativeId,
      isGranted: true,
      grantedAt: new Date(),
      source: data.source || 'crm-backend',
      documentPath: data.documentPath,
      notes: data.notes,
    },
  });
}

/**
 * Vollmacht widerrufen + PDF löschen falls vorhanden
 */
export async function withdrawAuthorization(customerId: number, representativeId: number) {
  // Erst prüfen ob eine PDF vorhanden ist
  const existing = await prisma.representativeAuthorization.findUnique({
    where: { customerId_representativeId: { customerId, representativeId } },
    select: { documentPath: true },
  });

  // PDF vom Filesystem löschen
  if (existing?.documentPath) {
    try {
      const filePath = path.join(process.cwd(), existing.documentPath);
      if (fs.existsSync(filePath)) {
        fs.unlinkSync(filePath);
      }
    } catch (err) {
      console.error('Fehler beim Löschen der Vollmacht-PDF:', err);
    }
  }

  return prisma.representativeAuthorization.update({
    where: {
      customerId_representativeId: { customerId, representativeId },
    },
    data: {
      isGranted: false,
      withdrawnAt: new Date(),
      documentPath: null,
    },
  });
}

/**
 * Vollmacht-Dokument (PDF) hochladen
 */
export async function updateAuthorizationDocument(
  customerId: number,
  representativeId: number,
  documentPath: string
) {
  // Wenn Dokument hochgeladen wird, gilt das als Vollmacht erteilen
  return prisma.representativeAuthorization.upsert({
    where: {
      customerId_representativeId: { customerId, representativeId },
    },
    update: {
      documentPath,
      isGranted: true,
      grantedAt: new Date(),
      withdrawnAt: null,
      source: 'papier',
    },
    create: {
      customerId,
      representativeId,
      documentPath,
      isGranted: true,
      grantedAt: new Date(),
      source: 'papier',
    },
  });
}

/**
 * Vollmacht-Dokument löschen
 */
export async function deleteAuthorizationDocument(customerId: number, representativeId: number) {
  // Prüfen ob die Vollmacht per Papier erteilt wurde
  const auth = await prisma.representativeAuthorization.findUnique({
    where: { customerId_representativeId: { customerId, representativeId } },
    select: { source: true, documentPath: true },
  });

  if (!auth) throw new Error('Vollmacht nicht gefunden');

  // Datei löschen
  if (auth.documentPath) {
    try {
      const filePath = path.join(process.cwd(), auth.documentPath);
      if (fs.existsSync(filePath)) {
        fs.unlinkSync(filePath);
      }
    } catch (err) {
      console.error('Fehler beim Löschen der Vollmacht-PDF:', err);
    }
  }

  // Wenn per Papier erteilt → Vollmacht widerrufen
  // Wenn per Portal/Online erteilt → nur PDF entfernen, Vollmacht bleibt
  const withdrawData = auth.source === 'papier'
    ? { documentPath: null, isGranted: false, withdrawnAt: new Date() }
    : { documentPath: null };

  return prisma.representativeAuthorization.update({
    where: { customerId_representativeId: { customerId, representativeId } },
    data: withdrawData,
  });
}

/**
 * Alle genehmigten Vertreter-IDs für einen Kunden
 * (Welche Vertreter dürfen die Verträge dieses Kunden sehen?)
 */
export async function getAuthorizedRepresentativeIds(customerId: number): Promise<number[]> {
  const auths = await prisma.representativeAuthorization.findMany({
    where: { customerId, isGranted: true },
    select: { representativeId: true },
  });
  return auths.map((a) => a.representativeId);
}

/**
 * Alle Kunden-IDs für die ein Vertreter eine Vollmacht hat
 */
export async function getAuthorizedCustomerIds(representativeId: number): Promise<number[]> {
  const auths = await prisma.representativeAuthorization.findMany({
    where: { representativeId, isGranted: true },
    select: { customerId: true },
  });
  return auths.map((a) => a.customerId);
}

/**
 * Erstellt fehlende Vollmacht-Einträge für bestehende Vertreterbeziehungen
 * (wird aufgerufen wenn man den Tab aufruft)
 */
export async function ensureAuthorizationEntries(customerId: number) {
  // Alle aktiven Vertreter für diesen Kunden
  const representatives = await prisma.customerRepresentative.findMany({
    where: { customerId, isActive: true },
    select: { representativeId: true },
  });

  for (const rep of representatives) {
    // Erstelle Eintrag falls nicht vorhanden
    await prisma.representativeAuthorization.upsert({
      where: {
        customerId_representativeId: { customerId, representativeId: rep.representativeId },
      },
      update: {}, // Nichts ändern wenn schon vorhanden
      create: {
        customerId,
        representativeId: rep.representativeId,
        isGranted: false,
      },
    });
  }
}
