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<TaskFormState> {
  final TasksRepository _repository = GetIt.I.get<TasksRepository>();
  final SettingsRepository _settingsRepository = GetIt.I
      .get<SettingsRepository>();
  final _staffRepository = GetIt.I.get<StaffRepository>();
  final SessionCubit _sessionCubit = GetIt.I.get<SessionCubit>();
  final List<StaffMemberModel>? _preloadedStaff;

  TaskFormCubit({
    String? initialTaskId, // <-- RIPRISTINATO PER DEEP LINK
    TaskModel? existingTask,
    List<StaffMemberModel>? 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<void> 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<void> _loadAndGroupStaff() async {
    final List<StaffMemberModel> 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<String, List<StaffMemberModel>> 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<void> _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<void> _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<String>.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<String>.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<TaskReminderConfig>.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<TaskReminderConfig>.from(state.reminders)
      ..removeAt(index);
    emit(state.copyWith(reminders: updated));
  }

  // --- SALVATAGGIO ---
  Future<void> 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(),
        ),
      );
    }
  }
}
