/// Provider: User Info Provider
///
/// Manages the state of user information using Riverpod.
/// Fetches data from API and provides it to the UI.
library;

import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:worker/core/network/dio_client.dart';
import 'package:worker/features/account/data/datasources/user_info_remote_datasource.dart';
import 'package:worker/features/account/data/repositories/user_info_repository_impl.dart';
import 'package:worker/features/account/domain/entities/user_info.dart'
    as domain;
import 'package:worker/features/account/domain/repositories/user_info_repository.dart';
import 'package:worker/features/account/domain/usecases/get_user_info.dart';

part 'user_info_provider.g.dart';

// ============================================================================
// DATA SOURCE PROVIDERS
// ============================================================================

/// User Info Remote Data Source Provider
@riverpod
Future<UserInfoRemoteDataSource> userInfoRemoteDataSource(Ref ref) async {
  final dioClient = await ref.watch(dioClientProvider.future);
  return UserInfoRemoteDataSource(dioClient);
}

// ============================================================================
// REPOSITORY PROVIDERS
// ============================================================================

/// User Info Repository Provider
@riverpod
Future<UserInfoRepository> userInfoRepository(Ref ref) async {
  final remoteDataSource = await ref.watch(
    userInfoRemoteDataSourceProvider.future,
  );
  return UserInfoRepositoryImpl(remoteDataSource: remoteDataSource);
}

// ============================================================================
// USE CASE PROVIDERS
// ============================================================================

/// Get User Info Use Case Provider
@riverpod
Future<GetUserInfo> getUserInfoUseCase(Ref ref) async {
  final repository = await ref.watch(userInfoRepositoryProvider.future);
  return GetUserInfo(repository);
}

// ============================================================================
// STATE PROVIDERS
// ============================================================================

/// User Info Provider
///
/// Fetches and manages user information state.
/// Automatically loads user info on initialization.
/// Provides refresh functionality for manual updates.
///
/// Usage:
/// ```dart
/// // In a widget
/// final userInfoAsync = ref.watch(userInfoProvider);
///
/// userInfoAsync.when(
///   data: (userInfo) => Text(userInfo.fullName),
///   loading: () => const CustomLoadingIndicator(),
///   error: (error, stack) => ErrorWidget(error),
/// );
///
/// // To refresh
/// ref.read(userInfoProvider.notifier).refresh();
/// ```
@riverpod
class UserInfo extends _$UserInfo {
  @override
  Future<domain.UserInfo> build() async {
    // Fetch user info on initialization
    final useCase = await ref.watch(getUserInfoUseCaseProvider.future);
    return await useCase();
  }

  /// Refresh user information
  ///
  /// Forces a fresh fetch from the API.
  /// Updates the state with new data.
  ///
  /// Usage:
  /// ```dart
  /// await ref.read(userInfoProvider.notifier).refresh();
  /// ```
  Future<void> refresh() async {
    // Set loading state
    state = const AsyncValue.loading();

    // Fetch fresh data
    state = await AsyncValue.guard(() async {
      final useCase = await ref.read(getUserInfoUseCaseProvider.future);
      return await useCase.refresh();
    });
  }

  /// Update user information
  ///
  /// Sends updated user data to the API and refreshes the state.
  ///
  /// [data] should contain:
  /// - full_name: String
  /// - date_of_birth: String (YYYY-MM-DD)
  /// - gender: String
  /// - company_name: String?
  /// - tax_code: String?
  /// - avatar_base64: String? (base64 encoded)
  /// - id_card_front_base64: String? (base64 encoded)
  /// - id_card_back_base64: String? (base64 encoded)
  /// - certificates_base64: List<String> (base64 encoded)
  ///
  /// Usage:
  /// ```dart
  /// await ref.read(userInfoProvider.notifier).updateUserInfo(updateData);
  /// ```
  Future<void> updateUserInfo(Map<String, dynamic> data) async {
    // Set loading state
    state = const AsyncValue.loading();

    // Update via repository and fetch fresh data
    state = await AsyncValue.guard(() async {
      final repository = await ref.read(userInfoRepositoryProvider.future);
      return await repository.updateUserInfo(data);
    });
  }

  /// Update user info locally
  ///
  /// Updates the cached state without fetching from API.
  /// Useful after local profile updates.
  ///
  /// Usage:
  /// ```dart
  /// ref.read(userInfoProvider.notifier).updateLocal(updatedUserInfo);
  /// ```
  void updateLocal(domain.UserInfo updatedInfo) {
    state = AsyncValue.data(updatedInfo);
  }

  /// Clear user info
  ///
  /// Resets the state to loading.
  /// Useful on logout or session expiry.
  void clear() {
    state = const AsyncValue.loading();
  }
}

// ============================================================================
// COMPUTED PROVIDERS
// ============================================================================

/// User Display Name Provider
///
/// Provides the user's display name (full name).
/// Returns null if user info is not loaded.
@riverpod
String? userDisplayName(Ref ref) {
  final userInfoAsync = ref.watch(userInfoProvider);
  return userInfoAsync.value?.fullName;
}

/// User Loyalty Tier Provider
///
/// Provides the user's current loyalty tier.
/// Returns null if user info is not loaded.
@riverpod
String? userLoyaltyTier(Ref ref) {
  final userInfoAsync = ref.watch(userInfoProvider);
  return userInfoAsync.value?.tierDisplayName;
}

/// User Total Points Provider
///
/// Provides the user's total loyalty points.
/// Returns 0 if user info is not loaded.
@riverpod
int userTotalPoints(Ref ref) {
  final userInfoAsync = ref.watch(userInfoProvider);
  return userInfoAsync.value?.totalPoints ?? 0;
}

/// User Available Points Provider
///
/// Provides the user's available points for redemption.
/// Returns 0 if user info is not loaded.
@riverpod
int userAvailablePoints(Ref ref) {
  final userInfoAsync = ref.watch(userInfoProvider);
  return userInfoAsync.value?.availablePoints ?? 0;
}

/// User Avatar URL Provider
///
/// Provides the user's avatar URL.
/// Returns null if user info is not loaded or no avatar set.
@riverpod
String? userAvatarUrl(Ref ref) {
  final userInfoAsync = ref.watch(userInfoProvider);
  return userInfoAsync.value?.avatarUrl;
}

/// User Has Company Info Provider
///
/// Checks if the user has company information.
/// Returns false if user info is not loaded.
@riverpod
bool userHasCompanyInfo(Ref ref) {
  final userInfoAsync = ref.watch(userInfoProvider);
  return userInfoAsync.value?.hasCompanyInfo ?? false;
}

/// User Is Active Provider
///
/// Checks if the user's account is active.
/// Returns false if user info is not loaded.
@riverpod
bool userIsActive(Ref ref) {
  final userInfoAsync = ref.watch(userInfoProvider);
  return userInfoAsync.value?.isActive ?? false;
}
