import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import '../../models/slide.dart';
import '../../l10n/app_localizations.dart';
import '_editor_field.dart';
import 'list_style_selector.dart';

typedef _Mutate = void Function(VoidCallback fn);

class TwoBulletsEditor extends StatefulWidget {
  final Slide slide;
  final ValueChanged<Slide> onUpdate;

  const TwoBulletsEditor({
    super.key,
    required this.slide,
    required this.onUpdate,
  });

  @override
  State<TwoBulletsEditor> createState() => _TwoBulletsEditorState();
}

class _TwoBulletsEditorState extends State<TwoBulletsEditor> {
  late final TextEditingController _title;
  late final TextEditingController _heading1;
  late final TextEditingController _heading2;
  late _BulletSet _left;
  late _BulletSet _right;
  late ListStyle _listStyle;
  late bool _showChecklistProgress;

  @override
  void initState() {
    super.initState();
    _title = TextEditingController(text: widget.slide.title);
    _title.addListener(_emit);
    _heading1 = TextEditingController(text: widget.slide.columnTitle1);
    _heading2 = TextEditingController(text: widget.slide.columnTitle2);
    _heading1.addListener(_emit);
    _heading2.addListener(_emit);
    _listStyle = widget.slide.listStyle;
    _showChecklistProgress = widget.slide.showChecklistProgress;
    _left = _BulletSet(widget.slide.bullets, _emit);
    _right = _BulletSet(widget.slide.bullets2, _emit);
  }

  void _emit() {
    widget.onUpdate(
      widget.slide.copyWith(
        title: _title.text,
        columnTitle1: _heading1.text,
        columnTitle2: _heading2.text,
        listStyle: _listStyle,
        showChecklistProgress: _showChecklistProgress,
        bullets: _left.values(_listStyle),
        bullets2: _right.values(_listStyle),
      ),
    );
  }

  @override
  void dispose() {
    _title.dispose();
    _heading1.dispose();
    _heading2.dispose();
    _left.dispose();
    _right.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return ListView(
      padding: const EdgeInsets.all(16),
      children: [
        EditorField(label: 'Titel', controller: _title, hint: 'Slide titel'),
        const SizedBox(height: 16),
        ListStyleSelector(
          value: _listStyle,
          onChanged: (value) {
            setState(() => _listStyle = value);
            _emit();
          },
        ),
        if (_listStyle == ListStyle.checklist)
          SwitchListTile(
            contentPadding: EdgeInsets.zero,
            title: Text(context.l10n.d('Voortgangsgrafiek tonen')),
            subtitle: Text(
              context.l10n.d(
                'Toont afgevinkt en niet afgevinkt als percentages.',
              ),
            ),
            value: _showChecklistProgress,
            onChanged: (value) {
              setState(() => _showChecklistProgress = value);
              _emit();
            },
          ),
        const SizedBox(height: 16),
        LayoutBuilder(
          builder: (context, constraints) {
            final narrow = constraints.maxWidth < 560;
            final columns = [
              _BulletColumn(
                label: 'Bullets links',
                set: _left,
                emit: _emit,
                headingController: _heading1,
                listStyle: _listStyle,
              ),
              _BulletColumn(
                label: 'Bullets rechts',
                set: _right,
                emit: _emit,
                headingController: _heading2,
                listStyle: _listStyle,
              ),
            ];
            if (narrow) {
              return Column(
                children: [columns[0], const SizedBox(height: 18), columns[1]],
              );
            }
            return Row(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Expanded(child: columns[0]),
                const SizedBox(width: 16),
                Expanded(child: columns[1]),
              ],
            );
          },
        ),
      ],
    );
  }
}

class _BulletSet {
  static const maxLevel = 4;

  final VoidCallback emit;
  late List<TextEditingController> controllers;
  late List<int> levels;
  late List<bool> checked;
  late List<FocusNode> focusNodes;

  _BulletSet(List<String> raw, this.emit) {
    final list = raw.isEmpty ? [''] : raw;
    levels = list.map(_levelOf).toList();
    checked = list.map(checklistItemChecked).toList();
    controllers = list.map((b) => _makeCtrl(checklistItemText(b))).toList();
    focusNodes = List.generate(controllers.length, (_) => FocusNode());
  }

  List<String> values(ListStyle listStyle) => List.generate(
    controllers.length,
    (i) => listStyle == ListStyle.checklist
        ? checklistBullet(
            level: levels[i],
            text: controllers[i].text,
            checked: checked[i],
          )
        : '\t' * levels[i] + controllers[i].text,
  );

  static int _levelOf(String b) {
    int l = 0;
    while (l < b.length && b[l] == '\t' && l < maxLevel) {
      l++;
    }
    return l;
  }

  TextEditingController _makeCtrl(String text) {
    final c = TextEditingController(text: text);
    c.addListener(emit);
    return c;
  }

  void addAfter(_Mutate mutate, int i) {
    mutate(() {
      controllers.insert(i + 1, _makeCtrl(''));
      levels.insert(i + 1, levels[i]);
      checked.insert(i + 1, false);
      focusNodes.insert(i + 1, FocusNode());
    });
    emit();
    WidgetsBinding.instance.addPostFrameCallback((_) {
      if (i + 1 < focusNodes.length) focusNodes[i + 1].requestFocus();
    });
  }

  void removeAndFocus(_Mutate mutate, int i) {
    if (controllers.length == 1) {
      mutate(() {
        controllers[i].removeListener(emit);
        controllers[i].clear();
        controllers[i].addListener(emit);
        levels[i] = 0;
        checked[i] = false;
      });
      emit();
      focusNodes[i].requestFocus();
      return;
    }
    final target = (i - 1).clamp(0, controllers.length - 2);
    mutate(() {
      controllers[i].removeListener(emit);
      controllers[i].dispose();
      controllers.removeAt(i);
      levels.removeAt(i);
      checked.removeAt(i);
      focusNodes[i].dispose();
      focusNodes.removeAt(i);
    });
    emit();
    WidgetsBinding.instance.addPostFrameCallback((_) {
      if (target < focusNodes.length) focusNodes[target].requestFocus();
    });
  }

  Future<void> paste(_Mutate mutate, int i) async {
    final data = await Clipboard.getData(Clipboard.kTextPlain);
    if (data?.text == null) return;
    final lines = data!.text!
        .split('\n')
        .map((l) => l.trim().replaceAll(RegExp(r'^[-*•◦▪▫]\s*'), ''))
        .where((l) => l.isNotEmpty)
        .toList();
    if (lines.isEmpty) return;

    if (lines.length == 1) {
      final ctrl = controllers[i];
      final sel = ctrl.selection;
      final start = sel.isValid ? sel.start : ctrl.text.length;
      final end = sel.isValid ? sel.end : ctrl.text.length;
      ctrl.value = TextEditingValue(
        text: ctrl.text.replaceRange(start, end, lines[0]),
        selection: TextSelection.collapsed(offset: start + lines[0].length),
      );
      return;
    }

    mutate(() {
      controllers[i].removeListener(emit);
      controllers[i].dispose();
      controllers[i] = _makeCtrl(lines[0]);
      for (int j = 1; j < lines.length; j++) {
        controllers.insert(i + j, _makeCtrl(lines[j]));
        levels.insert(i + j, levels[i]);
        checked.insert(i + j, false);
        focusNodes.insert(i + j, FocusNode());
      }
    });
    emit();
    WidgetsBinding.instance.addPostFrameCallback((_) {
      final last = i + lines.length - 1;
      if (last < focusNodes.length) focusNodes[last].requestFocus();
    });
  }

  void dispose() {
    for (final c in controllers) {
      c.dispose();
    }
    for (final f in focusNodes) {
      f.dispose();
    }
  }
}

class _BulletColumn extends StatefulWidget {
  final String label;
  final _BulletSet set;
  final VoidCallback emit;
  final TextEditingController headingController;
  final ListStyle listStyle;

  const _BulletColumn({
    required this.label,
    required this.set,
    required this.emit,
    required this.headingController,
    required this.listStyle,
  });

  @override
  State<_BulletColumn> createState() => _BulletColumnState();
}

class _BulletColumnState extends State<_BulletColumn> {
  _BulletSet get set => widget.set;

  @override
  Widget build(BuildContext context) {
    final l10n = context.l10n;
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        TextField(
          controller: widget.headingController,
          decoration: InputDecoration(
            labelText: l10n.d('Kop (optioneel)'),
            isDense: true,
          ),
        ),
        const SizedBox(height: 12),
        SectionLabel(widget.label),
        const SizedBox(height: 6),
        for (int i = 0; i < set.controllers.length; i++) _buildRow(i),
        const SizedBox(height: 4),
        TextButton.icon(
          onPressed: () =>
              set.addAfter((fn) => setState(fn), set.controllers.length - 1),
          icon: const Icon(Icons.add, size: 16),
          label: Text(l10n.d('Bullet toevoegen')),
        ),
      ],
    );
  }

  Widget _buildRow(int i) {
    final l10n = context.l10n;
    final level = set.levels[i];
    return Padding(
      key: ValueKey(set.controllers[i]),
      padding: EdgeInsets.only(left: level * 20.0, top: 4, bottom: 4),
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          if (widget.listStyle == ListStyle.checklist)
            SizedBox(
              width: 24,
              height: 24,
              child: Checkbox(
                key: ValueKey('checklist-item-${widget.label}-$i'),
                value: set.checked[i],
                onChanged: (value) {
                  setState(() => set.checked[i] = value ?? false);
                  widget.emit();
                },
                visualDensity: VisualDensity.compact,
              ),
            )
          else
            Text(
              _markerForItem(i),
              style: const TextStyle(fontSize: 16, color: Color(0xFF64748B)),
            ),
          const SizedBox(width: 8),
          Expanded(
            child: Focus(
              onKeyEvent: (_, event) {
                if (event is! KeyDownEvent) return KeyEventResult.ignored;
                if (event.logicalKey == LogicalKeyboardKey.enter) {
                  set.addAfter((fn) => setState(fn), i);
                  return KeyEventResult.handled;
                }
                if (event.logicalKey == LogicalKeyboardKey.backspace &&
                    set.controllers[i].text.isEmpty &&
                    set.controllers.length > 1) {
                  set.removeAndFocus((fn) => setState(fn), i);
                  return KeyEventResult.handled;
                }
                if (event.logicalKey == LogicalKeyboardKey.tab) {
                  if (HardwareKeyboard.instance.isShiftPressed) {
                    if (set.levels[i] > 0) setState(() => set.levels[i]--);
                  } else {
                    if (set.levels[i] < _BulletSet.maxLevel) {
                      setState(() => set.levels[i]++);
                    }
                  }
                  widget.emit();
                  return KeyEventResult.handled;
                }
                if (event.logicalKey == LogicalKeyboardKey.keyV &&
                    (HardwareKeyboard.instance.isMetaPressed ||
                        HardwareKeyboard.instance.isControlPressed)) {
                  set.paste((fn) => setState(fn), i);
                  return KeyEventResult.handled;
                }
                return KeyEventResult.ignored;
              },
              child: TextField(
                controller: set.controllers[i],
                focusNode: set.focusNodes[i],
                decoration: InputDecoration(
                  hintText: '${l10n.d('Bullet')} ${i + 1}',
                  isDense: true,
                ),
              ),
            ),
          ),
          IconButton(
            key: ValueKey('remove-bullet-${widget.label}-$i'),
            icon: const Icon(
              Icons.remove_circle_outline,
              size: 18,
              color: Color(0xFF64748B),
            ),
            onPressed: () => set.removeAndFocus((fn) => setState(fn), i),
            tooltip: l10n.d('Verwijder'),
            padding: const EdgeInsets.symmetric(horizontal: 4),
            constraints: const BoxConstraints(minWidth: 28),
          ),
        ],
      ),
    );
  }

  String _markerForLevel(int level) {
    const markers = ['•', '◦', '▪', '▫', '–'];
    return markers[level.clamp(0, markers.length - 1)];
  }

  String _markerForItem(int index) {
    if (widget.listStyle == ListStyle.bullets) {
      return _markerForLevel(set.levels[index]);
    }
    if (widget.listStyle == ListStyle.checklist) return '';
    final level = set.levels[index];
    var number = 0;
    for (var i = 0; i <= index; i++) {
      if (set.levels[i] == level) number++;
      if (set.levels[i] < level) number = 0;
    }
    return '$number.';
  }
}
