false, 'error' => 'Método no permitido. Use POST o DELETE.']); exit; } try { $input = json_decode(file_get_contents('php://input'), true); // También soportar query params para DELETE if (!$input && $_SERVER['REQUEST_METHOD'] === 'DELETE') { $input = [ 'message_id' => $_GET['message_id'] ?? $_GET['id'] ?? null, 'delete_for_everyone' => $_GET['delete_for_everyone'] ?? false ]; } if (!$input) { http_response_code(400); echo json_encode(['success' => false, 'error' => 'JSON inválido']); exit; } $messageId = $input['message_id'] ?? $input['id'] ?? null; $deleteForEveryone = $input['delete_for_everyone'] ?? false; $softDelete = $input['soft_delete'] ?? true; // Por defecto, soft delete if (!$messageId) { http_response_code(400); echo json_encode(['success' => false, 'error' => 'message_id es requerido']); exit; } $db = Database::getInstance(); // Buscar el mensaje $sql = "SELECT id, user_id, direction, message_type, content, message_id as wa_message_id, local_file, local_thumb, media_url FROM conversations WHERE id = :mid1 OR message_id = :mid2 LIMIT 1"; $message = $db->fetch($sql, ['mid1' => $messageId, 'mid2' => $messageId]); if (!$message) { http_response_code(404); echo json_encode(['success' => false, 'error' => 'Mensaje no encontrado']); exit; } // Solo permitir eliminar mensajes salientes (outgoing) a menos que sea admin $isAdmin = isset($_SESSION['admin_logged_in']) && $_SESSION['admin_logged_in']; if ($message['direction'] !== 'outgoing' && !$isAdmin) { http_response_code(403); echo json_encode(['success' => false, 'error' => 'Solo puedes eliminar tus propios mensajes']); exit; } $deletedMessageId = $message['id']; $userId = $message['user_id']; $waMessageId = $message['wa_message_id']; if ($softDelete) { // Soft delete: marcar como eliminado pero mantener registro // Verificar si existen las columnas deleted_at y original_content $hasDeletedAt = false; $hasOriginalContent = false; try { $columns = $db->fetchAll("SHOW COLUMNS FROM conversations WHERE Field IN ('deleted_at', 'original_content')"); foreach ($columns as $col) { if ($col['Field'] === 'deleted_at') $hasDeletedAt = true; if ($col['Field'] === 'original_content') $hasOriginalContent = true; } } catch (Exception $e) { // Ignorar } // Construir la query según las columnas disponibles // IMPORTANTE: Guardar original_content ANTES de modificar content if ($hasDeletedAt && $hasOriginalContent) { // Primero guardamos el contenido original $db->execute("UPDATE conversations SET original_content = content WHERE id = :id AND original_content IS NULL", ['id' => $deletedMessageId]); // Luego marcamos como eliminado $updateSql = "UPDATE conversations SET content = '[Mensaje eliminado]', deleted_at = NOW() WHERE id = :id"; } elseif ($hasDeletedAt) { $updateSql = "UPDATE conversations SET content = '[Mensaje eliminado]', deleted_at = NOW() WHERE id = :id"; } else { $updateSql = "UPDATE conversations SET content = '[Mensaje eliminado]' WHERE id = :id"; } $db->execute($updateSql, ['id' => $deletedMessageId]); error_log("Message soft-deleted: ID={$deletedMessageId}, User={$userId}"); } else { // Hard delete: eliminar completamente // Primero, eliminar archivos multimedia asociados si existen if (!empty($message['local_file'])) { $filePath = dirname(__DIR__) . '/' . $message['local_file']; if (file_exists($filePath)) { @unlink($filePath); error_log("Deleted media file: {$filePath}"); } } if (!empty($message['local_thumb'])) { $thumbPath = dirname(__DIR__) . '/' . $message['local_thumb']; if (file_exists($thumbPath)) { @unlink($thumbPath); error_log("Deleted thumbnail: {$thumbPath}"); } } // Eliminar el mensaje de la base de datos $deleteSql = "DELETE FROM conversations WHERE id = :id"; $db->execute($deleteSql, ['id' => $deletedMessageId]); error_log("Message hard-deleted: ID={$deletedMessageId}, User={$userId}"); } // Intentar notificar por SSE si está disponible try { $ssePayload = [ 'type' => 'message_deleted', 'user_id' => $userId, 'message_id' => $deletedMessageId, 'wa_message_id' => $waMessageId, 'soft_delete' => $softDelete, 'deleted_at' => date('Y-m-d H:i:s') ]; // Llamar al endpoint push_event interno $pushUrl = 'http://127.0.0.1' . dirname($_SERVER['SCRIPT_NAME']) . '/push_event.php'; $ch = curl_init($pushUrl); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([ 'event_type' => 'message_deleted', 'data' => $ssePayload, 'target_user_id' => 'all' ])); curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_TIMEOUT, 2); curl_exec($ch); curl_close($ch); } catch (Exception $sseErr) { error_log("delete_message: SSE notification failed: " . $sseErr->getMessage()); } echo json_encode([ 'success' => true, 'message' => $softDelete ? 'Mensaje eliminado' : 'Mensaje eliminado permanentemente', 'data' => [ 'id' => $deletedMessageId, 'message_id' => $waMessageId, 'soft_delete' => $softDelete, 'deleted_at' => date('Y-m-d H:i:s') ] ]); } catch (Exception $e) { error_log('delete_message.php error: ' . $e->getMessage() . ' | Trace: ' . $e->getTraceAsString()); http_response_code(500); echo json_encode(['success' => false, 'error' => 'Error interno del servidor', 'debug' => $e->getMessage()]); }