import 'package:equatable/equatable.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flux/core/blocs/session/session_cubit.dart'; import 'package:flux/features/master_data/staff/data/staff_repository.dart'; import 'package:flux/features/master_data/staff/models/staff_member_model.dart'; import 'package:flux/features/settings/data/settings_repository.dart'; import 'package:flux/features/tasks/data/task_repository.dart'; import 'package:flux/features/tasks/models/task_model.dart'; import 'package:flux/features/tasks/models/task_reminder_config.dart'; import 'package:get_it/get_it.dart'; part 'task_form_state.dart'; class TaskFormCubit extends Cubit { final TasksRepository _repository = GetIt.I.get(); final SettingsRepository _settingsRepository = GetIt.I .get(); final _staffRepository = GetIt.I.get(); final SessionCubit _sessionCubit = GetIt.I.get(); final List? _preloadedStaff; TaskFormCubit({ String? initialTaskId, // <-- RIPRISTINATO PER DEEP LINK TaskModel? existingTask, List? allStaff, }) : _preloadedStaff = allStaff, super(const TaskFormState()) { // Avviamo l'inizializzazione centralizzata (gestisce sia mem, sia deep link, sia nuovo) initForm(initialTaskId: initialTaskId, existingTask: existingTask); } String get _companyId => _sessionCubit.state.company!.id!; String get _currentUserId => _sessionCubit.state.currentStaffMember!.id!; String? get _currentStoreId => _sessionCubit.state.currentStore?.id; // --- ARMED INITIALIZATION (Nuovo, Esistente o Deep Link) --- Future initForm({ String? initialTaskId, TaskModel? existingTask, }) async { emit(state.copyWith(status: TaskFormStatus.loading)); try { TaskModel? task = existingTask; // 1. Se arriviamo da Deep Link col solo ID, lo scarichiamo dal DB if (initialTaskId != null && task == null) { task = await _repository.fetchTaskById(initialTaskId); } if (task != null) { // CASO: TASK ESISTENTE (Modifica o Deep Link pronto) emit( state.copyWith( id: task.id, title: task.title, description: task.description, dueDate: task.dueDate, isGlobal: task.isGlobal, // Sfrutta il tuo getter storeId == null selectedStaffIds: task.assignedToIds, ), ); await _loadExistingTaskReminders(task.id!); } else { // CASO: NUOVO TASK await _initializeNewTaskReminders(); } // 2. Carichiamo e raggruppiamo il personale (Global o Store) await _loadAndGroupStaff(); // Mandiamo lo status a 'initial' così il FormScreen sincronizza i controller di testo! emit(state.copyWith(status: TaskFormStatus.initial)); } catch (e) { emit( state.copyWith( status: TaskFormStatus.failure, errorMessage: e.toString(), ), ); } } // --- LOGICA GESTIONE STAFF (GLOBAL STAFF / STORE STAFF) --- Future _loadAndGroupStaff() async { final List staffList; // SE C'È LO STAFF PASCIUTO DALL'APP USA QUELLO, ALTRIMENTI CHIAMA IL REPO if (_preloadedStaff != null && _preloadedStaff.isNotEmpty) { staffList = _preloadedStaff; } else { staffList = await _staffRepository.getStaffMembers(_companyId); } final Map> grouped = {}; for (var staff in staffList) { if (!state.isGlobal) { final belongsToCurrentStore = staff.assignedStores.any( (store) => store.id == _currentStoreId, ); if (!belongsToCurrentStore) continue; } if (staff.assignedStores.isEmpty) { grouped.putIfAbsent('Direzione / Senza Sede', () => []).add(staff); } else { for (var store in staff.assignedStores) { if (!state.isGlobal && store.id != _currentStoreId) continue; final storeName = store.name; grouped.putIfAbsent(storeName, () => []).add(staff); } } } emit(state.copyWith(groupedAvailableStaff: grouped)); } // Se l'utente switcha su "Globale Aziendale", ricarichiamo lo staff di conseguenza void toggleGlobalScope(bool g) async { emit(state.copyWith(isGlobal: g, status: TaskFormStatus.loading)); await _loadAndGroupStaff(); emit( state.copyWith(status: TaskFormStatus.initial), ); // Ri-notifichiamo la UI } // --- INIT REMINDER --- Future _initializeNewTaskReminders() async { try { final defaults = await _settingsRepository.getMyReminderDefaults( companyId: _companyId, staffId: _currentUserId, ); final initialReminders = defaults .map( (d) => TaskReminderConfig( minutesBefore: d.minutesBefore, channel: d.channel, ), ) .toList(); emit(state.copyWith(reminders: initialReminders)); } catch (e) { emit( state.copyWith( reminders: const [ TaskReminderConfig(minutesBefore: 15, channel: 'push'), ], ), ); } } Future _loadExistingTaskReminders(String taskId) async { try { final existingConfigs = await _repository.fetchPersonalReminders( taskId: taskId, staffId: _currentUserId, ); emit(state.copyWith(reminders: existingConfigs)); } catch (e) { debugPrint('Errore caricamento reminder: $e'); } } // --- AGGIORNAMENTO CAMPI --- void updateTitle(String t) => emit(state.copyWith(title: t)); void updateDescription(String d) => emit(state.copyWith(description: d)); void updateDueDate(DateTime? d) => emit(state.copyWith(dueDate: d)); void toggleStaffSelection(String staffId) { final updated = List.from(state.selectedStaffIds); updated.contains(staffId) ? updated.remove(staffId) : updated.add(staffId); emit(state.copyWith(selectedStaffIds: updated)); } void toggleStoreSelection(String storeName, bool selectAll) { final updated = List.from(state.selectedStaffIds); final storeStaff = state.groupedAvailableStaff[storeName] ?? []; for (var staff in storeStaff) { if (staff.id == null) continue; if (selectAll) { if (!updated.contains(staff.id)) updated.add(staff.id!); } else { updated.remove(staff.id); } } emit(state.copyWith(selectedStaffIds: updated)); } // --- AZIONI REMINDER --- void addReminderRule(int minutesBefore, String channel) { final updated = List.from(state.reminders); final newConfig = TaskReminderConfig( minutesBefore: minutesBefore, channel: channel, ); if (!updated.contains(newConfig)) { updated.add(newConfig); updated.sort((a, b) => a.minutesBefore.compareTo(b.minutesBefore)); emit(state.copyWith(reminders: updated)); } } void removeReminderRule(int index) { final updated = List.from(state.reminders) ..removeAt(index); emit(state.copyWith(reminders: updated)); } // --- SALVATAGGIO --- Future saveTask() async { if (!state.isFormValid) return; emit(state.copyWith(status: TaskFormStatus.submitting)); final taskToSave = TaskModel( id: state.id, companyId: _companyId, createdById: _currentUserId, title: state.title.trim(), description: state.description.trim(), dueDate: state.dueDate, storeId: state.isGlobal ? null : _currentStoreId, // Gestione nativa basata sulla tua logica assignedToIds: state.selectedStaffIds, ); try { if (state.id == null) { await _repository.createTask( task: taskToSave, assignedStaffIds: state.selectedStaffIds, currentUserId: _currentUserId, currentUserCustomReminders: state.reminders, ); } else { await _repository.updateTask( task: taskToSave, assignedStaffIds: state.selectedStaffIds, currentUserId: _currentUserId, currentUserCustomReminders: state.reminders, ); } emit(state.copyWith(status: TaskFormStatus.success)); } catch (e) { emit( state.copyWith( status: TaskFormStatus.failure, errorMessage: e.toString(), ), ); } } }