import 'package:firebase_auth/firebase_auth.dart' as firebase_auth;
import 'package:cloud_firestore/cloud_firestore.dart';
import '../models/user.dart';
import '../services/auth_service.dart';

class AuthRepository {
  final AuthService _authService;
  final FirebaseFirestore _firestore;

  AuthRepository({
    AuthService? authService,
    FirebaseFirestore? firestore,
  })  : _authService = authService ?? AuthService(),
        _firestore = firestore ?? FirebaseFirestore.instance;

  // Vérifier l'état de connexion actuel
  Stream<firebase_auth.User?> get authStateChanges =>
      _authService.authStateChanges;

  firebase_auth.User? get currentUser => _authService.currentUser;

  // Connexion avec email/mot de passe
  Future<User?> signInWithEmailAndPassword({
    required String email,
    required String password,
  }) async {
    try {
      final firebaseUser = await _authService.signInWithEmailAndPassword(
        email: email,
        password: password,
      );
      return await getUserFromFirestore(firebaseUser.user!.uid);
    } catch (e) {
      throw Exception('Erreur de connexion: $e');
    }
  }

  // Inscription avec email/mot de passe
  Future<User?> signUpWithEmailAndPassword({
    required String email,
    required String password,
    required String nom,
    required String prenom,
  }) async {
    try {
      final firebaseUser = await _authService.signUpWithEmailAndPassword(
        email: email,
        password: password,
      );

      // Créer le document utilisateur dans Firestore
      final user = User(
        id: firebaseUser.user!.uid,
        email: email,
        nom: nom,
        prenom: prenom,
      );

      await _firestore.collection('users').doc(user.id).set(user.toMap());
      return user;
      
    } catch (e) {
      throw Exception('Erreur d\'inscription: $e');
    }
  }

  // Connexion avec Google
  Future<User?> signInWithGoogle() async {
    try {
      final firebaseUser = await _authService.signInWithGoogle();

      if (firebaseUser.user != null) {
        // Vérifier si l'utilisateur existe déjà
        final existingUser = await getUserFromFirestore(firebaseUser.user!.uid);
        
        if (existingUser != null) {
          return existingUser;
        }

        // Créer un nouvel utilisateur
        final user = User(
          id: firebaseUser.user!.uid,
          email: firebaseUser.user!.email ?? '',
          nom: '',
          prenom: firebaseUser.user!.displayName ?? 'Utilisateur',
        );

        await _firestore.collection('users').doc(user.id).set(user.toMap());
        return user;
      }
      return null;
    } catch (e) {
      throw Exception('Erreur de connexion Google: $e');
    }
  }

  // Connexion avec Apple
  Future<User?> signInWithApple() async {
    try {
      final firebaseUser = await _authService.signInWithApple();

      if (firebaseUser?.user != null) {
        final existingUser = await getUserFromFirestore(firebaseUser!.user!.uid);
        
        if (existingUser != null) {
          return existingUser;
        }

        final user = User(
          id: firebaseUser.user!.uid,
          email: firebaseUser.user!.email ?? '',
          nom: '',
          prenom: firebaseUser.user!.displayName ?? 'Utilisateur',
        );

        await _firestore.collection('users').doc(user.id).set(user.toMap());
        return user;
      }
      return null;
    } catch (e) {
      throw Exception('Erreur de connexion Apple: $e');
    }
  }

  // Déconnexion
  Future<void> signOut() async {
    await _authService.signOut();
  }

  // Réinitialisation du mot de passe
  Future<void> resetPassword(String email) async {
    await _authService.resetPassword(email);
  }

  // Récupérer les données utilisateur depuis Firestore
  Future<User?> getUserFromFirestore(String uid) async {
    try {
      final doc = await _firestore.collection('users').doc(uid).get();
      if (doc.exists) {
        final data = doc.data() as Map<String, dynamic>;
        return User.fromMap({...data, 'id': uid});
      }
      return null;
    } catch (e) {
      return null;
    }
  }
}