import 'dart:developer'; import 'package:business_panel/core/config/api_config.dart'; import 'package:business_panel/core/services/token_storage_service.dart'; import 'package:business_panel/core/utils/logging_interceptor.dart'; import 'package:dio/dio.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'discount_event.dart'; import 'discount_state.dart'; class DiscountBloc extends Bloc { final Dio _dio = Dio(); final TokenStorageService _tokenStorage = TokenStorageService(); DiscountBloc() : super(const DiscountState()) { _dio.interceptors.add(LoggingInterceptor()); on((event, emit) async { emit(state.copyWith(isLoadingDetails: true, errorMessage: null)); try { final token = await _tokenStorage.getAccessToken(); if (token == null) { emit( state.copyWith( isLoadingDetails: false, errorMessage: "خطای احراز هویت.", ), ); return; } final response = await _dio.get( ApiConfig.getDiscountById(event.discountId), options: Options(headers: {'Authorization': 'Bearer $token'}), ); if (response.statusCode == 200 && response.data['data'] != null) { final data = response.data['data']; List> images = []; if (data['Images'] is List) { images = (data['Images'] as List) .map>( (img) => { 'id': img['ID'] as String?, 'url': img['Url'] as String?, }, ) .where((img) => img['url'] != null) .toList(); } final name = data['Name'] ?? ''; final typeId = data['Type']?['ID']; final description = data['Description'] ?? ''; final price = data['Price']?.toString() ?? '0'; final nPrice = data['NPrice']?.toString() ?? '0'; final startDate = data['StartDate'] != null ? DateTime.tryParse(data['StartDate']) : null; final endDate = data['EndDate'] != null ? DateTime.tryParse(data['EndDate']) : null; final startTime = data['StartTime']; final endTime = data['EndTime']; final radius = (data['Radius'] as num?)?.toDouble() ?? 0.0; emit( state.copyWith( isLoadingDetails: false, discountId: data['_id'], productName: name, productImages: images, discountTypeId: typeId, description: description, price: price, discountedPrice: nPrice, startDate: startDate, endDate: endDate, startTime: startTime, endTime: endTime, notificationRadius: radius, ), ); } else { emit( state.copyWith( isLoadingDetails: false, errorMessage: "تخفیف یافت نشد.", ), ); } } catch (e) { emit( state.copyWith( isLoadingDetails: false, errorMessage: 'خطا در دریافت اطلاعات.', ), ); } }); on((event, emit) { List> updatedImages = List.from(state.productImages); final newImageMap = {'id': null, 'url': event.imagePath}; if (updatedImages.length > event.index) { updatedImages[event.index] = newImageMap; } else { updatedImages.add(newImageMap); } emit(state.copyWith(productImages: updatedImages)); }); on((event, emit) { emit(state.copyWith(productName: event.name)); }); on((event, emit) { emit(state.copyWith(discountTypeId: event.typeId)); }); on((event, emit) { emit(state.copyWith(description: event.description)); }); on((event, emit) { emit(state.copyWith(startDate: event.startDate, endDate: event.endDate)); }); on((event, emit) { emit(state.copyWith(startTime: event.startTime, endTime: event.endTime)); }); on((event, emit) { emit(state.copyWith(price: event.price)); }); on((event, emit) { emit(state.copyWith(discountedPrice: event.price)); }); on((event, emit) { emit(state.copyWith(notificationRadius: event.radius)); }); on((event, emit) async { await _submitDiscountForm(emit, isEdit: false); }); on((event, emit) async { await _submitDiscountForm( emit, isEdit: true, discountId: event.discountId, ); }); on((event, emit) { emit(state.copyWith(clearErrorMessage: true)); }); } Future _submitDiscountForm( Emitter emit, { required bool isEdit, String? discountId, }) async { emit(state.copyWith(isSubmitting: true, errorMessage: null)); try { final token = await _tokenStorage.getAccessToken(); if (token == null) { emit( state.copyWith(isSubmitting: false, errorMessage: "خطای احراز هویت."), ); return; } final Map data = { 'Name': state.productName, 'Type': state.discountTypeId, 'Description': state.description, 'Price': double.tryParse(state.price), 'NPrice': double.tryParse(state.discountedPrice), 'Start': state.startDate?.toUtc().toIso8601String(), 'End': state.endDate?.toUtc().toIso8601String(), 'StartTime': state.startTime, 'EndTime': state.endTime, 'Radius': state.notificationRadius, }; List newImageFiles = []; List existingImageIds = []; for (var imageMap in state.productImages) { final id = imageMap['id']; final url = imageMap['url']; if (id != null && url != null && url.startsWith('http')) { existingImageIds.add(id); } else if (url != null && !url.startsWith('http')) { newImageFiles.add( await MultipartFile.fromFile(url, filename: url.split('/').last), ); } } if (newImageFiles.isNotEmpty) { data['Images'] = newImageFiles; } if (isEdit) { data['Picture'] = existingImageIds; } log('Submitting Discount Data: $data', name: 'DiscountBloc'); final formData = FormData.fromMap(data); final url = isEdit ? ApiConfig.editDiscount(discountId!) : ApiConfig.addDiscount; await _dio.post( url, data: formData, options: Options(headers: {'Authorization': 'Bearer $token'}), ); emit(state.copyWith(isSubmitting: false, isSuccess: true)); }on DioException catch (e) { emit( state.copyWith( isSubmitting: false, errorMessage: e.response?.data['message'] ?? 'خطای سرور.', ), ); } catch (e) { emit( state.copyWith( isSubmitting: false, errorMessage: 'خطای ناشناخته: ${e.toString()}', ), ); } } }