import 'package:dartz/dartz.dart'; import 'package:injectable/injectable.dart'; import '../../core/errors/failures.dart'; import '../../core/errors/exceptions.dart'; import '../../domain/repositories/user_repository.dart'; import '../../models/user_model.dart'; import '../datasources/remote/user_remote_datasource.dart'; import '../models/common/paginated_response.dart'; import '../models/user/user_dto.dart'; /// 사용자 관리 Repository 구현체 (서버 API v0.2.1 대응) /// Clean Architecture Data Layer - Repository 구현 /// 도메인 레이어와 데이터 소스 사이의 변환 및 에러 처리 담당 @Injectable(as: UserRepository) class UserRepositoryImpl implements UserRepository { final UserRemoteDataSource _remoteDataSource; UserRepositoryImpl(this._remoteDataSource); /// 사용자 목록 조회 (페이지네이션 지원) @override Future>> getUsers({ int? page, int? perPage, UserRole? role, bool? isActive, }) async { try { final result = await _remoteDataSource.getUsers( page: page ?? 1, perPage: perPage ?? 20, isActive: isActive, role: role?.name, // UserRole enum을 문자열로 변환 ); // UserListDto를 PaginatedResponse로 변환 final users = result.toDomainModels(); final paginatedResult = PaginatedResponse( items: users, page: result.page, size: result.perPage, totalElements: result.total, totalPages: result.totalPages, first: result.first, last: result.last, ); return Right(paginatedResult); } on ApiException catch (e) { return Left(_mapApiExceptionToFailure(e)); } catch (e) { return Left(ServerFailure( message: '사용자 목록 조회 중 오류가 발생했습니다: ${e.toString()}', )); } } /// 단일 사용자 조회 @override Future> getUserById(int id) async { try { final dto = await _remoteDataSource.getUser(id); final user = dto.toDomainModel(); return Right(user); } on ApiException catch (e) { return Left(_mapApiExceptionToFailure(e, resourceId: id.toString())); } catch (e) { return Left(ServerFailure( message: '사용자 정보 조회 중 오류가 발생했습니다: ${e.toString()}', )); } } /// 사용자 계정 생성 @override Future> createUser({ required String username, required String email, required String password, required String name, String? phone, required UserRole role, }) async { try { final request = CreateUserRequest( username: username, email: email, password: password, name: name, phone: phone, role: role.name, ); final dto = await _remoteDataSource.createUser(request); final user = dto.toDomainModel(); return Right(user); } on ApiException catch (e) { return Left(_mapApiExceptionToFailure(e)); } catch (e) { return Left(ServerFailure( message: '사용자 생성 중 오류가 발생했습니다: ${e.toString()}', )); } } /// 사용자 정보 수정 @override Future> updateUser(int id, User user, {String? newPassword}) async { try { final request = UpdateUserRequest.fromDomain(user, newPassword: newPassword); final dto = await _remoteDataSource.updateUser(id, request); final updatedUser = dto.toDomainModel(); return Right(updatedUser); } on ApiException catch (e) { return Left(_mapApiExceptionToFailure(e, resourceId: id.toString())); } catch (e) { return Left(ServerFailure( message: '사용자 정보 수정 중 오류가 발생했습니다: ${e.toString()}', )); } } /// 사용자 소프트 삭제 @override Future> deleteUser(int id) async { try { await _remoteDataSource.deleteUser(id); return const Right(null); } on ApiException catch (e) { return Left(_mapApiExceptionToFailure(e, resourceId: id.toString())); } catch (e) { return Left(ServerFailure( message: '사용자 삭제 중 오류가 발생했습니다: ${e.toString()}', )); } } /// 사용자명 사용 가능 여부 확인 @override Future> checkUsernameAvailability(String username) async { try { final response = await _remoteDataSource.checkUsernameAvailability(username); return Right(response.available); } on ApiException catch (e) { return Left(_mapApiExceptionToFailure(e)); } catch (e) { return Left(ServerFailure( message: '사용자명 중복 확인 중 오류가 발생했습니다: ${e.toString()}', )); } } /// ApiException을 적절한 Failure로 매핑하는 헬퍼 메서드 Failure _mapApiExceptionToFailure(ApiException exception, {String? resourceId}) { final statusCode = exception.statusCode; final message = exception.message; if (statusCode == 404) { return NotFoundFailure( message: '요청한 사용자를 찾을 수 없습니다.', resourceType: 'User', resourceId: resourceId, ); } else if (statusCode == 400) { if (message.contains('duplicate') || message.contains('중복')) { return DuplicateFailure( message: '이미 사용 중인 사용자명 또는 이메일입니다.', field: 'username', value: '', ); } else { return ValidationFailure(message: message); } } else if (statusCode == 401) { return AuthenticationFailure(message: '인증이 필요합니다.'); } else if (statusCode == 403) { return AuthorizationFailure(message: '권한이 없습니다.'); } else { return ServerFailure(message: message); } } }