import 'dart:io' show Platform; import 'package:flutter/foundation.dart' show kIsWeb, kDebugMode; import 'package:firebase_auth/firebase_auth.dart'; import 'package:google_sign_in_all_platforms/google_sign_in_all_platforms.dart'; import '../../core/constants/google_oauth.dart'; import '../../core/services/shop_context.dart'; /// يُرمى هذا الاستثناء عندما يكون المستخدم الحالي Anonymous ويحاول ربط حساب Google /// لكن بيانات Google بالفعل مرتبطة بـ uid آخر. class GoogleAccountAlreadyLinkedException implements Exception { final AuthCredential credential; final FirebaseAuthException original; const GoogleAccountAlreadyLinkedException({ required this.credential, required this.original, }); @override String toString() => 'GoogleAccountAlreadyLinkedException(code=${original.code}, message=${original.message})'; } class GoogleAuthService { final FirebaseAuth _auth = FirebaseAuth.instance; static bool get _isDesktop => !kIsWeb && (Platform.isWindows || Platform.isLinux || Platform.isMacOS); // ✅ حافظ على instance واحدة بدل إنشاء GoogleSignIn كل مرة late final GoogleSignIn _googleSignIn = GoogleSignIn( params: GoogleSignInParams( clientId: _isDesktop ? kGoogleDesktopClientId : null, clientSecret: _isDesktop ? kGoogleDesktopClientSecret : null, scopes: const ['openid', 'email', 'profile'], redirectPort: 8000, ), ); Future signInWithGoogle() async { try { // ✅ مهم جدًا: امسح أي جلسة Google معلّقة قبل محاولة الدخول // ده بيحل حالة "لازم أقفل وأفتح التطبيق" await _googleSignIn.signOut(); await _googleSignIn.disconnect(); final creds = await _googleSignIn.signInOnline(); if (creds == null) { throw Exception('Sign-in cancelled'); } final credential = GoogleAuthProvider.credential( accessToken: creds.accessToken, idToken: creds.idToken, ); final current = _auth.currentUser; // ✅ لو المستخدم الحالي Anonymous: نحاول نربط نفس الـ uid بحساب Google if (current != null && current.isAnonymous) { try { return await current.linkWithCredential(credential); } on FirebaseAuthException catch (e) { // ✅ الحساب مرتبط بـ uid آخر -> نطلب تأكيد من الواجهة if (e.code == 'credential-already-in-use' || e.code == 'email-already-in-use' || e.code == 'account-exists-with-different-credential') { throw GoogleAccountAlreadyLinkedException( credential: credential, original: e, ); } rethrow; } } // تسجيل دخول طبيعي return await _auth.signInWithCredential(credential); } catch (e, st) { // ✅ بدل swallow: اطبع الخطأ في debug عشان نعرف السبب لو تكرر if (kDebugMode) { // ignore: avoid_print print('Google sign-in failed: $e'); // ignore: avoid_print print(st); } rethrow; } } Future signOut() async { // ✅ لازم تسجيل خروج من Firebase ومن Google كمان await _auth.signOut(); await _googleSignIn.signOut(); await _googleSignIn.disconnect(); await ShopContext.instance.clearContext(); } /// ✅ لو محتاج ترجع لوضع التجربة (Anonymous) بعد تسجيل الخروج /// استدعِ الدالة دي من الواجهة بعد signOut() أو عند بداية التطبيق. Future ensureAnonymous() async { if (_auth.currentUser == null) { await _auth.signInAnonymously(); await ShopContext.instance.load(); } } }