import 'package:flutter_riverpod/legacy.dart';

enum EditorMode { visual, markdown }

class EditorState {
  /// The active slide (shown in the editor/preview). Always part of [selection].
  final int selectedIndex;

  /// All currently selected slide indices (for bulk actions). Never empty.
  final Set<int> selection;
  final EditorMode mode;
  final String markdownBuffer;
  final bool parseError;

  const EditorState({
    this.selectedIndex = 0,
    this.selection = const {0},
    this.mode = EditorMode.visual,
    this.markdownBuffer = '',
    this.parseError = false,
  });

  bool get hasMultiSelection => selection.length > 1;

  EditorState copyWith({
    int? selectedIndex,
    Set<int>? selection,
    EditorMode? mode,
    String? markdownBuffer,
    bool? parseError,
  }) {
    return EditorState(
      selectedIndex: selectedIndex ?? this.selectedIndex,
      selection: selection ?? this.selection,
      mode: mode ?? this.mode,
      markdownBuffer: markdownBuffer ?? this.markdownBuffer,
      parseError: parseError ?? this.parseError,
    );
  }
}

class EditorNotifier extends StateNotifier<EditorState> {
  EditorNotifier() : super(const EditorState());

  EditorState get currentState => state;

  /// Single-select [index] (clears any multi-selection).
  void select(int index) {
    if (index == state.selectedIndex && state.selection.length == 1) return;
    state = state.copyWith(
      selectedIndex: index,
      selection: {index},
      parseError: false,
    );
  }

  /// Ctrl/Cmd-click: voeg [index] toe of haal 'm uit de selectie.
  void toggleSelect(int index) {
    final next = Set<int>.from(state.selection);
    if (next.contains(index) && next.length > 1) {
      next.remove(index);
      final active = index == state.selectedIndex
          ? next.reduce((a, b) => a < b ? a : b)
          : state.selectedIndex;
      state = state.copyWith(selection: next, selectedIndex: active);
    } else {
      next.add(index);
      state = state.copyWith(selection: next, selectedIndex: index);
    }
  }

  /// Selecteer alle [count] slides (Ctrl/Cmd+A).
  void selectAll(int count) {
    if (count <= 0) return;
    state = state.copyWith(
      selection: {for (var i = 0; i < count; i++) i},
      selectedIndex: state.selectedIndex.clamp(0, count - 1),
    );
  }

  /// Shift-click: selecteer het bereik van de actieve slide tot [index].
  void selectRange(int index) {
    final anchor = state.selectedIndex;
    final lo = anchor < index ? anchor : index;
    final hi = anchor < index ? index : anchor;
    state = state.copyWith(
      selection: {for (var i = lo; i <= hi; i++) i},
      selectedIndex: index,
    );
  }

  void setMode(EditorMode mode, {String? initialMarkdown}) {
    state = state.copyWith(
      mode: mode,
      markdownBuffer: initialMarkdown ?? state.markdownBuffer,
      parseError: false,
    );
  }

  void updateMarkdown(String content) {
    state = state.copyWith(markdownBuffer: content);
  }

  void setParseError(bool value) {
    state = state.copyWith(parseError: value);
  }

  /// Clamp/normaliseer de selectie nadat slides zijn verwijderd.
  void clampIndex(int maxIndex) {
    final max = maxIndex < 0 ? 0 : maxIndex;
    final pruned = state.selection.where((i) => i <= max).toSet();
    final index = state.selectedIndex > max ? max : state.selectedIndex;
    state = state.copyWith(
      selectedIndex: index,
      selection: pruned.isEmpty ? {index} : pruned,
    );
  }
}

final editorProvider = StateNotifierProvider<EditorNotifier, EditorState>(
  (_) => EditorNotifier(),
);
