import 'dart:convert';

import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:shared_preferences/shared_preferences.dart';

import '../domain/favorite_employee.dart';

abstract class FavoritesRepository {
  const FavoritesRepository();

  Future<List<FavoriteEmployee>> loadFavorites();

  Future<void> toggleFavorite(String employeeId);
}

class SharedPreferencesFavoritesRepository implements FavoritesRepository {
  SharedPreferencesFavoritesRepository({
    required SharedPreferencesAsync preferences,
  }) : this.withStore(SharedPreferencesFavoritesStore(preferences));

  const SharedPreferencesFavoritesRepository.withStore(this.store);

  static const _storageKey = 'tdc114plus.favoriteEmployees';

  final FavoritesKeyValueStore store;

  @override
  Future<List<FavoriteEmployee>> loadFavorites() async {
    final encoded = await store.getString(_storageKey);
    if (encoded == null || encoded.isEmpty) {
      return const [];
    }

    final decoded = jsonDecode(encoded) as List<dynamic>;
    return decoded
        .map((item) => FavoriteEmployee.fromJson(item as Map<String, dynamic>))
        .where((favorite) => favorite.employeeId.isNotEmpty)
        .toList();
  }

  @override
  Future<void> toggleFavorite(String employeeId) async {
    final normalizedId = employeeId.trim();
    if (normalizedId.isEmpty) {
      return;
    }

    final favorites = await loadFavorites();
    final nextFavorites = favorites
        .where((favorite) => favorite.employeeId != normalizedId)
        .toList();
    if (nextFavorites.length == favorites.length) {
      nextFavorites.add(
        FavoriteEmployee(employeeId: normalizedId, createdAt: DateTime.now()),
      );
    }

    await store.setString(
      _storageKey,
      jsonEncode(nextFavorites.map((favorite) => favorite.toJson()).toList()),
    );
  }
}

abstract class FavoritesKeyValueStore {
  const FavoritesKeyValueStore();

  Future<String?> getString(String key);

  Future<void> setString(String key, String value);
}

class SharedPreferencesFavoritesStore implements FavoritesKeyValueStore {
  const SharedPreferencesFavoritesStore(this._preferences);

  final SharedPreferencesAsync _preferences;

  @override
  Future<String?> getString(String key) {
    return _preferences.getString(key);
  }

  @override
  Future<void> setString(String key, String value) {
    return _preferences.setString(key, value);
  }
}

final favoritesRepositoryProvider = Provider<FavoritesRepository>((ref) {
  return SharedPreferencesFavoritesRepository(
    preferences: SharedPreferencesAsync(),
  );
});

final favoriteEmployeeIdsProvider = FutureProvider<Set<String>>((ref) async {
  final favorites = await ref
      .watch(favoritesRepositoryProvider)
      .loadFavorites();
  return favorites.map((favorite) => favorite.employeeId).toSet();
});
