import 'dart:async'; import 'package:flutter/material.dart'; import 'package:get_it/get_it.dart'; import 'package:superport/models/company_model.dart'; import 'package:superport/models/user_model.dart'; import 'package:superport/services/mock_data_service.dart'; import 'package:superport/services/user_service.dart'; import 'package:superport/utils/constants.dart'; import 'package:superport/models/user_phone_field.dart'; // 사용자 폼의 상태 및 비즈니스 로직을 담당하는 컨트롤러 class UserFormController extends ChangeNotifier { final MockDataService dataService; final UserService _userService = GetIt.instance(); final GlobalKey formKey = GlobalKey(); // 상태 변수 bool _isLoading = false; String? _error; bool _useApi = true; // Feature flag // 폼 필드 bool isEditMode = false; int? userId; String name = ''; String username = ''; // 추가 String password = ''; // 추가 int? companyId; int? branchId; String role = UserRoles.member; String position = ''; String email = ''; // username 중복 확인 bool _isCheckingUsername = false; bool? _isUsernameAvailable; String? _lastCheckedUsername; Timer? _usernameCheckTimer; // 전화번호 관련 상태 final List phoneFields = []; final List phoneTypes = ['휴대폰', '사무실', '팩스', '기타']; List companies = []; List branches = []; // Getters bool get isLoading => _isLoading; String? get error => _error; bool get isCheckingUsername => _isCheckingUsername; bool? get isUsernameAvailable => _isUsernameAvailable; UserFormController({required this.dataService, this.userId}) { isEditMode = userId != null; if (isEditMode) { loadUser(); } else { addPhoneField(); } loadCompanies(); } // 회사 목록 로드 void loadCompanies() { companies = dataService.getAllCompanies(); notifyListeners(); } // 회사 ID에 따라 지점 목록 로드 void loadBranches(int companyId) { final company = dataService.getCompanyById(companyId); branches = company?.branches ?? []; // 지점 변경 시 이전 선택 지점이 새 회사에 없으면 초기화 if (branchId != null && !branches.any((b) => b.id == branchId)) { branchId = null; } notifyListeners(); } // 사용자 정보 로드 (수정 모드) Future loadUser() async { if (userId == null) return; _isLoading = true; _error = null; notifyListeners(); try { User? user; if (_useApi) { user = await _userService.getUser(userId!); } else { user = dataService.getUserById(userId!); } if (user != null) { name = user.name; username = user.username ?? ''; companyId = user.companyId; branchId = user.branchId; role = user.role; position = user.position ?? ''; email = user.email ?? ''; if (companyId != null) { loadBranches(companyId!); } phoneFields.clear(); if (user.phoneNumbers.isNotEmpty) { for (var phone in user.phoneNumbers) { phoneFields.add( UserPhoneField( type: phone['type'] ?? '휴대폰', initialValue: phone['number'] ?? '', ), ); } } else { addPhoneField(); } } } catch (e) { _error = e.toString(); } finally { _isLoading = false; notifyListeners(); } } // 전화번호 필드 추가 void addPhoneField() { phoneFields.add(UserPhoneField(type: '휴대폰')); notifyListeners(); } // 전화번호 필드 삭제 void removePhoneField(int index) { if (phoneFields.length > 1) { phoneFields[index].dispose(); phoneFields.removeAt(index); notifyListeners(); } } // Username 중복 확인 void checkUsernameAvailability(String value) { if (value.isEmpty || value == _lastCheckedUsername) { return; } // 디바운싱 _usernameCheckTimer?.cancel(); _usernameCheckTimer = Timer(const Duration(milliseconds: 500), () async { _isCheckingUsername = true; notifyListeners(); try { if (_useApi) { final isDuplicate = await _userService.checkDuplicateUsername(value); _isUsernameAvailable = !isDuplicate; } else { // Mock 데이터에서 중복 확인 final users = dataService.getAllUsers(); final exists = users.any((u) => u.username == value && u.id != userId); _isUsernameAvailable = !exists; } _lastCheckedUsername = value; } catch (e) { _isUsernameAvailable = null; } finally { _isCheckingUsername = false; notifyListeners(); } }); } // 사용자 저장 (UI에서 호출) Future saveUser(Function(String? error) onResult) async { if (formKey.currentState?.validate() != true) { onResult('폼 유효성 검사 실패'); return; } formKey.currentState?.save(); if (companyId == null) { onResult('소속 회사를 선택해주세요'); return; } // 신규 등록 시 username 중복 확인 if (!isEditMode) { if (username.isEmpty) { onResult('사용자명을 입력해주세요'); return; } if (_isUsernameAvailable == false) { onResult('이미 사용중인 사용자명입니다'); return; } if (password.isEmpty) { onResult('비밀번호를 입력해주세요'); return; } } _isLoading = true; _error = null; notifyListeners(); try { // 전화번호 목록 준비 String? phoneNumber; for (var phoneField in phoneFields) { if (phoneField.number.isNotEmpty) { phoneNumber = phoneField.number; break; // API는 단일 전화번호만 지원 } } if (_useApi) { if (isEditMode && userId != null) { // 사용자 수정 await _userService.updateUser( userId!, name: name, email: email.isNotEmpty ? email : null, phone: phoneNumber, companyId: companyId, branchId: branchId, role: role, position: position.isNotEmpty ? position : null, password: password.isNotEmpty ? password : null, ); } else { // 사용자 생성 await _userService.createUser( username: username, email: email, password: password, name: name, role: role, companyId: companyId!, branchId: branchId, phone: phoneNumber, position: position.isNotEmpty ? position : null, ); } } else { // Mock 데이터 사용 List> phoneNumbersList = []; for (var phoneField in phoneFields) { if (phoneField.number.isNotEmpty) { phoneNumbersList.add({ 'type': phoneField.type, 'number': phoneField.number, }); } } if (isEditMode && userId != null) { final user = dataService.getUserById(userId!); if (user != null) { final updatedUser = User( id: user.id, companyId: companyId!, branchId: branchId, name: name, role: role, position: position.isNotEmpty ? position : null, email: email.isNotEmpty ? email : null, phoneNumbers: phoneNumbersList, username: username.isNotEmpty ? username : null, isActive: user.isActive, createdAt: user.createdAt, updatedAt: DateTime.now(), ); dataService.updateUser(updatedUser); } } else { final newUser = User( companyId: companyId!, branchId: branchId, name: name, role: role, position: position.isNotEmpty ? position : null, email: email.isNotEmpty ? email : null, phoneNumbers: phoneNumbersList, username: username, isActive: true, createdAt: DateTime.now(), updatedAt: DateTime.now(), ); dataService.addUser(newUser); } } onResult(null); } catch (e) { _error = e.toString(); onResult(_error); } finally { _isLoading = false; notifyListeners(); } } // 컨트롤러 해제 @override void dispose() { _usernameCheckTimer?.cancel(); for (var phoneField in phoneFields) { phoneField.dispose(); } super.dispose(); } // API/Mock 모드 전환 void toggleApiMode() { _useApi = !_useApi; notifyListeners(); } }