import 'package:flutter/material.dart'; import 'package:dartz/dartz.dart'; import '../../../core/errors/failures.dart'; import '../../../domain/usecases/base_usecase.dart'; import '../../../domain/usecases/auth/login_usecase.dart'; import '../../../domain/usecases/auth/check_auth_status_usecase.dart'; import '../../../services/auth_service.dart'; import '../../../services/health_check_service.dart'; import '../../../di/injection_container.dart'; /// UseCase를 활용한 로그인 화면 컨트롤러 /// 비즈니스 로직을 UseCase로 분리하여 테스트 용이성과 재사용성 향상 class LoginControllerWithUseCase extends ChangeNotifier { // UseCases late final LoginUseCase _loginUseCase; late final CheckAuthStatusUseCase _checkAuthStatusUseCase; // Services final HealthCheckService _healthCheckService = HealthCheckService(); // UI Controllers final TextEditingController idController = TextEditingController(); final TextEditingController pwController = TextEditingController(); // Focus Nodes final FocusNode idFocus = FocusNode(); final FocusNode pwFocus = FocusNode(); // State bool saveId = false; bool _isLoading = false; String? _errorMessage; // Getters bool get isLoading => _isLoading; String? get errorMessage => _errorMessage; LoginControllerWithUseCase() { // UseCase 초기화 final authService = inject(); _loginUseCase = LoginUseCase(authService); _checkAuthStatusUseCase = CheckAuthStatusUseCase(authService); // 초기 인증 상태 확인 _checkInitialAuthStatus(); } /// 초기 인증 상태 확인 Future _checkInitialAuthStatus() async { final result = await _checkAuthStatusUseCase(const NoParams()); result.fold( (failure) => debugPrint('인증 상태 확인 실패: ${failure.message}'), (isAuthenticated) { if (isAuthenticated) { debugPrint('이미 로그인된 상태입니다.'); } }, ); } /// 아이디 저장 체크박스 상태 변경 void setSaveId(bool value) { saveId = value; notifyListeners(); } /// 에러 메시지 초기화 void clearError() { _errorMessage = null; notifyListeners(); } /// 로그인 처리 Future login() async { // 입력값 검증 (UI 레벨) if (idController.text.trim().isEmpty) { _errorMessage = '아이디 또는 이메일을 입력해주세요.'; notifyListeners(); return false; } if (pwController.text.isEmpty) { _errorMessage = '비밀번호를 입력해주세요.'; notifyListeners(); return false; } // 로딩 시작 _isLoading = true; _errorMessage = null; notifyListeners(); // 입력값이 이메일인지 username인지 판단 final inputValue = idController.text.trim(); final emailRegex = RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$'); final isEmail = emailRegex.hasMatch(inputValue); try { // UseCase 실행 final params = LoginParams( email: isEmail ? inputValue : '$inputValue@superport.kr', // username인 경우 임시 도메인 추가 password: pwController.text, ); debugPrint('[LoginController] 로그인 시도: ${params.email}'); final result = await _loginUseCase(params).timeout( const Duration(seconds: 10), onTimeout: () async { debugPrint('[LoginController] 로그인 요청 타임아웃'); return Left(NetworkFailure( message: '요청 시간이 초과되었습니다. 네트워크 연결을 확인해주세요.', )); }, ); return result.fold( (failure) { debugPrint('[LoginController] 로그인 실패: ${failure.message}'); // 실패 타입에 따른 메시지 처리 if (failure is ValidationFailure) { _errorMessage = failure.message; } else if (failure is AuthenticationFailure) { _errorMessage = '이메일 또는 비밀번호가 올바르지 않습니다.'; } else if (failure is NetworkFailure) { _errorMessage = '네트워크 연결을 확인해주세요.'; } else if (failure is ServerFailure) { _errorMessage = '서버 오류가 발생했습니다.\n잠시 후 다시 시도해주세요.'; } else { _errorMessage = failure.message; } _isLoading = false; notifyListeners(); return false; }, (loginResponse) { debugPrint('[LoginController] 로그인 성공'); _isLoading = false; notifyListeners(); return true; }, ); } catch (e) { debugPrint('[LoginController] 예상치 못한 에러: $e'); _errorMessage = '로그인 중 오류가 발생했습니다.'; _isLoading = false; notifyListeners(); return false; } } /// 헬스체크 실행 Future performHealthCheck() async { debugPrint('[LoginController] 헬스체크 시작'); _isLoading = true; notifyListeners(); try { final healthResult = await _healthCheckService.checkHealth(); _isLoading = false; notifyListeners(); // HealthCheckService가 Map을 반환하는 경우 적절히 변환 final isHealthy = healthResult is bool ? healthResult : (healthResult is Map && healthResult['status'] == 'healthy'); if (isHealthy == false) { _errorMessage = '서버와 연결할 수 없습니다.\n잠시 후 다시 시도해주세요.'; notifyListeners(); return false; } return true; } catch (e) { debugPrint('[LoginController] 헬스체크 실패: $e'); _errorMessage = '서버 상태 확인 중 오류가 발생했습니다.'; _isLoading = false; notifyListeners(); return false; } } @override void dispose() { idController.dispose(); pwController.dispose(); idFocus.dispose(); pwFocus.dispose(); super.dispose(); } }