import 'package:flutter/material.dart';
import 'base_field.dart';
import '../../../shared/widgets/inputs/modern_text_field.dart';

class AutocompleteDropdownField extends BaseField {
  final String fieldKey;
  final String label;
  final String hint;
  final bool isRequired;
  final Future<List<Map<String, dynamic>>> Function() optionsLoader;
  final String valueKey;
  final String displayKey;

  AutocompleteDropdownField({
    required this.fieldKey,
    required this.label,
    required this.hint,
    required this.optionsLoader,
    required this.valueKey,
    required this.displayKey,
    this.isRequired = false,
  })  : assert(valueKey != ''),
        assert(displayKey != '');

  @override
  String? Function(String?)? get validator => (value) {
        if (isRequired && (value == null || value.isEmpty)) {
          return '$label is required';
        }
        return null;
      };

  @override
  Map<String, dynamic>? get customProperties => {
        'isAutocomplete': true,
        'valueKey': valueKey,
        'displayKey': displayKey,
      };

  @override
  Widget buildField({
    required TextEditingController controller,
    required ColorScheme colorScheme,
    VoidCallback? onChanged,
  }) {
    // We'll lazily set the UI label into the Autocomplete's textController once options load
    String initialLabel = '';

    return FutureBuilder<List<Map<String, dynamic>>>(
      future: optionsLoader(),
      builder: (context, snapshot) {
        final List<Map<String, dynamic>> options = snapshot.data ?? const [];

        // Resolve initial display label from stored id
        if (snapshot.connectionState == ConnectionState.done &&
            controller.text.isNotEmpty) {
          final match = options.firstWhere(
            (o) => (o[valueKey]?.toString() ?? '') == controller.text,
            orElse: () => const {},
          );
          initialLabel =
              match.isNotEmpty ? (match[displayKey]?.toString() ?? '') : '';
        }

        final Iterable<String> displayOptions = options
            .map((e) => e[displayKey])
            .where((e) => e != null)
            .map((e) => e.toString());

        return Autocomplete<String>(
          optionsBuilder: (TextEditingValue tev) {
            if (tev.text.isEmpty) return const Iterable<String>.empty();
            return displayOptions.where(
                (opt) => opt.toLowerCase().contains(tev.text.toLowerCase()));
          },
          onSelected: (String selection) {
            // set UI label and hidden id
            final match = options.firstWhere(
              (o) => (o[displayKey]?.toString() ?? '') == selection,
              orElse: () => const {},
            );
            final idStr =
                match.isNotEmpty ? (match[valueKey]?.toString() ?? '') : '';
            controller.text = idStr;
            onChanged?.call();
          },
          fieldViewBuilder:
              (context, textController, focusNode, onFieldSubmitted) {
            // Initialize UI text once options are available
            if (initialLabel.isNotEmpty && textController.text.isEmpty) {
              textController.text = initialLabel;
            }
            return ModernTextField(
              label: label,
              hint: hint,
              controller: textController,
              focusNode: focusNode,
              validator: (v) => validator?.call(controller.text),
              onChanged: (_) => onChanged?.call(),
              suffixIcon: textController.text.isNotEmpty
                  ? IconButton(
                      icon: const Icon(Icons.clear),
                      onPressed: () {
                        textController.clear();
                        controller.clear();
                        onChanged?.call();
                      },
                    )
                  : const Icon(Icons.search),
            );
          },
          optionsViewBuilder: (context, onSelected, optionsIt) {
            final optionsList = optionsIt.toList();
            return Align(
              alignment: Alignment.topLeft,
              child: Material(
                elevation: 6,
                color: colorScheme.surface,
                shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(12),
                  side:
                      BorderSide(color: colorScheme.outline.withOpacity(0.15)),
                ),
                child: ConstrainedBox(
                  constraints:
                      const BoxConstraints(maxHeight: 280, minWidth: 240),
                  child: optionsList.isEmpty
                      ? Padding(
                          padding: const EdgeInsets.all(16),
                          child: Row(
                            children: [
                              Icon(Icons.info_outline,
                                  color: colorScheme.onSurfaceVariant),
                              const SizedBox(width: 8),
                              Expanded(
                                child: Text(
                                  'No results',
                                  style: TextStyle(
                                      color: colorScheme.onSurfaceVariant),
                                ),
                              ),
                            ],
                          ),
                        )
                      : ListView.separated(
                          shrinkWrap: true,
                          padding: const EdgeInsets.symmetric(vertical: 8),
                          itemCount: optionsList.length,
                          separatorBuilder: (_, __) => Divider(
                              height: 1,
                              color: colorScheme.outline.withOpacity(0.08)),
                          itemBuilder: (context, index) {
                            final opt = optionsList[index];
                            return InkWell(
                              onTap: () => onSelected(opt),
                              child: Padding(
                                padding: const EdgeInsets.symmetric(
                                    horizontal: 12, vertical: 10),
                                child: _buildHighlightedText(
                                    opt, // current query text
                                    // Pull current query from the Autocomplete field's text
                                    // (not stored here directly, so we simply render opt)
                                    '',
                                    colorScheme),
                              ),
                            );
                          },
                        ),
                ),
              ),
            );
          },
        );
      },
    );
  }

  Widget _buildHighlightedText(
      String text, String query, ColorScheme colorScheme) {
    if (query.isEmpty)
      return Text(text, style: TextStyle(color: colorScheme.onSurface));
    final lowerText = text.toLowerCase();
    final lowerQuery = query.toLowerCase();
    final int start = lowerText.indexOf(lowerQuery);
    if (start < 0)
      return Text(text, style: TextStyle(color: colorScheme.onSurface));
    final int end = start + query.length;
    return RichText(
      text: TextSpan(
        children: [
          TextSpan(
              text: text.substring(0, start),
              style: TextStyle(color: colorScheme.onSurface)),
          TextSpan(
              text: text.substring(start, end),
              style: TextStyle(
                  color: colorScheme.primary, fontWeight: FontWeight.w600)),
          TextSpan(
              text: text.substring(end),
              style: TextStyle(color: colorScheme.onSurface)),
        ],
      ),
    );
  }
}
