export const DOCUMENT_MAX_BYTES = 6 * 1024 * 1024;

export const DOCUMENT_ALLOWED_MIME_TYPES = new Set([
  "application/pdf",
  "text/plain",
  "text/csv",
  "image/jpeg",
  "image/png",
  "image/webp",
  "image/gif",
  "image/heic",
  "application/msword",
  "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
  "application/vnd.ms-excel",
  "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
  "application/vnd.ms-powerpoint",
  "application/vnd.openxmlformats-officedocument.presentationml.presentation",
]);

export interface DocumentUploadPlan {
  id: string;
  displayName: string;
  storagePath: string;
  mimeType: string;
  sizeBytes: number;
}

export function sanitizeDocumentFileName(fileName: string): string {
  const normalized = fileName
    .normalize("NFKD")
    .replace(/[\u0300-\u036f]/g, "")
    .replace(/[^A-Za-z0-9._-]+/g, "_")
    .replace(/\.{2,}/g, ".")
    .replace(/^[._-]+/, "")
    .slice(0, 180);
  return normalized || "document";
}

export function assertDocumentFile(file: Pick<File, "name" | "size" | "type">): void {
  if (!file.name.trim() || file.name.length > 255) throw new Error("Nom de fichier invalide.");
  if (file.size < 1) throw new Error("Le fichier est vide.");
  if (file.size > DOCUMENT_MAX_BYTES) throw new Error("Le fichier dépasse la limite de 6 Mio.");
  if (!DOCUMENT_ALLOWED_MIME_TYPES.has(file.type.toLowerCase())) {
    throw new Error("Ce type de fichier n'est pas autorisé.");
  }
}

export function createDocumentUploadPlan(
  tripId: string,
  file: Pick<File, "name" | "size" | "type">,
  documentId = crypto.randomUUID(),
): DocumentUploadPlan {
  assertDocumentFile(file);
  const physicalName = sanitizeDocumentFileName(file.name);
  return {
    id: documentId,
    displayName: file.name.trim(),
    storagePath: `${tripId}/${documentId}/${physicalName}`,
    mimeType: file.type.toLowerCase(),
    sizeBytes: file.size,
  };
}

export function assertDocumentStoragePath(tripId: string, path: string): void {
  const escapedTripId = tripId.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
  const pattern = new RegExp(`^${escapedTripId}/[0-9a-f-]{36}/[A-Za-z0-9][A-Za-z0-9._-]{0,179}$`);
  if (!pattern.test(path) || path.includes("..")) throw new Error("Chemin de document invalide.");
}

export function isManagedDocumentStoragePath(tripId: string, path: string): boolean {
  const escapedTripId = tripId.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
  const newPath = new RegExp(`^${escapedTripId}/[0-9a-f-]{36}/[A-Za-z0-9][A-Za-z0-9._-]{0,179}$`);
  const legacyPath = new RegExp(`^${escapedTripId}/[A-Za-z0-9][A-Za-z0-9._-]{0,179}$`);
  return !path.includes("..") && (newPath.test(path) || legacyPath.test(path));
}
