import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:firebase_auth/firebase_auth.dart';

class GoogleSignInWrapper {
  static GoogleSignInWrapper? _instance;
  static GoogleSignInWrapper get instance =>
      _instance ??= GoogleSignInWrapper._internal();

  GoogleSignInWrapper._internal();

  GoogleSignIn? _googleSignIn;
  bool _isInitialized = false;

  // Initialize Google Sign-In with crash protection
  Future<bool> initialize() async {
    if (_isInitialized) return true;

    try {
      debugPrint('🔧 Initializing Google Sign-In wrapper...');

      _googleSignIn = GoogleSignIn(scopes: ['email', 'profile']);

      _isInitialized = true;
      debugPrint('✅ Google Sign-In wrapper initialized successfully');
      return true;
    } catch (e) {
      debugPrint('❌ Google Sign-In wrapper initialization failed: $e');
      _googleSignIn = null;
      _isInitialized = false;
      return false;
    }
  }

  // Safe sign-in method with comprehensive error handling
  Future<UserCredential?> signIn() async {
    try {
      debugPrint('🚀 Starting safe Google Sign-In...');

      // Ensure initialization
      if (!_isInitialized || _googleSignIn == null) {
        debugPrint(
          '⚠️ Google Sign-In not initialized, attempting to initialize...',
        );
        bool initSuccess = await initialize();
        if (!initSuccess) {
          throw Exception('Failed to initialize Google Sign-In');
        }
      }

      // Check if already signed in and clean up
      try {
        if (await _googleSignIn!.isSignedIn()) {
          debugPrint('🔄 User already signed in, signing out first...');
          await _googleSignIn!.signOut();
          await Future.delayed(
            const Duration(milliseconds: 500),
          ); // Give time for cleanup
        }
      } catch (e) {
        debugPrint('⚠️ Error during pre-cleanup: $e');
        // Continue anyway
      }

      // Attempt sign-in with timeout
      debugPrint('📱 Showing Google Sign-In dialog...');
      GoogleSignInAccount? googleUser;

      try {
        googleUser = await _googleSignIn!.signIn().timeout(
          const Duration(seconds: 60),
          onTimeout: () {
            debugPrint('⏰ Google Sign-In dialog timeout');
            return null;
          },
        );
      } on PlatformException catch (e) {
        debugPrint(
          '❌ Platform exception during sign-in: ${e.code} - ${e.message}',
        );

        if (e.code == 'sign_in_canceled') {
          debugPrint('👤 User canceled sign-in');
          return null;
        }

        throw Exception('Google Sign-In failed: ${e.message}');
      }

      if (googleUser == null) {
        debugPrint('👤 User canceled or sign-in failed');
        return null;
      }

      debugPrint('✅ Google account selected: ${googleUser.email}');

      // Get authentication details
      debugPrint('🔑 Getting authentication tokens...');
      GoogleSignInAuthentication googleAuth;

      try {
        googleAuth = await googleUser.authentication;
      } catch (e) {
        debugPrint('❌ Failed to get authentication tokens: $e');
        throw Exception('Failed to get authentication tokens');
      }

      // Validate tokens
      if (googleAuth.accessToken == null || googleAuth.idToken == null) {
        debugPrint('❌ Missing authentication tokens');
        throw Exception('Authentication tokens are missing');
      }

      debugPrint('✅ Authentication tokens obtained');

      // Create Firebase credential
      debugPrint('🔐 Creating Firebase credential...');
      AuthCredential credential;

      try {
        credential = GoogleAuthProvider.credential(
          accessToken: googleAuth.accessToken,
          idToken: googleAuth.idToken,
        );
      } catch (e) {
        debugPrint('❌ Failed to create Firebase credential: $e');
        throw Exception('Failed to create Firebase credential');
      }

      // Sign in to Firebase
      debugPrint('🔥 Signing in to Firebase...');
      UserCredential userCredential;

      try {
        userCredential = await FirebaseAuth.instance.signInWithCredential(
          credential,
        );
      } catch (e) {
        debugPrint('❌ Firebase sign-in failed: $e');
        throw Exception('Firebase sign-in failed: $e');
      }

      debugPrint('✅ Successfully signed in: ${userCredential.user?.email}');
      return userCredential;
    } catch (e) {
      debugPrint('❌ Google Sign-In error: $e');

      // Cleanup on error
      try {
        await _googleSignIn?.signOut();
      } catch (cleanupError) {
        debugPrint('⚠️ Cleanup error: $cleanupError');
      }

      rethrow;
    }
  }

  /// Get Google account info WITHOUT signing in to Firebase.
  /// Returns [GoogleSignInAccount] with email and name,
  /// but does NOT create a Firebase Auth entry.
  Future<GoogleSignInAccount?> getGoogleAccount() async {
    try {
      debugPrint('🔍 Getting Google account info (no Firebase sign-in)...');

      if (!_isInitialized || _googleSignIn == null) {
        bool initSuccess = await initialize();
        if (!initSuccess) {
          throw Exception('Failed to initialize Google Sign-In');
        }
      }

      // Clean up previous session
      try {
        if (await _googleSignIn!.isSignedIn()) {
          await _googleSignIn!.signOut();
          await Future.delayed(const Duration(milliseconds: 300));
        }
      } catch (e) {
        debugPrint('⚠️ Pre-cleanup error: $e');
      }

      final googleUser = await _googleSignIn!.signIn().timeout(
        const Duration(seconds: 60),
        onTimeout: () => null,
      );

      if (googleUser == null) {
        debugPrint('👤 User canceled Google account selection');
        return null;
      }

      debugPrint(
        '✅ Google account obtained: ${googleUser.email} (NO Firebase auth yet)',
      );
      return googleUser;
    } catch (e) {
      debugPrint('❌ getGoogleAccount error: $e');
      rethrow;
    }
  }

  /// Sign in to Firebase using a previously obtained [GoogleSignInAccount].
  /// Call this AFTER email verification (OTP) is complete.
  Future<UserCredential?> signInToFirebase(
    GoogleSignInAccount googleUser,
  ) async {
    try {
      debugPrint('🔥 Now signing in to Firebase with ${googleUser.email}...');

      final googleAuth = await googleUser.authentication;

      if (googleAuth.accessToken == null || googleAuth.idToken == null) {
        throw Exception('Authentication tokens are missing');
      }

      final credential = GoogleAuthProvider.credential(
        accessToken: googleAuth.accessToken,
        idToken: googleAuth.idToken,
      );

      final userCredential = await FirebaseAuth.instance.signInWithCredential(
        credential,
      );
      debugPrint('✅ Firebase sign-in complete: ${userCredential.user?.email}');
      return userCredential;
    } catch (e) {
      debugPrint('❌ signInToFirebase error: $e');
      rethrow;
    }
  }

  // Safe sign-out
  Future<void> signOut() async {
    try {
      debugPrint('🚪 Signing out from Google...');

      if (_googleSignIn != null) {
        await _googleSignIn!.signOut();
      }

      await FirebaseAuth.instance.signOut();
      debugPrint('✅ Successfully signed out');
    } catch (e) {
      debugPrint('❌ Sign-out error: $e');
      // Don't rethrow sign-out errors
    }
  }

  // Check if Google Sign-In is available
  Future<bool> isAvailable() async {
    try {
      if (!_isInitialized || _googleSignIn == null) {
        return await initialize();
      }
      return true;
    } catch (e) {
      debugPrint('❌ Google Sign-In availability check failed: $e');
      return false;
    }
  }

  // Get current signed-in user
  GoogleSignInAccount? get currentUser {
    try {
      return _googleSignIn?.currentUser;
    } catch (e) {
      debugPrint('❌ Error getting current user: $e');
      return null;
    }
  }

  // Check if user is signed in
  Future<bool> isSignedIn() async {
    try {
      if (_googleSignIn == null) return false;
      return await _googleSignIn!.isSignedIn();
    } catch (e) {
      debugPrint('❌ Error checking sign-in status: $e');
      return false;
    }
  }
}
