validate([ 'file_id' => 'required|exists:files,id', 'attachable_type' => 'required|string|in:App\Models\Intervention,App\Models\Client,App\Models\Deceased', 'attachable_id' => 'required|integer', 'label' => 'nullable|string|max:255', 'sort_order' => 'nullable|integer|min:0', ]); // Verify the attachable model exists $attachableModel = $this->getAttachableModel($request->attachable_type, $request->attachable_id); if (!$attachableModel) { return response()->json([ 'message' => 'Le modèle cible n\'existe pas.', ], 404); } // Check if file is already attached to this model $existingAttachment = FileAttachment::where('file_id', $request->file_id) ->where('attachable_type', $request->attachable_type) ->where('attachable_id', $request->attachable_id) ->first(); if ($existingAttachment) { return response()->json([ 'message' => 'Ce fichier est déjà attaché à cet élément.', ], 422); } DB::beginTransaction(); try { // Create the attachment $attachment = FileAttachment::create([ 'file_id' => $request->file_id, 'attachable_type' => $request->attachable_type, 'attachable_id' => $request->attachable_id, 'label' => $request->label, 'sort_order' => $request->sort_order ?? 0, ]); // Load relationships for response $attachment->load('file'); DB::commit(); return response()->json([ 'data' => new FileAttachmentResource($attachment), 'message' => 'Fichier attaché avec succès.', ], 201); } catch (\Exception $e) { DB::rollBack(); throw $e; } } catch (\Exception $e) { Log::error('Error attaching file: ' . $e->getMessage(), [ 'exception' => $e, 'trace' => $e->getTraceAsString(), 'request_data' => $request->all(), ]); return response()->json([ 'message' => 'Une erreur est survenue lors de l\'attachement du fichier.', 'error' => config('app.debug') ? $e->getMessage() : null, ], 500); } } /** * Detach a file from a model */ public function detach(Request $request, string $attachmentId): JsonResponse { try { $attachment = FileAttachment::find($attachmentId); if (!$attachment) { return response()->json([ 'message' => 'Attachement de fichier non trouvé.', ], 404); } DB::beginTransaction(); try { $attachment->delete(); DB::commit(); return response()->json([ 'message' => 'Fichier détaché avec succès.', ], 200); } catch (\Exception $e) { DB::rollBack(); throw $e; } } catch (\Exception $e) { Log::error('Error detaching file: ' . $e->getMessage(), [ 'exception' => $e, 'trace' => $e->getTraceAsString(), 'attachment_id' => $attachmentId, ]); return response()->json([ 'message' => 'Une erreur est survenue lors du détachement du fichier.', 'error' => config('app.debug') ? $e->getMessage() : null, ], 500); } } /** * Update file attachment metadata */ public function update(Request $request, string $attachmentId): JsonResponse { try { $request->validate([ 'label' => 'nullable|string|max:255', 'sort_order' => 'nullable|integer|min:0', ]); $attachment = FileAttachment::find($attachmentId); if (!$attachment) { return response()->json([ 'message' => 'Attachement de fichier non trouvé.', ], 404); } DB::beginTransaction(); try { $attachment->update($request->only(['label', 'sort_order'])); $attachment->load('file'); DB::commit(); return response()->json([ 'data' => new FileAttachmentResource($attachment), 'message' => 'Attachement de fichier mis à jour avec succès.', ], 200); } catch (\Exception $e) { DB::rollBack(); throw $e; } } catch (\Exception $e) { Log::error('Error updating file attachment: ' . $e->getMessage(), [ 'exception' => $e, 'trace' => $e->getTraceAsString(), 'attachment_id' => $attachmentId, 'request_data' => $request->all(), ]); return response()->json([ 'message' => 'Une erreur est survenue lors de la mise à jour de l\'attachement.', 'error' => config('app.debug') ? $e->getMessage() : null, ], 500); } } /** * Get files attached to a specific model */ public function getAttachedFiles(Request $request): JsonResponse { try { $request->validate([ 'attachable_type' => 'required|string|in:App\Models\Intervention,App\Models\Client,App\Models\Deceased', 'attachable_id' => 'required|integer', ]); $attachments = FileAttachment::where('attachable_type', $request->attachable_type) ->where('attachable_id', $request->attachable_id) ->with('file') ->orderBy('sort_order') ->orderBy('created_at') ->get(); return response()->json([ 'data' => FileAttachmentResource::collection($attachments), 'count' => $attachments->count(), 'message' => 'Fichiers attachés récupérés avec succès.', ], 200); } catch (\Exception $e) { Log::error('Error getting attached files: ' . $e->getMessage(), [ 'exception' => $e, 'trace' => $e->getTraceAsString(), 'request_data' => $request->all(), ]); return response()->json([ 'message' => 'Une erreur est survenue lors de la récupération des fichiers attachés.', 'error' => config('app.debug') ? $e->getMessage() : null, ], 500); } } /** * Get files attached to an intervention */ public function getInterventionFiles(Request $request, int $interventionId): JsonResponse { try { $intervention = Intervention::find($interventionId); if (!$intervention) { return response()->json([ 'message' => 'Intervention non trouvée.', ], 404); } $attachments = $intervention->fileAttachments()->with('file')->get(); return response()->json([ 'data' => FileAttachmentResource::collection($attachments), 'count' => $attachments->count(), 'message' => 'Fichiers de l\'intervention récupérés avec succès.', ], 200); } catch (\Exception $e) { Log::error('Error getting intervention files: ' . $e->getMessage(), [ 'exception' => $e, 'trace' => $e->getTraceAsString(), 'intervention_id' => $interventionId, ]); return response()->json([ 'message' => 'Une erreur est survenue lors de la récupération des fichiers de l\'intervention.', 'error' => config('app.debug') ? $e->getMessage() : null, ], 500); } } /** * Get files attached to a client */ public function getClientFiles(Request $request, int $clientId): JsonResponse { try { $client = Client::find($clientId); if (!$client) { return response()->json([ 'message' => 'Client non trouvé.', ], 404); } $attachments = $client->fileAttachments()->with('file')->get(); return response()->json([ 'data' => FileAttachmentResource::collection($attachments), 'count' => $attachments->count(), 'message' => 'Fichiers du client récupérés avec succès.', ], 200); } catch (\Exception $e) { Log::error('Error getting client files: ' . $e->getMessage(), [ 'exception' => $e, 'trace' => $e->getTraceAsString(), 'client_id' => $clientId, ]); return response()->json([ 'message' => 'Une erreur est survenue lors de la récupération des fichiers du client.', 'error' => config('app.debug') ? $e->getMessage() : null, ], 500); } } /** * Get files attached to a deceased */ public function getDeceasedFiles(Request $request, int $deceasedId): JsonResponse { try { $deceased = Deceased::find($deceasedId); if (!$deceased) { return response()->json([ 'message' => 'Défunt non trouvé.', ], 404); } $attachments = $deceased->fileAttachments()->with('file')->get(); return response()->json([ 'data' => FileAttachmentResource::collection($attachments), 'count' => $attachments->count(), 'message' => 'Fichiers du défunt récupérés avec succès.', ], 200); } catch (\Exception $e) { Log::error('Error getting deceased files: ' . $e->getMessage(), [ 'exception' => $e, 'trace' => $e->getTraceAsString(), 'deceased_id' => $deceasedId, ]); return response()->json([ 'message' => 'Une erreur est survenue lors de la récupération des fichiers du défunt.', 'error' => config('app.debug') ? $e->getMessage() : null, ], 500); } } /** * Detach multiple files at once */ public function detachMultiple(Request $request): JsonResponse { try { $request->validate([ 'attachment_ids' => 'required|array|min:1', 'attachment_ids.*' => 'exists:file_attachments,id', ]); DB::beginTransaction(); try { $deletedCount = FileAttachment::whereIn('id', $request->attachment_ids)->delete(); DB::commit(); return response()->json([ 'deleted_count' => $deletedCount, 'message' => $deletedCount . ' fichier(s) détaché(s) avec succès.', ], 200); } catch (\Exception $e) { DB::rollBack(); throw $e; } } catch (\Exception $e) { Log::error('Error detaching multiple files: ' . $e->getMessage(), [ 'exception' => $e, 'trace' => $e->getTraceAsString(), 'attachment_ids' => $request->attachment_ids ?? [], ]); return response()->json([ 'message' => 'Une erreur est survenue lors du détachement des fichiers.', 'error' => config('app.debug') ? $e->getMessage() : null, ], 500); } } /** * Reorder file attachments */ public function reorder(Request $request): JsonResponse { try { $request->validate([ 'attachments' => 'required|array|min:1', 'attachments.*.id' => 'required|exists:file_attachments,id', 'attachments.*.sort_order' => 'required|integer|min:0', ]); DB::beginTransaction(); try { foreach ($request->attachments as $attachmentData) { FileAttachment::where('id', $attachmentData['id']) ->update(['sort_order' => $attachmentData['sort_order']]); } DB::commit(); return response()->json([ 'message' => 'Ordre des fichiers mis à jour avec succès.', ], 200); } catch (\Exception $e) { DB::rollBack(); throw $e; } } catch (\Exception $e) { Log::error('Error reordering file attachments: ' . $e->getMessage(), [ 'exception' => $e, 'trace' => $e->getTraceAsString(), 'attachments' => $request->attachments ?? [], ]); return response()->json([ 'message' => 'Une erreur est survenue lors de la réorganisation des fichiers.', 'error' => config('app.debug') ? $e->getMessage() : null, ], 500); } } /** * Get the attachable model instance */ private function getAttachableModel(string $type, int $id): ?Model { return match ($type) { Intervention::class => Intervention::find($id), Client::class => Client::find($id), Deceased::class => Deceased::find($id), default => null, }; } }