import 'package:flutter/foundation.dart'; import 'package:shared_preferences/shared_preferences.dart'; import '../config/api_config.dart'; import '../models/event_model.dart'; import '../models/participant_model.dart'; import '../models/score_model.dart'; import '../models/team_model.dart'; import './api_service.dart'; class EventService with ChangeNotifier { List _events = []; Event? _currentEvent; List _participants = []; List _scores = []; List _teams = []; bool _isLoading = false; String? _token; ApiService _apiService; String? _clubId; // 기본 생성자 EventService() : _apiService = ApiService(); // 테스트용 생성자 EventService.forTest(this._apiService); List get events => [..._events]; Event? get currentEvent => _currentEvent; List get participants => [..._participants]; List get scores => [..._scores]; List get teams => [..._teams]; bool get isLoading => _isLoading; // 초기화 함수 Future initialize(String token) async { _token = token; _apiService.setToken(token); } // 클럽 ID 설정 void setClubId(String clubId) { _clubId = clubId; notifyListeners(); } // 클럽의 모든 이벤트 가져오기 Future fetchClubEvents() async { print('fetchClubEvents 호출됨: token=$_token'); _isLoading = true; notifyListeners(); try { // 클럽 ID 가져오기 final prefs = await SharedPreferences.getInstance(); final clubId = prefs.getString(ApiConfig.clubIdKey); if (clubId == null) { throw Exception('선택된 클럽이 없습니다'); } final data = await _apiService.post( '${ApiConfig.clubs}/events', data: {'clubId': clubId}, ); // 응답 데이터가 리스트 형태로 직접 왔는지 확인 if (data is List) { final List eventsData = data; _events = eventsData .map((eventData) => Event.fromJson(eventData)) .toList(); } else { // 응답 데이터가 객체 형태로 왔을 경우 events 키를 통해 접근 final List eventsData = data['events'] ?? []; _events = eventsData .map((eventData) => Event.fromJson(eventData)) .toList(); } _isLoading = false; notifyListeners(); } catch (e) { _isLoading = false; notifyListeners(); throw Exception('이벤트 목록을 불러오는데 실패했습니다: $e'); } } // ID로 이벤트 정보 가져오기 Future fetchEventById(String eventId) async { if (_token == null || _clubId == null) { throw Exception('인증 또는 클럽 정보가 필요합니다'); } try { final data = await _apiService.post( '${ApiConfig.clubs}/events/detail', data: {'eventId': eventId}, ); return Event.fromJson(data['event']); } catch (e) { throw Exception('이벤트 정보를 불러오는데 실패했습니다: $e'); } } // 이벤트 생성 Future createEvent(Map eventData) async { if (_token == null || _clubId == null) { throw Exception('인증 또는 클럽 정보가 필요합니다'); } _isLoading = true; notifyListeners(); try { final data = await _apiService.post( '${ApiConfig.clubs}/events', data: eventData, ); final newEvent = Event.fromJson(data['event']); _events.add(newEvent); _isLoading = false; notifyListeners(); return newEvent; } catch (e) { _isLoading = false; notifyListeners(); throw Exception('이벤트 생성에 실패했습니다: $e'); } } // 이벤트 정보 업데이트 Future updateEvent( String eventId, Map updates, ) async { if (_token == null || _clubId == null) { throw Exception('인증 또는 클럽 정보가 필요합니다'); } _isLoading = true; notifyListeners(); try { final data = await _apiService.put( '${ApiConfig.clubs}/events/$eventId', data: updates, ); final updatedEvent = Event.fromJson(data['event']); // 이벤트 목록 업데이트 final index = _events.indexWhere((event) => event.id == eventId); if (index >= 0) { _events[index] = updatedEvent; } _isLoading = false; notifyListeners(); return updatedEvent; } catch (e) { _isLoading = false; notifyListeners(); throw Exception('이벤트 정보 업데이트에 실패했습니다: $e'); } } // 이벤트 삭제 Future deleteEvent(String eventId) async { if (_token == null || _clubId == null) { throw Exception('인증 또는 클럽 정보가 필요합니다'); } _isLoading = true; notifyListeners(); try { await _apiService.delete('${ApiConfig.clubs}/events/$eventId'); // 이벤트 목록에서 삭제 _events.removeWhere((event) => event.id == eventId); _isLoading = false; notifyListeners(); return true; } catch (e) { _isLoading = false; notifyListeners(); throw Exception('이벤트 삭제에 실패했습니다: $e'); } } // 참가자 관리 기능 // 이벤트 참가자 목록 가져오기 Future> fetchEventParticipants(String eventId) async { if (_token == null || _clubId == null) { throw Exception('인증 또는 클럽 정보가 필요합니다'); } _isLoading = true; notifyListeners(); try { final data = await _apiService.post( '${ApiConfig.clubs}/events/participants', data: {'eventId': eventId}, ); final List participantsData = data['participants'] ?? []; _participants = participantsData .map((participantData) => Participant.fromJson(participantData)) .toList(); _isLoading = false; notifyListeners(); return _participants; } catch (e) { _isLoading = false; notifyListeners(); throw Exception('참가자 목록을 불러오는데 실패했습니다: $e'); } } // 참가자 추가 Future addParticipant( String eventId, Map participantData, ) async { if (_token == null || _clubId == null) { throw Exception('인증 또는 클럽 정보가 필요합니다'); } _isLoading = true; notifyListeners(); try { final data = await _apiService.post( '${ApiConfig.clubs}/events/$eventId/participants', data: participantData, ); final newParticipant = Participant.fromJson(data['participant']); _participants.add(newParticipant); _isLoading = false; notifyListeners(); return newParticipant; } catch (e) { _isLoading = false; notifyListeners(); throw Exception('참가자 추가에 실패했습니다: $e'); } } // 참가자 정보 업데이트 Future updateParticipant( String eventId, String participantId, Map updates, ) async { if (_token == null || _clubId == null) { throw Exception('인증 또는 클럽 정보가 필요합니다'); } _isLoading = true; notifyListeners(); try { final data = await _apiService.put( '${ApiConfig.clubs}/events/$eventId/participants/$participantId', data: updates, ); final updatedParticipant = Participant.fromJson(data['participant']); // 참가자 목록 업데이트 final index = _participants.indexWhere( (participant) => participant.id == participantId, ); if (index >= 0) { _participants[index] = updatedParticipant; } _isLoading = false; notifyListeners(); return updatedParticipant; } catch (e) { _isLoading = false; notifyListeners(); throw Exception('참가자 정보 업데이트에 실패했습니다: $e'); } } // 참가자 삭제 Future removeParticipant(String eventId, String participantId) async { if (_token == null || _clubId == null) { throw Exception('인증 또는 클럽 정보가 필요합니다'); } _isLoading = true; notifyListeners(); try { await _apiService.delete( '${ApiConfig.clubs}/events/$eventId/participants/$participantId', ); // 참가자 목록에서 삭제 _participants.removeWhere( (participant) => participant.id == participantId, ); _isLoading = false; notifyListeners(); return true; } catch (e) { _isLoading = false; notifyListeners(); throw Exception('참가자 삭제에 실패했습니다: $e'); } } // 참가자 상태 업데이트 Future updateParticipantStatus( String eventId, String participantId, String status, ) async { return updateParticipant(eventId, participantId, {'status': status}); } // 점수 관리 기능 // 이벤트 점수 목록 가져오기 Future> fetchEventScores(String eventId) async { if (_token == null || _clubId == null) { throw Exception('인증 또는 클럽 정보가 필요합니다'); } _isLoading = true; notifyListeners(); try { final data = await _apiService.post( '${ApiConfig.clubs}/events/scores', data: {'eventId': eventId}, ); final List scoresData = data['scores'] ?? []; _scores = scoresData .map((scoreData) => Score.fromJson(scoreData)) .toList(); _isLoading = false; notifyListeners(); return _scores; } catch (e) { _isLoading = false; notifyListeners(); throw Exception('점수 목록을 불러오는데 실패했습니다: $e'); } } // 점수 추가 Future addScore(String eventId, Map scoreData) async { if (_token == null || _clubId == null) { throw Exception('인증 또는 클럽 정보가 필요합니다'); } _isLoading = true; notifyListeners(); try { final data = await _apiService.post( '${ApiConfig.clubs}/events/$eventId/scores', data: scoreData, ); final newScore = Score.fromJson(data['score']); _scores.add(newScore); _isLoading = false; notifyListeners(); return newScore; } catch (e) { _isLoading = false; notifyListeners(); throw Exception('점수 추가에 실패했습니다: $e'); } } // 점수 업데이트 Future updateScore( String eventId, String scoreId, Map updates, ) async { if (_token == null || _clubId == null) { throw Exception('인증 또는 클럽 정보가 필요합니다'); } _isLoading = true; notifyListeners(); try { final data = await _apiService.put( '${ApiConfig.clubs}/events/$eventId/scores/$scoreId', data: updates, ); final updatedScore = Score.fromJson(data['score']); // 점수 목록 업데이트 final index = _scores.indexWhere((score) => score.id == scoreId); if (index >= 0) { _scores[index] = updatedScore; } _isLoading = false; notifyListeners(); return updatedScore; } catch (e) { _isLoading = false; notifyListeners(); throw Exception('점수 업데이트에 실패했습니다: $e'); } } // 점수 삭제 Future deleteScore(String eventId, String scoreId) async { if (_token == null || _clubId == null) { throw Exception('인증 또는 클럽 정보가 필요합니다'); } _isLoading = true; notifyListeners(); try { await _apiService.delete( '${ApiConfig.clubs}/events/$eventId/scores/$scoreId', ); // 점수 목록에서 삭제 _scores.removeWhere((score) => score.id == scoreId); _isLoading = false; notifyListeners(); return true; } catch (e) { _isLoading = false; notifyListeners(); throw Exception('점수 삭제에 실패했습니다: $e'); } } // 팀 관리 기능 // 이벤트 팀 목록 가져오기 Future> fetchEventTeams(String eventId) async { if (_token == null || _clubId == null) { throw Exception('인증 또는 클럽 정보가 필요합니다'); } _isLoading = true; notifyListeners(); try { final data = await _apiService.post( '${ApiConfig.clubs}/events/teams', data: {'eventId': eventId}, ); final List teamsData = data['teams'] ?? []; _teams = teamsData.map((teamData) => Team.fromJson(teamData)).toList(); _isLoading = false; notifyListeners(); return _teams; } catch (e) { _isLoading = false; notifyListeners(); throw Exception('팀 목록을 불러오는데 실패했습니다: $e'); } } // 팀 생성 Future> generateTeams( String eventId, Map teamConfig, ) async { if (_token == null || _clubId == null) { throw Exception('인증 또는 클럽 정보가 필요합니다'); } _isLoading = true; notifyListeners(); try { final data = await _apiService.post( '${ApiConfig.clubs}/events/$eventId/teams/generate', data: teamConfig, ); final List teamsData = data['teams'] ?? []; _teams = teamsData.map((teamData) => Team.fromJson(teamData)).toList(); _isLoading = false; notifyListeners(); return _teams; } catch (e) { _isLoading = false; notifyListeners(); throw Exception('팀 생성에 실패했습니다: $e'); } } // 팀 저장 Future saveTeams(String eventId, List teams) async { if (_token == null || _clubId == null) { throw Exception('인증 또는 클럽 정보가 필요합니다'); } _isLoading = true; notifyListeners(); try { await _apiService.post( '${ApiConfig.clubs}/events/$eventId/teams/save', data: {'teams': teams.map((team) => team.toJson()).toList()}, ); _teams = teams; _isLoading = false; notifyListeners(); return true; } catch (e) { _isLoading = false; notifyListeners(); throw Exception('팀 저장에 실패했습니다: $e'); } } // 파일에서 이벤트 일괄 생성 Future> createEventsFromFile( List> eventsData, ) async { if (_token == null || _clubId == null) { throw Exception('인증 또는 클럽 정보가 필요합니다'); } _isLoading = true; notifyListeners(); try { final List createdEvents = []; // 각 이벤트 데이터에 클럽 ID 추가 for (var eventData in eventsData) { eventData['clubId'] = _clubId; // null 값 처리 - 빈 문자열을 명시적 null로 변환 eventData.forEach((key, value) { if (value is String && value.isEmpty) { eventData[key] = null; } }); // 이벤트 생성 API 호출 final data = await _apiService.post( '${ApiConfig.clubs}/events', data: eventData, ); final newEvent = Event.fromJson(data['event']); createdEvents.add(newEvent); _events.add(newEvent); } _isLoading = false; notifyListeners(); return createdEvents; } catch (e) { _isLoading = false; notifyListeners(); throw Exception('파일에서 이벤트 생성에 실패했습니다: $e'); } } // 이벤트 복제 Future cloneEvent(String eventId, {String? newName}) async { if (_token == null || _clubId == null) { throw Exception('인증 또는 클럽 정보가 필요합니다'); } _isLoading = true; notifyListeners(); try { // 원본 이벤트 정보 가져오기 final originalEvent = await fetchEventById(eventId); // 복제할 이벤트 데이터 준비 final Map cloneData = { 'clubId': _clubId, 'title': newName ?? '${originalEvent.title} (복사본)', 'description': originalEvent.description, 'location': originalEvent.location, 'type': originalEvent.type, 'status': 'draft', // 복제된 이벤트는 초안 상태로 시작 'startDate': originalEvent.startDate.toIso8601String(), 'endDate': originalEvent.endDate?.toIso8601String(), 'maxParticipants': originalEvent.maxParticipants, 'participantFee': originalEvent.participantFee, 'gameCount': originalEvent.gameCount, 'publicHash': originalEvent.publicHash, 'accessPassword': originalEvent.accessPassword, 'isActive': true, }; // 이벤트 생성 API 호출 final data = await _apiService.post( '${ApiConfig.clubs}/events', data: cloneData, ); final newEvent = Event.fromJson(data['event']); _events.add(newEvent); _isLoading = false; notifyListeners(); return newEvent; } catch (e) { _isLoading = false; notifyListeners(); throw Exception('이벤트 복제에 실패했습니다: $e'); } } }