false, 'error' => 'Method not allowed']); exit; } try { $input = json_decode(file_get_contents('php://input'), true) ?: []; $messageId = isset($input['message_id']) ? intval($input['message_id']) : 0; if (!$messageId) { echo json_encode(['success' => false, 'error' => 'message_id requerido']); exit; } $db = Database::getInstance(); // Obtener info del mensaje $msg = $db->fetchOne( "SELECT id, media_url, whatsapp_media_id, message_type, local_file, conversation_id FROM conversations WHERE id = ?", [$messageId] ); if (!$msg) { echo json_encode(['success' => false, 'error' => 'Mensaje no encontrado']); exit; } // Si ya tiene archivo local, retornar éxito directo if (!empty($msg['local_file']) && file_exists($_SERVER['DOCUMENT_ROOT'] . '/' . $msg['local_file'])) { echo json_encode(['success' => true, 'status' => 'already_downloaded', 'local_file' => $msg['local_file']]); exit; } // Determinar el media_id a descargar $mediaId = !empty($msg['whatsapp_media_id']) ? $msg['whatsapp_media_id'] : $msg['media_url']; if (empty($mediaId)) { echo json_encode(['success' => false, 'error' => 'Sin media_id disponible']); exit; } // Buscar o crear entrada en media_queue $existing = $db->fetchOne( "SELECT id, status, attempts FROM media_queue WHERE conversation_id = ? OR media_id = ? LIMIT 1", [$msg['id'], $mediaId] ); if ($existing) { // Resetear a pending para que sea procesado $db->query( "UPDATE media_queue SET status = 'pending', attempts = 0, result = NULL, updated_at = NOW() WHERE id = ?", [$existing['id']] ); $queueId = $existing['id']; } else { // Crear nueva entrada en la cola $convInfo = $db->fetchOne("SELECT user_id FROM conversations WHERE id = ?", [$msg['id']]); $userId = $convInfo['user_id'] ?? 0; // Determinar subdirectorio por mes $subdir = date('Y/m'); $db->query( "INSERT INTO media_queue (media_id, subdir, status, attempts, conversation_id, media_url, message_type, created_at) VALUES (?, ?, 'pending', 0, ?, ?, ?, NOW())", [$mediaId, $subdir, $msg['id'], $mediaId, $msg['message_type'] ?? 'image'] ); $queueId = $db->lastInsertId(); } // Ejecutar descarga inmediata usando MediaService $result = ['success' => false, 'status' => 'queued']; try { require_once '../classes/MediaService.php'; $mediaService = new MediaService(); $subdir = date('Y/m'); $localPath = $mediaService->fetchAndStoreFromGraph($mediaId, $subdir); if ($localPath) { // Actualizar el mensaje con el archivo local $db->query( "UPDATE conversations SET local_file = ?, updated_at = NOW() WHERE id = ?", [$localPath, $messageId] ); // Marcar como completado en la cola $db->query( "UPDATE media_queue SET status = 'completed', result = ?, updated_at = NOW() WHERE id = ?", ['OK: ' . $localPath, $queueId] ); $result = ['success' => true, 'status' => 'downloaded', 'local_file' => $localPath]; } else { // Falló la descarga pero quedó en cola para el worker $db->query( "UPDATE media_queue SET status = 'failed', attempts = attempts + 1, updated_at = NOW() WHERE id = ?", [$queueId] ); $result = ['success' => false, 'status' => 'failed', 'message' => 'No se pudo descargar ahora. Quedó en cola para reintento automático.']; } } catch (Exception $e) { error_log('[force_download_media] Error al descargar: ' . $e->getMessage()); $result = ['success' => false, 'status' => 'failed', 'message' => 'Error: ' . $e->getMessage()]; } echo json_encode($result); } catch (Exception $e) { error_log('[force_download_media] Exception: ' . $e->getMessage()); http_response_code(500); echo json_encode(['success' => false, 'error' => $e->getMessage()]); }