import 'dart:async';

import 'package:riverpod_annotation/riverpod_annotation.dart';

import '../../../core/api/api_client.dart';
import '../domain/app_user.dart';
import '../infrastructure/auth_repository.dart';

part 'auth_notifier.g.dart';

@Riverpod(keepAlive: true)
class AuthNotifier extends _$AuthNotifier {
  @override
  Future<AppUser?> build() async {
    final repo = ref.watch(authRepositoryProvider);

    final completer = Completer<AppUser?>();
    final sub = repo.authStateChanges().listen(
      (user) {
        if (!completer.isCompleted) {
          completer.complete(user);
        } else {
          state = AsyncData(user);
        }
      },
      onError: (Object error, StackTrace stack) {
        if (!completer.isCompleted) {
          completer.completeError(error, stack);
        } else {
          state = AsyncError(error, stack);
        }
      },
    );

    ref.onDispose(sub.cancel);
    return completer.future;
  }

  Future<void> signIn({
    required String email,
    required String password,
  }) async {
    final repo = ref.read(authRepositoryProvider);
    state = const AsyncLoading();
    state = await AsyncValue.guard(
      () => repo.signInWithEmail(email: email, password: password),
    );
  }

  Future<void> register({
    required String email,
    required String password,
    required String displayName,
  }) async {
    final repo = ref.read(authRepositoryProvider);
    state = const AsyncLoading();
    state = await AsyncValue.guard(
      () => repo.registerWithEmail(
        email: email,
        password: password,
        displayName: displayName,
      ),
    );
  }

  Future<void> signOut() async {
    final repo = ref.read(authRepositoryProvider);
    state = const AsyncLoading();
    state = await AsyncValue.guard(() async {
      await repo.signOut();
      return null;
    });
  }
}

/// Maps an [ApiException] or generic error to a friendly message.
String authErrorMessage(Object error) {
  if (error is ApiException) {
    final msg = error.message.toLowerCase();
    if (msg.contains('email already')) return 'An account already exists for that email.';
    if (msg.contains('invalid email')) return 'That email address looks invalid.';
    if (msg.contains('password')) return 'Password must be at least 6 characters.';
    if (msg.contains('invalid email or password')) return 'Incorrect email or password.';
    return error.message;
  }
  return 'Something went wrong. Please try again.';
}
