import 'package:drift/drift.dart'; import 'package:drift_postgres/drift_postgres.dart'; import 'package:injectable/injectable.dart'; import 'package:mnemo_cards_backend/database/database.dart'; import 'package:mnemo_cards_backend/packs/card_pack_drift_extension.dart'; import 'package:mnemo_cards_common_backend/mnemo_cards_common_backend.dart'; import 'user_drift_extension.dart'; /// Repository для работы с пользователями /// Работает с доменными моделями (UserModel), использует DAO для доступа к БД @lazySingleton class UserRepository { final AppDatabase _db; UserRepository(this._db); /// Получить пользователя по ID /// [includePacks] - загружать ли связанные паки пользователя Future getUserById( String id, { bool includePacks = false, }) async { final user = await _db.userDao.getUserById(id); if (user == null) return null; if (includePacks) { final packs = await _db.userDao.getUserPacks(id); return await user.toUserModel(packs); } return await user.toUserModel(); } /// Получить пользователя по email Future getUserByEmail(String email) async { final user = await _db.userDao.getUserByEmail(email); if (user == null) return null; return await user.toUserModel(); } /// Получить пользователя по externalUserId Future getUserByExternalId(String externalId) async { final user = await _db.userDao.getUserByExternalId(externalId); if (user == null) return null; return await user.toUserModel(); } /// Получить пользователя с UserData Future getUserWithDataById(String id) async { final userWithData = await _db.userDao.getUserWithDataById(id); if (userWithData == null) return null; final packs = await _db.userDao.getUserPacks(id); final userModel = await userWithData.user.toUserModel(packs); // TODO: загрузить UserDataModel если нужно // userModel.userData = userWithData.userData?.toUserDataModel(); return userModel; } /// Создать пользователя Future createUser(UserModel userModel) async { final userCompanion = userModel.toUsersCompanion(); return await _db.userDao.createUser(userCompanion); } /// Создать пользователя с UserData Future createUserWithData({ required UserModel userModel, required UserDatasCompanion userData, }) async { final userCompanion = userModel.toUsersCompanion(); return await _db.userDao.createUserWithData( user: userCompanion, userData: userData, ); } /// Обновить пользователя Future updateUser(UserModel userModel) async { if (userModel.id == null) { throw ArgumentError('User ID is required'); } await _db.userDao.updateUserPartial( userModel.toUsersCompanion().copyWith( updatedAt: Value(PgDateTime(DateTime.now())), ), ); } /// Обновить пользователя частично Future updateUserPartial(UsersCompanion updates) async { await _db.userDao.updateUserPartial(updates); } /// Удалить пользователя (soft delete) Future softDeleteUser(String userId) async { await _db.userDao.softDeleteUser(userId); } /// Получить всех пользователей (для админки) Future> getAllUsers({ int? limit, int? offset, bool includeDeleted = false, bool includePacks = false, }) async { final users = await _db.userDao.getAllUsers( limit: limit, offset: offset, includeDeleted: includeDeleted, ); if (includePacks) { final userModels = []; for (final user in users) { final packs = await _db.userDao.getUserPacks(user.id); final userModel = await user.toUserModel(packs); userModels.add(userModel); } return userModels; } return await Future.wait(users.map((u) => u.toUserModel())); } /// Подсчитать пользователей Future countUsers({bool includeDeleted = false}) async { return await _db.userDao.countUsers(includeDeleted: includeDeleted); } /// Получить паки пользователя Future> getUserPacks(String userId) async { final packs = await _db.userDao.getUserPacks(userId); return await Future.wait(packs.map((p) => p.toModel())); } /// Проверить, есть ли у пользователя доступ к паку Future hasPackAccess(String userId, String packId) async { return await _db.userDao.hasPackAccess(userId, packId); } /// Дать пользователю доступ к паку Future grantPackAccess({ required String userId, required String packId, String grantType = 'purchase', }) async { await _db.userDao.grantPackAccess( userId: userId, packId: packId, grantType: grantType, ); } /// Отозвать доступ к паку Future revokePackAccess(String userId, String packId) async { await _db.userDao.revokePackAccess(userId, packId); } /// Получить UserData пользователя Future getUserData(String userId) async { return await _db.userDao.getUserData(userId); } /// Обновить UserData частично Future updateUserDataPartial(UserDatasCompanion updates) async { await _db.userDao.updateUserDataPartial(updates); } /// Обновить время последнего визита Future updateLastOnline(String userId) async { await _db.userDao.updateLastOnline(userId); } }