import 'package:flutter/material.dart'; import 'package:dartz/dartz.dart'; import 'package:superport/core/errors/failures.dart'; import 'package:superport/data/models/auth/login_request.dart'; import 'package:superport/di/injection_container.dart'; import 'package:superport/services/auth_service.dart'; import 'package:superport/services/health_test_service.dart'; import 'package:superport/services/health_check_service.dart'; /// 로그인 화면의 상태 및 비즈니스 로직을 담당하는 ChangeNotifier 기반 컨트롤러 class LoginController extends ChangeNotifier { final AuthService _authService = inject(); final HealthCheckService _healthCheckService = HealthCheckService(); /// 아이디 입력 컨트롤러 final TextEditingController idController = TextEditingController(); /// 비밀번호 입력 컨트롤러 final TextEditingController pwController = TextEditingController(); /// 아이디 입력란 포커스 final FocusNode idFocus = FocusNode(); /// 비밀번호 입력란 포커스 final FocusNode pwFocus = FocusNode(); /// 아이디 저장 여부 bool saveId = false; /// 로딩 상태 bool _isLoading = false; bool get isLoading => _isLoading; /// 에러 메시지 String? _errorMessage; String? get errorMessage => _errorMessage; /// 아이디 저장 체크박스 상태 변경 void setSaveId(bool value) { saveId = value; notifyListeners(); } /// 로그인 처리 Future login() async { // 입력값 검증 if (idController.text.trim().isEmpty) { _errorMessage = '아이디 또는 이메일을 입력해주세요.'; notifyListeners(); return false; } if (pwController.text.isEmpty) { _errorMessage = '비밀번호를 입력해주세요.'; notifyListeners(); return false; } // 입력값이 이메일인지 username인지 판단 final inputValue = idController.text.trim(); final emailRegex = RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$'); final isEmail = emailRegex.hasMatch(inputValue); // 로딩 시작 _isLoading = true; _errorMessage = null; notifyListeners(); try { // 로그인 요청 (이메일 또는 username으로) final request = LoginRequest( email: isEmail ? inputValue : null, username: !isEmail ? inputValue : null, password: pwController.text, ); print('[LoginController] 로그인 요청 시작: ${isEmail ? 'email: ${request.email}' : 'username: ${request.username}'}'); print('[LoginController] 입력값: "$inputValue" (비밀번호 길이: ${pwController.text.length})'); print('[LoginController] 요청 데이터 JSON: ${request.toJson()}'); final result = await _authService.login(request).timeout( const Duration(seconds: 10), onTimeout: () async { print('[LoginController] 로그인 요청 타임아웃 (10초)'); return Left(NetworkFailure(message: '요청 시간이 초과되었습니다. 네트워크 연결을 확인해주세요.')); }, ); print('[LoginController] 로그인 결과 수신: ${result.isRight() ? '성공' : '실패'}'); return result.fold( (failure) { print('[LoginController] 로그인 실패: ${failure.message}'); // 더 구체적인 에러 메시지 제공 if (failure.message.contains('자격 증명') || failure.message.contains('올바르지 않습니다')) { _errorMessage = '이메일 또는 비밀번호가 올바르지 않습니다.\n비밀번호는 특수문자(!@#\$%^&*)를 포함할 수 있습니다.'; } else if (failure.message.contains('네트워크') || failure.message.contains('연결')) { _errorMessage = '네트워크 연결을 확인해주세요.\n서버와 통신할 수 없습니다.'; } else if (failure.message.contains('시간 초과') || failure.message.contains('타임아웃')) { _errorMessage = '서버 응답 시간이 초과되었습니다.\n잠시 후 다시 시도해주세요.'; } else { _errorMessage = failure.message; } _isLoading = false; notifyListeners(); return false; }, (loginResponse) async { print('[LoginController] 로그인 성공: ${loginResponse.user.email}'); // 테스트 로그인인 경우 주기적 헬스체크 시작 if (loginResponse.user.email == 'admin@superport.kr') { print('[LoginController] 테스트 로그인 감지 - 헬스체크 모니터링 시작'); _healthCheckService.startPeriodicHealthCheck(); } // Health Test 실행 try { print('[LoginController] ========== Health Test 시작 =========='); final healthTestService = HealthTestService(); final testResults = await healthTestService.checkAllEndpoints(); // 상세한 결과 출력 print('\n[LoginController] === 인증 상태 ==='); print('인증됨: ${testResults['auth']?['success']}'); print('Access Token: ${testResults['auth']?['accessToken'] == true ? '있음' : '없음'}'); print('Refresh Token: ${testResults['auth']?['refreshToken'] == true ? '있음' : '없음'}'); print('\n[LoginController] === 대시보드 API ==='); print('Overview Stats: ${testResults['dashboard_stats']?['success'] == true ? '✅ 성공' : '❌ 실패'}'); if (testResults['dashboard_stats']?['error'] != null) { print(' 에러: ${testResults['dashboard_stats']['error']}'); } if (testResults['dashboard_stats']?['data'] != null) { print(' 데이터: ${testResults['dashboard_stats']['data']}'); } print('\n[LoginController] === 장비 상태 분포 ==='); print('Equipment Status: ${testResults['equipment_status_distribution']?['success'] == true ? '✅ 성공' : '❌ 실패'}'); if (testResults['equipment_status_distribution']?['error'] != null) { print(' 에러: ${testResults['equipment_status_distribution']['error']}'); } if (testResults['equipment_status_distribution']?['data'] != null) { print(' 데이터: ${testResults['equipment_status_distribution']['data']}'); } print('\n[LoginController] === 장비 목록 ==='); print('Equipments: ${testResults['equipments']?['success'] == true ? '✅ 성공' : '❌ 실패'}'); if (testResults['equipments']?['error'] != null) { print(' 에러: ${testResults['equipments']['error']}'); } if (testResults['equipments']?['sample'] != null) { print(' 샘플: ${testResults['equipments']['sample']}'); } print('\n[LoginController] === 입고지 ==='); print('Warehouses: ${testResults['warehouses']?['success'] == true ? '✅ 성공' : '❌ 실패'}'); if (testResults['warehouses']?['error'] != null) { print(' 에러: ${testResults['warehouses']['error']}'); } print('\n[LoginController] === 회사 ==='); print('Companies: ${testResults['companies']?['success'] == true ? '✅ 성공' : '❌ 실패'}'); if (testResults['companies']?['error'] != null) { print(' 에러: ${testResults['companies']['error']}'); } print('\n[LoginController] ========== Health Test 완료 ==========\n'); } catch (e, stackTrace) { print('[LoginController] Health Test 오류: $e'); print('[LoginController] Stack Trace: $stackTrace'); } _isLoading = false; notifyListeners(); return true; }, ); } catch (e, stackTrace) { print('[LoginController] 로그인 예외 발생: $e'); print('[LoginController] 스택 트레이스: $stackTrace'); _errorMessage = '로그인 중 오류가 발생했습니다: ${e.toString()}'; _isLoading = false; notifyListeners(); return false; } } /// 에러 메시지 초기화 void clearError() { _errorMessage = null; notifyListeners(); } /// 로그아웃 처리 void logout() { // 헬스체크 모니터링 중지 if (_healthCheckService.isMonitoring) { print('[LoginController] 헬스체크 모니터링 중지'); _healthCheckService.stopPeriodicHealthCheck(); } } @override void dispose() { // 헬스체크 모니터링 중지 if (_healthCheckService.isMonitoring) { _healthCheckService.stopPeriodicHealthCheck(); } idController.dispose(); pwController.dispose(); idFocus.dispose(); pwFocus.dispose(); super.dispose(); } }