import 'dart:convert'; import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; import 'package:flutter/foundation.dart'; import 'package:hoshan/core/services/api/dio_service.dart'; import 'package:hoshan/data/model/ai/ai_response_model.dart'; import 'package:hoshan/data/model/ai/send_message_model.dart'; import 'package:hoshan/data/repository/chatbot_repository.dart'; import 'package:image_picker/image_picker.dart'; part 'media_g_response_state.dart'; class MediaGResponseCubit extends Cubit { MediaGResponseCubit() : super(MediaGResponseInitial()); void request(SendMessageModel model) async { emit(MediaGResponseLoading(file: model.file, query: model.query)); try { AiResponseModel response = AiResponseModel(); await for (String message in ChatbotRepository.sendMessageTool(model)) { late Map jsonMap; try { jsonMap = jsonDecode(message); } catch (e) { if (kDebugMode) { print('Error in Parse: $e'); } } final r = AiResponseModel.fromJson(jsonMap) .copyWith(humanMessageId: model.messageId); response = response.copyWith( aiMessageId: r.aiMessageId, chatId: r.chatId, chatTitle: r.chatTitle, content: r.content, credit: r.credit, detail: r.detail, error: r.content?.startsWith('Check failed') ?? r.error, freeCredit: r.freeCredit, humanMessageId: r.humanMessageId, statusCode: r.statusCode); } // Check if this is a Suno music creation request const sunoMusicBotIds = [ 783, 871, 957, 958, 959, 960, 961, 962, 963, 964, 965 ]; if (model.botId != null && sunoMusicBotIds.contains(model.botId)) { if (kDebugMode) { print('🎵 Suno music creation detected for botId: ${model.botId}'); } // Extract content (task ID) from the response final taskId = response.content; if (taskId != null && taskId.isNotEmpty) { if (kDebugMode) { print('🎵 Retrieved content (taskId): $taskId'); print('🎵 Making request to: /api/suno/tasks/$taskId'); } try { final dioService = DioService(); String? audioUrl; int retryCount = 0; const maxRetries = 60; // Maximum 60 attempts (5 minutes with 5 second delays) const retryDelay = Duration(seconds: 5); // Poll the Suno API until audio_url is available while (audioUrl == null && retryCount < maxRetries) { if (retryCount > 0) { if (kDebugMode) { print( '⏳ Waiting for audio to be generated... (attempt ${retryCount + 1}/$maxRetries)'); } await Future.delayed(retryDelay); } // Make GET request to Suno API to get audio_url final sunoResponse = await dioService.sendRequest().get( DioService.sunoTask(taskId: taskId), ); if (kDebugMode) { print( '🎵 Suno API response (attempt ${retryCount + 1}): ${sunoResponse.data}'); } // Extract audio_url from response final responseAudioUrl = sunoResponse.data['audio_url'] as String?; final status = sunoResponse.data['status'] as String?; if (kDebugMode) { print( '📊 Status: $status, audio_url: ${responseAudioUrl ?? "null"}'); } if (responseAudioUrl != null && responseAudioUrl.isNotEmpty) { audioUrl = responseAudioUrl; if (kDebugMode) { print('✅ Retrieved audio_url: $audioUrl'); } } else { retryCount++; } } if (audioUrl != null) { // Update response content with audio_url response = response.copyWith(content: audioUrl); } else { if (kDebugMode) { print('⚠️ Audio URL not available after $maxRetries attempts'); } } } catch (e) { if (kDebugMode) { print('❌ Error fetching Suno task: $e'); } } } else { if (kDebugMode) { print('⚠️ No content (taskId) found in initial response'); } } } emit(MediaGResponseSucess( response: response, file: model.file, query: model.query, error: response.error ?? false ? 'مشکلی از طرف سرور رخ داده است' : null)); } catch (e) { if (kDebugMode) { print('Dio Error is: $e'); } emit(MediaGResponseFail()); } } }