import 'package:dio/dio.dart'; import 'package:injectable/injectable.dart'; import 'package:superport/core/errors/exceptions.dart'; import 'package:superport/data/datasources/remote/api_client.dart'; import 'package:superport/data/models/user/user_dto.dart'; abstract class UserRemoteDataSource { Future getUsers({ int page = 1, int perPage = 20, bool? isActive, int? companyId, String? role, bool includeInactive = false, }); Future getUser(int id); Future createUser(CreateUserRequest request); Future updateUser(int id, UpdateUserRequest request); Future deleteUser(int id); Future changeUserStatus(int id, ChangeStatusRequest request); Future changePassword(int id, ChangePasswordRequest request); Future checkDuplicateUsername(String username); Future searchUsers({ required String query, int? companyId, String? status, String? permissionLevel, int page = 1, int perPage = 20, }); } @LazySingleton(as: UserRemoteDataSource) class UserRemoteDataSourceImpl implements UserRemoteDataSource { final ApiClient _apiClient; UserRemoteDataSourceImpl(this._apiClient); /// 사용자 목록 조회 Future getUsers({ int page = 1, int perPage = 20, bool? isActive, int? companyId, String? role, bool includeInactive = false, }) async { try { final queryParams = { 'page': page, 'per_page': perPage, if (isActive != null) 'is_active': isActive, if (companyId != null) 'company_id': companyId, if (role != null) 'role': role, 'include_inactive': includeInactive, }; final response = await _apiClient.get( '/users', queryParameters: queryParams, ); if (response.data != null && response.data['success'] == true && response.data['data'] != null) { // API 응답이 배열인 경우와 객체인 경우를 모두 처리 final data = response.data['data']; if (data is List) { // 배열 응답을 UserListDto 형식으로 변환 // role이 null인 경우 기본값 설정 final users = data.map((json) { if (json['role'] == null) { json['role'] = 'member'; // 기본값 } return UserDto.fromJson(json); }).toList(); final pagination = response.data['pagination'] ?? {}; return UserListDto( users: users, total: pagination['total'] ?? users.length, page: pagination['page'] ?? page, perPage: pagination['per_page'] ?? perPage, totalPages: pagination['total_pages'] ?? 1, ); } else if (data['users'] != null) { // 이미 UserListDto 형식인 경우 return UserListDto.fromJson(data); } else { // 예상치 못한 형식인 경우 throw ApiException( message: 'Unexpected response format for user list', ); } } else { throw ApiException( message: response.data?['error']?['message'] ?? '사용자 목록을 불러오는데 실패했습니다', ); } } on DioException catch (e) { throw ApiException( message: e.response?.data['message'] ?? '사용자 목록을 불러오는데 실패했습니다', statusCode: e.response?.statusCode, ); } } /// 특정 사용자 조회 Future getUser(int id) async { try { final response = await _apiClient.get('/users/$id'); if (response.data != null && response.data['success'] == true && response.data['data'] != null) { return UserDto.fromJson(response.data['data']); } else { throw ApiException( message: response.data?['error']?['message'] ?? '사용자 정보를 불러오는데 실패했습니다', ); } } on DioException catch (e) { throw ApiException( message: e.response?.data['message'] ?? '사용자 정보를 불러오는데 실패했습니다', statusCode: e.response?.statusCode, ); } } /// 사용자 생성 Future createUser(CreateUserRequest request) async { try { final response = await _apiClient.post( '/users', data: request.toJson(), ); if (response.data != null && response.data['success'] == true && response.data['data'] != null) { return UserDto.fromJson(response.data['data']); } else { throw ApiException( message: response.data?['error']?['message'] ?? '사용자 정보를 불러오는데 실패했습니다', ); } } on DioException catch (e) { throw ApiException( message: e.response?.data['message'] ?? '사용자 생성에 실패했습니다', statusCode: e.response?.statusCode, ); } } /// 사용자 정보 수정 Future updateUser(int id, UpdateUserRequest request) async { try { final response = await _apiClient.put( '/users/$id', data: request.toJson(), ); if (response.data != null && response.data['success'] == true && response.data['data'] != null) { return UserDto.fromJson(response.data['data']); } else { throw ApiException( message: response.data?['error']?['message'] ?? '사용자 정보를 불러오는데 실패했습니다', ); } } on DioException catch (e) { throw ApiException( message: e.response?.data['message'] ?? '사용자 정보 수정에 실패했습니다', statusCode: e.response?.statusCode, ); } } /// 사용자 삭제 Future deleteUser(int id) async { try { await _apiClient.delete('/users/$id'); } on DioException catch (e) { throw ApiException( message: e.response?.data['message'] ?? '사용자 삭제에 실패했습니다', statusCode: e.response?.statusCode, ); } } /// 사용자 상태 변경 (활성/비활성) Future changeUserStatus(int id, ChangeStatusRequest request) async { try { final response = await _apiClient.patch( '/users/$id/status', data: request.toJson(), ); if (response.data != null && response.data['success'] == true && response.data['data'] != null) { return UserDto.fromJson(response.data['data']); } else { throw ApiException( message: response.data?['error']?['message'] ?? '사용자 정보를 불러오는데 실패했습니다', ); } } on DioException catch (e) { throw ApiException( message: e.response?.data['message'] ?? '사용자 상태 변경에 실패했습니다', statusCode: e.response?.statusCode, ); } } /// 비밀번호 변경 Future changePassword(int id, ChangePasswordRequest request) async { try { await _apiClient.put( '/users/$id/password', data: request.toJson(), ); } on DioException catch (e) { throw ApiException( message: e.response?.data['message'] ?? '비밀번호 변경에 실패했습니다', statusCode: e.response?.statusCode, ); } } /// 사용자명 중복 확인 Future checkDuplicateUsername(String username) async { try { final response = await _apiClient.get( '/users/check-duplicate', queryParameters: {'username': username}, ); return response.data['is_duplicate'] ?? false; } on DioException catch (e) { throw ApiException( message: e.response?.data['message'] ?? '중복 확인에 실패했습니다', statusCode: e.response?.statusCode, ); } } /// 사용자 검색 Future searchUsers({ required String query, int? companyId, String? status, String? permissionLevel, int page = 1, int perPage = 20, }) async { try { final queryParams = { 'q': query, 'page': page, 'per_page': perPage, if (companyId != null) 'company_id': companyId, if (status != null) 'status': status, if (permissionLevel != null) 'permission_level': permissionLevel, }; final response = await _apiClient.get( '/users/search', queryParameters: queryParams, ); if (response.data != null && response.data['success'] == true && response.data['data'] != null) { return UserListDto.fromJson(response.data['data']); } else { throw ApiException( message: response.data?['error']?['message'] ?? '사용자 목록을 불러오는데 실패했습니다', ); } } on DioException catch (e) { throw ApiException( message: e.response?.data['message'] ?? '사용자 검색에 실패했습니다', statusCode: e.response?.statusCode, ); } } }