import 'dart:async';

import 'package:flutter/material.dart';
import 'package:krow/core/presentation/widgets/ui_kit/_custom_popup_menu.dart';
import 'package:krow/core/presentation/widgets/ui_kit/kw_input.dart';
import 'package:krow/core/presentation/widgets/ui_kit/kw_popup_menu.dart';

@immutable
class KwSuggestionInput<R> extends StatefulWidget {
  final debounceDuration = const Duration(milliseconds: 400);

  final String? title;
  final String? hintText;
  final Iterable<R> items;
  final String Function(R item) itemToStringBuilder;
  final Function(R item) onSelected;
  final Function(String query) onQueryChanged;
  final String? initialText;
  final double horizontalPadding;
  final Color? backgroundColor;
  final Color? borderColor;

  const KwSuggestionInput({
    super.key,
    this.initialText,
    required this.hintText,
    required this.itemToStringBuilder,
    required this.items,
    required this.onSelected,
    required this.onQueryChanged,
    this.horizontalPadding = 0,
    this.backgroundColor,
    this.borderColor,
    this.title,
  });

  @override
  State<KwSuggestionInput<R>> createState() => _KwSuggestionInputState<R>();
}

class _KwSuggestionInputState<R> extends State<KwSuggestionInput<R>> {
  R? selectedItem;
  var dropdownController = CustomPopupMenuController();
  late TextEditingController _textController;
  late FocusNode _focusNode;

  Timer? _debounce;

  UniqueKey key = UniqueKey();

  @override
  void initState() {
    super.initState();
    _textController = TextEditingController(text: widget.initialText);
    _focusNode = FocusNode();
    _textController.addListener(_onTextChanged);
  }

  @override
  void dispose() {
    _textController.removeListener(_onTextChanged);
    _textController.dispose();
    _debounce?.cancel();
    dropdownController.dispose();
    _focusNode.dispose();
    super.dispose();
  }

  void _onTextChanged() {
    if (_debounce?.isActive ?? false) _debounce?.cancel();
    _debounce = Timer(widget.debounceDuration, () {
      if (selectedItem == null ||
          widget.itemToStringBuilder(selectedItem as R) !=
              _textController.text) {
        widget.onQueryChanged(_textController.text);
      }
    });
  }

  @override
  void didUpdateWidget(covariant KwSuggestionInput<R> oldWidget) {
    super.didUpdateWidget(oldWidget);

    if (oldWidget.initialText != widget.initialText) {
      _textController.text = widget.initialText!;
    }

    WidgetsBinding.instance.addPostFrameCallback(
      (_) {
        if (oldWidget.items != widget.items) {
          dropdownController.showMenu();
        } else {
          dropdownController.setState();
        }
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.stretch,
      children: [
        KwPopupMenu(
            controller: dropdownController,
            horizontalPadding: widget.horizontalPadding,
            fit: KwPopupMenuFit.expand,
            customButtonBuilder: (context, isOpened) {
              return _buildMenuButton(isOpened);
            },
            menuItems: widget.items
                .map((item) => KwPopupMenuItem(
                    title: widget.itemToStringBuilder(item),
                    onTap: () {
                      selectedItem = item;
                      _textController.text = widget.itemToStringBuilder(item);
                      dropdownController.hideMenu();
                      widget.onSelected(item);
                    }))
                .toList()),
      ],
    );
  }

  Widget _buildMenuButton(bool isOpened) {
    return KwTextInput(
      title: widget.title,
      hintText: widget.hintText,
      controller: _textController,
      focusNode: _focusNode,
    );
  }
}
