import 'dart:async';

import 'package:flutter/foundation.dart';

import '../../../../core/errors/failures.dart';
import '../../../../core/logging/app_logger.dart';
import '../../domain/entities/user_entity.dart';
import '../../domain/repositories/auth_repository.dart';

enum AuthState {
  initial,
  loading,
  authenticated,
  unauthenticated,
}

class AuthViewModel extends ChangeNotifier {
  final AuthRepository repository;
  final AppLogger logger;

  AuthState _state = AuthState.initial;
  UserEntity? _user;
  String? _error;
  StreamSubscription<bool>? _authStateSubscription;

  AuthViewModel({
    required this.repository,
    required this.logger,
  }) {
    _init();
  }

  AuthState get state => _state;
  UserEntity? get user => _user;
  String? get error => _error;
  bool get isAuthenticated => _state == AuthState.authenticated;
  bool get isLoading => _state == AuthState.loading;

  Future<void> _init() async {
    _authStateSubscription = repository.authStateChanges.listen((isAuth) {
      if (!isAuth && _state == AuthState.authenticated) {
        _state = AuthState.unauthenticated;
        _user = null;
        notifyListeners();
      }
    });

    await checkAuthStatus();
  }

  Future<void> checkAuthStatus() async {
    final isAuth = await repository.isAuthenticated();
    if (isAuth) {
      final result = await repository.getCurrentUser();
      result.when(
        success: (user) {
          _user = user;
          _state = AuthState.authenticated;
        },
        error: (_) {
          _state = AuthState.unauthenticated;
        },
      );
    } else {
      _state = AuthState.unauthenticated;
    }
    notifyListeners();
  }

  Future<bool> register({
    required String email,
    required String password,
    required String name,
  }) async {
    _state = AuthState.loading;
    _error = null;
    notifyListeners();

    final result = await repository.register(
      email: email,
      password: password,
      name: name,
    );

    return result.when(
      success: (user) {
        _state = AuthState.unauthenticated;
        notifyListeners();
        return true;
      },
      error: (failure) {
        _error = _getErrorMessage(failure);
        _state = AuthState.unauthenticated;
        notifyListeners();
        return false;
      },
    );
  }

  Future<bool> login({
    required String email,
    required String password,
  }) async {
    _state = AuthState.loading;
    _error = null;
    notifyListeners();

    final result = await repository.login(
      email: email,
      password: password,
    );

    return result.when(
      success: (user) {
        _user = user;
        _state = AuthState.authenticated;
        notifyListeners();
        return true;
      },
      error: (failure) {
        _error = _getErrorMessage(failure);
        _state = AuthState.unauthenticated;
        notifyListeners();
        return false;
      },
    );
  }

  Future<void> logout() async {
    _state = AuthState.loading;
    notifyListeners();

    await repository.logout();
    _user = null;
    _state = AuthState.unauthenticated;
    notifyListeners();
  }

  void clearError() {
    _error = null;
    notifyListeners();
  }

  String _getErrorMessage(Failure failure) {
    if (failure is AuthFailure) {
      return failure.message;
    } else if (failure is NetworkFailure) {
      return 'No internet connection';
    } else if (failure is ServerFailure) {
      return 'Server error. Please try again.';
    }
    return 'An unexpected error occurred';
  }

  @override
  void dispose() {
    _authStateSubscription?.cancel();
    super.dispose();
  }
}
