export interface DocumentDeletionTarget {
  id: string;
  tripId: string;
  storagePath: string | null;
}

export interface DocumentDeletionDependencies {
  loadTarget: (tripId: string, documentId: string) => Promise<DocumentDeletionTarget>;
  deleteStorageFile: (tripId: string, storagePath: string) => Promise<void>;
  deleteDatabaseRow: (tripId: string, documentId: string) => Promise<void>;
  reloadDocuments: (tripId: string) => Promise<void>;
}

export interface ParentDocumentDeletionDependencies<T> {
  loadTarget: () => Promise<{ target: T; storagePaths: string[] }>;
  deleteStorageFiles: (paths: string[]) => Promise<void>;
  deleteParentRow: (target: T) => Promise<void>;
  reload: () => Promise<void>;
}

export class PartialDocumentDeletionError extends Error {
  readonly cause: unknown;

  constructor(cause?: unknown) {
    super("Le fichier a été supprimé, mais l'enregistrement du document n'a pas pu être supprimé. Les documents ont été rechargés.");
    this.name = "PartialDocumentDeletionError";
    this.cause = cause;
  }
}

export class PartialParentDocumentDeletionError extends Error {
  readonly cause: unknown;

  constructor(cause?: unknown) {
    super("Les fichiers ont été supprimés, mais l'enregistrement principal n'a pas pu être supprimé. Les données ont été rechargées.");
    this.name = "PartialParentDocumentDeletionError";
    this.cause = cause;
  }
}

export async function deleteParentWithDocumentsSafely<T>(
  dependencies: ParentDocumentDeletionDependencies<T>,
): Promise<T> {
  const { target, storagePaths } = await dependencies.loadTarget();
  if (storagePaths.length > 0) await dependencies.deleteStorageFiles([...new Set(storagePaths)]);
  try {
    await dependencies.deleteParentRow(target);
  } catch (error) {
    try {
      await dependencies.reload();
    } catch (reloadError) {
      console.error("Impossible de recharger après une suppression partielle", reloadError);
    }
    throw new PartialParentDocumentDeletionError(error);
  }
  return target;
}

export async function deleteDocumentSafely(
  tripId: string,
  documentId: string,
  dependencies: DocumentDeletionDependencies,
): Promise<DocumentDeletionTarget> {
  const target = await dependencies.loadTarget(tripId, documentId);

  if (target.id !== documentId || target.tripId !== tripId) {
    throw new Error("Document introuvable ou non autorisé");
  }

  if (target.storagePath) await dependencies.deleteStorageFile(tripId, target.storagePath);

  try {
    await dependencies.deleteDatabaseRow(tripId, documentId);
  } catch (error) {
    try {
      await dependencies.reloadDocuments(tripId);
    } catch (reloadError) {
      console.error("Impossible de recharger les documents après une suppression partielle", reloadError);
    }

    throw new PartialDocumentDeletionError(error);
  }

  return target;
}
