import 'package:bloc/bloc.dart'; import 'package:dio/dio.dart'; import 'package:equatable/equatable.dart'; import 'package:flutter/material.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:meta/meta.dart'; import 'package:proxibuy/core/config/api_config.dart'; part 'auth_event.dart'; part 'auth_state.dart'; class AuthBloc extends Bloc { late final Dio _dio; final _storage = const FlutterSecureStorage(); AuthBloc() : super(AuthUnknown()) { _dio = Dio(); _dio.interceptors.add( LogInterceptor( requestHeader: true, requestBody: true, responseBody: true, error: true, ), ); on(_onCheckAuthStatus); on(_onSendOTP); on(_onVerifyOTP); on(_onUpdateUserInfo); on(_onLogout); on(_onSendFcmToken); } Future _onCheckAuthStatus( CheckAuthStatusEvent event, Emitter emit, ) async { final token = await _storage.read(key: 'accessToken'); if (token != null && token.isNotEmpty) { emit(AuthSuccess()); } else { emit(AuthInitial()); } } Future _onSendOTP(SendOTPEvent event, Emitter emit) async { emit(AuthLoading()); try { final response = await _dio.post( ApiConfig.baseUrl + ApiConfig.sendCode, data: {'Phone': event.phoneNumber, 'Code': event.countryCode}, ); if (isClosed) return; if (response.statusCode == 200) { emit( AuthCodeSentSuccess( phone: event.phoneNumber, countryCode: event.countryCode, ), ); } else { emit(AuthFailure(response.data['message'] ?? 'خطایی رخ داد')); } } on DioException catch (e) { if (isClosed) return; emit(AuthFailure(e.response?.data['message'] ?? 'خطا در ارتباط با سرور')); } } Future _onVerifyOTP( VerifyOTPEvent event, Emitter emit, ) async { emit(AuthLoading()); try { final response = await _dio.post( ApiConfig.baseUrl + ApiConfig.verifyCode, data: { 'Phone': event.phoneNumber, 'Code': event.countryCode, 'OTP': event.otp, }, ); if (isClosed) return; if (response.statusCode == 200) { final accessToken = response.data['data']['accessToken']; final refreshToken = response.data['data']['refreshToken']; final userID = response.data['data']['ID']; await _storage.write(key: 'accessToken', value: accessToken); await _storage.write(key: 'refreshToken', value: refreshToken); await _storage.write(key: 'userID', value: userID); emit(AuthNeedsInfo()); } else { emit(AuthFailure(response.data['message'] ?? 'کد صحیح نیست')); } } on DioException catch (e) { if (isClosed) return; emit(AuthFailure(e.response?.data['message'] ?? 'خطایی در سرور رخ داد')); } } Future _onUpdateUserInfo( UpdateUserInfoEvent event, Emitter emit, ) async { debugPrint( "AuthBloc: 🔵 ایونت UpdateUserInfoEvent دریافت شد با نام: ${event.name}", ); emit(AuthLoading()); try { final token = await _storage.read(key: 'accessToken'); if (token == null) { debugPrint("AuthBloc: 🔴 خطا: توکن کاربر یافت نشد."); emit(const AuthFailure("شما وارد نشده‌اید.")); return; } debugPrint("AuthBloc: 🟡 در حال ارسال درخواست آپدیت به سرور..."); final response = await _dio.post( ApiConfig.baseUrl + ApiConfig.updateUser, data: {'Name': event.name, 'Gender': event.gender}, options: Options(headers: {'Authorization': 'Bearer $token'}), ); debugPrint( "AuthBloc: 🟠 پاسخ سرور دریافت شد. StatusCode: ${response.statusCode}", ); if (isClosed) { debugPrint("AuthBloc: 🔴 خطا: BLoC قبل از اتمام عملیات بسته شده است."); return; } if (response.statusCode == 200) { debugPrint( "AuthBloc: ✅ درخواست موفق بود. در حال emit کردن AuthSuccess...", ); emit(AuthSuccess()); } else { debugPrint( "AuthBloc: 🔴 سرور پاسخ ناموفق داد: ${response.data['message']}", ); emit(AuthFailure(response.data['message'] ?? 'خطا در ثبت اطلاعات')); } } on DioException catch (e) { debugPrint( "AuthBloc: 🔴 خطای DioException رخ داد: ${e.response?.data['message']}", ); if (isClosed) return; emit(AuthFailure(e.response?.data['message'] ?? 'خطا در ارتباط با سرور')); } } Future _onLogout(LogoutEvent event, Emitter emit) async { await _storage.deleteAll(); emit(AuthInitial()); } Future _onSendFcmToken( SendFcmTokenEvent event, Emitter emit, ) async { try { final token = await _storage.read(key: 'accessToken'); if (token == null) { emit(const AuthFailure("شما وارد نشده‌اید.")); return; } await _dio.post( ApiConfig.baseUrl + ApiConfig.updateFcmToken, data: {'Token': event.fcmToken}, options: Options(headers: {'Authorization': 'Bearer $token'}), ); print("Firebase token: ${event.fcmToken}"); } on DioException catch (e) { debugPrint("Error sending FCM token: ${e.response?.data['message']}"); } } }