import 'package:flutter/material.dart'; import 'package:injectable/injectable.dart'; import 'package:superport/data/models/model/model_dto.dart'; import 'package:superport/data/models/vendor_dto.dart'; import 'package:superport/domain/usecases/models/get_models_usecase.dart'; import 'package:superport/domain/usecases/models/create_model_usecase.dart'; import 'package:superport/domain/usecases/models/update_model_usecase.dart'; import 'package:superport/domain/usecases/models/delete_model_usecase.dart'; import 'package:superport/domain/usecases/vendor_usecase.dart'; /// Model 관리 화면의 상태 관리 Controller @lazySingleton class ModelController extends ChangeNotifier { final GetModelsUseCase _getModelsUseCase; final CreateModelUseCase _createModelUseCase; final UpdateModelUseCase _updateModelUseCase; final DeleteModelUseCase _deleteModelUseCase; final VendorUseCase _vendorUseCase; ModelController( this._getModelsUseCase, this._createModelUseCase, this._updateModelUseCase, this._deleteModelUseCase, this._vendorUseCase, ); // 상태 변수들 List _models = []; List _filteredModels = []; List _vendors = []; final Map> _modelsByVendor = {}; bool _isLoading = false; bool _isLoadingVendors = false; bool _isSubmitting = false; String? _errorMessage; String? _vendorsError; String _searchQuery = ''; int? _selectedVendorId; // Getters List get models => _filteredModels; List get allModels => _models; List get vendors => _vendors; Map> get modelsByVendor => _modelsByVendor; bool get isLoading => _isLoading; bool get isLoadingVendors => _isLoadingVendors; bool get isSubmitting => _isSubmitting; String? get errorMessage => _errorMessage; String? get vendorsError => _vendorsError; String get searchQuery => _searchQuery; int? get selectedVendorId => _selectedVendorId; int get totalCount => _filteredModels.length; /// 초기 데이터 로드 Future loadInitialData() async { _isLoading = true; _errorMessage = null; notifyListeners(); try { // Vendor 데이터 로드 (완전 안전한 오류 처리) try { final vendorResponse = await _vendorUseCase.getVendors(); if (vendorResponse != null && vendorResponse.items.isNotEmpty) { _vendors = List.from(vendorResponse.items); } else { _vendors = []; } } catch (vendorError) { _vendors = []; _vendorsError = "제조사 목록 로드 실패: $vendorError"; } // Model 데이터 로드 (안전한 처리) const params = GetModelsParams(page: 1, perPage: 100); final modelResult = await _getModelsUseCase(params); modelResult.fold( (failure) => throw Exception(failure.message), (modelResponse) { if (modelResponse != null && modelResponse.items.isNotEmpty) { _models = List.from(modelResponse.items); _filteredModels = List.from(_models); } else { _models = []; _filteredModels = []; } }, ); // Vendor별로 모델 그룹핑 await _groupModelsByVendor(); } catch (e) { _errorMessage = "모델 목록 조회 실패: ${e.toString()}"; } finally { _isLoading = false; notifyListeners(); } } /// 모델 목록 새로고침 Future refreshModels() async { _errorMessage = null; try { final params = GetModelsParams( page: 1, perPage: 100, vendorId: _selectedVendorId, ); final result = await _getModelsUseCase(params); result.fold( (failure) => throw Exception(failure.message), (modelResponse) { if (modelResponse != null && modelResponse.items.isNotEmpty) { _models = List.from(modelResponse.items); } else { _models = []; } _applyFilters(); }, ); await _groupModelsByVendor(); } catch (e) { _errorMessage = e.toString(); } finally { notifyListeners(); } } /// 모델 생성 Future createModel({ required int vendorsId, required String name, }) async { _isSubmitting = true; _errorMessage = null; notifyListeners(); try { final request = CreateModelRequest(vendorsId: vendorsId, name: name); final result = await _createModelUseCase(request); return result.fold( (failure) { _errorMessage = failure.message; return false; }, (newModel) { // 목록에 추가 _models = [..._models, newModel]; _applyFilters(); _groupModelsByVendor(); return true; }, ); } catch (e) { _errorMessage = e.toString(); return false; } finally { _isSubmitting = false; notifyListeners(); } } /// 모델 수정 Future updateModel({ required int id, required int vendorsId, required String name, }) async { _isSubmitting = true; _errorMessage = null; notifyListeners(); try { final request = UpdateModelRequest(vendorsId: vendorsId, name: name); final params = UpdateModelParams(id: id, request: request); final result = await _updateModelUseCase(params); return result.fold( (failure) { _errorMessage = failure.message; return false; }, (updatedModel) { // 목록에서 업데이트 final index = _models.indexWhere((m) => m.id == id); if (index != -1) { _models = _models.map((model) => model.id == id ? updatedModel : model ).toList(); _applyFilters(); _groupModelsByVendor(); } return true; }, ); } catch (e) { _errorMessage = e.toString(); return false; } finally { _isSubmitting = false; notifyListeners(); } } /// 모델 삭제 (Soft Delete) Future deleteModel(int id) async { _isSubmitting = true; _errorMessage = null; notifyListeners(); try { final result = await _deleteModelUseCase(id); return result.fold( (failure) { _errorMessage = failure.message; return false; }, (_) { // 목록에서 제거 또는 비활성화 표시 _models = _models.where((m) => m.id != id).toList(); _applyFilters(); _groupModelsByVendor(); return true; }, ); } catch (e) { _errorMessage = e.toString(); return false; } finally { _isSubmitting = false; notifyListeners(); } } /// 검색어 설정 void setSearchQuery(String query) { _searchQuery = query; _applyFilters(); notifyListeners(); } /// Vendor 필터 설정 void setVendorFilter(int? vendorId) { _selectedVendorId = vendorId; _applyFilters(); notifyListeners(); } /// 필터 적용 void _applyFilters() { _filteredModels = _models.where((model) { // Vendor 필터 if (_selectedVendorId != null && model.vendorsId != _selectedVendorId) { return false; } // 검색어 필터 if (_searchQuery.isNotEmpty) { final query = _searchQuery.toLowerCase(); return model.name.toLowerCase().contains(query); } return true; }).toList(); } /// Vendor별 모델 그룹핑 Future _groupModelsByVendor() async { _modelsByVendor.clear(); for (final model in _models) { _modelsByVendor.putIfAbsent(model.vendorsId, () => []).add(model); } } /// Vendor ID로 Vendor 정보 가져오기 VendorDto? getVendorById(int vendorId) { try { return _vendors.firstWhere((v) => v.id == vendorId); } catch (_) { return null; } } /// 특정 Vendor의 모델 목록 가져오기 List getModelsByVendor(int vendorId) { return _modelsByVendor[vendorId] ?? []; } /// 모델명 중복 확인 Future checkDuplicateName(String name, {int? excludeId}) async { try { // 현재 로드된 모델 목록에서 중복 검사 final duplicates = _models.where((model) { // 수정 모드일 때 자기 자신은 제외 if (excludeId != null && model.id == excludeId) { return false; } // 대소문자 구분 없이 이름 비교 return model.name.toLowerCase() == name.toLowerCase(); }).toList(); return duplicates.isNotEmpty; } catch (e) { // 에러 발생 시 false 반환 (중복 없음으로 처리) return false; } } /// 에러 메시지 클리어 void clearError() { _errorMessage = null; notifyListeners(); } /// 컨트롤러 리셋 void reset() { _models.clear(); _filteredModels.clear(); _vendors.clear(); _modelsByVendor.clear(); _isLoading = false; _isSubmitting = false; _errorMessage = null; _searchQuery = ''; _selectedVendorId = null; notifyListeners(); } @override void dispose() { reset(); super.dispose(); } }