import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:logging/logging.dart';
import 'package:multi_trigger_autocomplete/multi_trigger_autocomplete.dart';
import 'package:provider/provider.dart';

import '../controls/autocomplete/hashtag_autocomplete_options.dart';
import '../controls/autocomplete/mention_autocomplete_options.dart';
import '../controls/image_control.dart';
import '../controls/padding.dart';
import '../globals.dart';
import '../models/connection.dart';
import '../models/filters/string_filter.dart';
import '../models/filters/timeline_entry_filter.dart';
import '../services/connections_manager.dart';
import '../services/timeline_entry_filter_service.dart';
import '../utils/active_profile_selector.dart';
import '../utils/snackbar_builder.dart';

class FilterEditorScreen extends StatefulWidget {
  final String id;

  const FilterEditorScreen({super.key, required this.id});

  @override
  State<FilterEditorScreen> createState() => _FilterEditorScreenState();
}

class _FilterEditorScreenState extends State<FilterEditorScreen> {
  static final _logger = Logger('$FilterEditorScreen');
  final nameController = TextEditingController();
  var action = TimelineEntryFilterAction.hide;
  final filteredAuthors = <Connection>[];
  final filteredDomains = <String>[];
  final filteredKeywords = <String>[];
  final filteredHashtags = <String>[];

  @override
  void initState() {
    super.initState();
    if (widget.id.isEmpty) {
      return;
    }
    final filter = getIt<ActiveProfileSelector<TimelineEntryFilterService>>()
        .activeEntry
        .andThen((tfs) => tfs.getForId(widget.id))
        .value;
    final cm =
        getIt<ActiveProfileSelector<ConnectionsManager>>().activeEntry.value;
    nameController.text = filter.name;
    action = filter.action;
    for (final f in filter.authorFilters) {
      cm.getById(f.filterString).withResult((c) => filteredAuthors.add(c));
    }
    filteredDomains.addAll(
      filter.domainFilters.map((f) => f.toLabel()),
    );

    filteredKeywords.addAll(
      filter.keywordFilters.map((f) => f.toLabel()),
    );

    filteredHashtags.addAll(
      filter.hashtagFilters.map((f) => f.toLabel()),
    );
  }

  @override
  Widget build(BuildContext context) {
    _logger.finest('Build for filter ${widget.id}');
    final fieldWidth = MediaQuery.of(context).size.width * 0.8;
    final service = context
        .watch<ActiveProfileSelector<TimelineEntryFilterService>>()
        .activeEntry
        .value;

    return Scaffold(
      appBar: AppBar(
        title: Text(widget.id.isEmpty ? 'New Filter' : 'Edit Filter'),
      ),
      body: SafeArea(
        child: Padding(
            padding: const EdgeInsets.all(8.0),
            child: SingleChildScrollView(
              child: Column(
                children: [
                  Row(
                    children: [
                      const HorizontalPadding(),
                      Expanded(
                        child: TextField(
                          controller: nameController,
                          decoration: InputDecoration(
                            labelText: 'Name of filter',
                            border: OutlineInputBorder(
                              borderSide: const BorderSide(),
                              borderRadius: BorderRadius.circular(5.0),
                            ),
                          ),
                        ),
                      ),
                    ],
                  ),
                  const VerticalPadding(),
                  const Text('Action:'),
                  DropdownMenu<TimelineEntryFilterAction>(
                      initialSelection: action,
                      onSelected: (value) => action = value!,
                      dropdownMenuEntries: TimelineEntryFilterAction.values
                          .map((a) =>
                              DropdownMenuEntry(value: a, label: a.toLabel()))
                          .toList()),
                  const VerticalPadding(),
                  const Text('Authors:'),
                  Container(
                    width: fieldWidth,
                    decoration: BoxDecoration(
                        borderRadius:
                            const BorderRadius.all(Radius.circular(5.0)),
                        border:
                            Border.all(color: Theme.of(context).dividerColor)),
                    child: Wrap(children: [
                      IconButton(
                        onPressed: () async {
                          final newConnection =
                              await promptForConnection(context);
                          if (!mounted) {
                            return;
                          }

                          if (newConnection == null) {
                            return;
                          }

                          if (filteredAuthors.contains(newConnection)) {
                            buildSnackbar(
                              context,
                              'Already filtering on ${newConnection.handle}',
                            );
                          }
                          setState(() {
                            filteredAuthors.add(newConnection);
                          });
                        },
                        icon: const Icon(Icons.add),
                      ),
                      ...filteredAuthors.map(
                        (a) => Padding(
                          padding: const EdgeInsets.all(4.0),
                          child: Card(
                            child: Padding(
                              padding: const EdgeInsets.only(left: 5.0),
                              child: Row(
                                  mainAxisSize: MainAxisSize.min,
                                  children: [
                                    ImageControl(
                                      imageUrl: a.avatarUrl.toString(),
                                      iconOverride: const Icon(Icons.person),
                                      width: 24.0,
                                    ),
                                    const HorizontalPadding(
                                      width: 2.0,
                                    ),
                                    Flexible(
                                      child: Text(
                                        '${a.name} (${a.handle})',
                                        softWrap: true,
                                        maxLines: 10,
                                      ),
                                    ),
                                    IconButton(
                                        tooltip: 'Delete',
                                        onPressed: () => setState(() {
                                              filteredAuthors.remove(a);
                                            }),
                                        icon: const Icon(Icons.cancel)),
                                  ]),
                            ),
                          ),
                        ),
                      )
                    ]),
                  ),
                  const VerticalPadding(),
                  const Text('Hashtags:'),
                  Container(
                    width: fieldWidth,
                    decoration: BoxDecoration(
                        borderRadius:
                            const BorderRadius.all(Radius.circular(5.0)),
                        border:
                            Border.all(color: Theme.of(context).dividerColor)),
                    child: Wrap(children: [
                      IconButton(
                        onPressed: () async {
                          final newValue = await promptForHashtag(context);
                          if (newValue == null || newValue.isEmpty) {
                            return;
                          }
                          setState(() {
                            filteredHashtags.add(newValue);
                          });
                        },
                        icon: const Icon(Icons.add),
                      ),
                      ...filteredHashtags.map(
                        (h) => Padding(
                          padding: const EdgeInsets.all(4.0),
                          child: Card(
                            child: Padding(
                              padding: const EdgeInsets.only(left: 5.0),
                              child: Row(
                                  mainAxisSize: MainAxisSize.min,
                                  children: [
                                    Flexible(
                                      child:
                                          Text(h, softWrap: true, maxLines: 10),
                                    ),
                                    IconButton(
                                        tooltip: 'Delete',
                                        onPressed: () => setState(() {
                                              filteredHashtags.remove(h);
                                            }),
                                        icon: const Icon(Icons.cancel)),
                                  ]),
                            ),
                          ),
                        ),
                      )
                    ]),
                  ),
                  const VerticalPadding(),
                  const Text('Keywords:'),
                  Container(
                    width: fieldWidth,
                    decoration: BoxDecoration(
                        borderRadius:
                            const BorderRadius.all(Radius.circular(5.0)),
                        border:
                            Border.all(color: Theme.of(context).dividerColor)),
                    child: Wrap(children: [
                      IconButton(
                        onPressed: () async {
                          final newValue = await promptForString(context);
                          if (newValue == null || newValue.isEmpty) {
                            return;
                          }
                          setState(() {
                            filteredKeywords.add(newValue);
                          });
                        },
                        icon: const Icon(Icons.add),
                      ),
                      ...filteredKeywords.map(
                        (k) => Padding(
                          padding: const EdgeInsets.all(4.0),
                          child: Card(
                            child: Padding(
                              padding: const EdgeInsets.only(left: 5.0),
                              child: Row(
                                  mainAxisSize: MainAxisSize.min,
                                  children: [
                                    Flexible(
                                      child:
                                          Text(k, softWrap: true, maxLines: 10),
                                    ),
                                    IconButton(
                                        tooltip: 'Delete',
                                        onPressed: () => setState(() {
                                              filteredKeywords.remove(k);
                                            }),
                                        icon: const Icon(Icons.cancel)),
                                  ]),
                            ),
                          ),
                        ),
                      )
                    ]),
                  ),
                  const VerticalPadding(),
                  const Text('Domains:'),
                  Container(
                    width: fieldWidth,
                    decoration: BoxDecoration(
                        borderRadius:
                            const BorderRadius.all(Radius.circular(5.0)),
                        border:
                            Border.all(color: Theme.of(context).dividerColor)),
                    child: Wrap(children: [
                      IconButton(
                        onPressed: () async {
                          final newValue = await promptForString(context);
                          if (newValue == null || newValue.isEmpty) {
                            return;
                          }
                          setState(() {
                            filteredDomains.add(newValue);
                          });
                        },
                        icon: const Icon(Icons.add),
                      ),
                      ...filteredDomains.map(
                        (d) => Padding(
                          padding: const EdgeInsets.all(4.0),
                          child: Card(
                            child: Padding(
                              padding: const EdgeInsets.only(left: 5.0),
                              child: Row(
                                  mainAxisSize: MainAxisSize.min,
                                  children: [
                                    Flexible(
                                      child:
                                          Text(d, softWrap: true, maxLines: 10),
                                    ),
                                    IconButton(
                                        tooltip: 'Delete',
                                        onPressed: () => setState(() {
                                              filteredDomains.remove(d);
                                            }),
                                        icon: const Icon(Icons.cancel)),
                                  ]),
                            ),
                          ),
                        ),
                      )
                    ]),
                  ),
                  const VerticalPadding(),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      ElevatedButton(
                          onPressed: () {
                            final update = TimelineEntryFilter.create(
                              id: widget.id.isNotEmpty ? widget.id : null,
                              action: action,
                              name: nameController.text,
                              enabled: true,
                              authors: filteredAuthors,
                              hashtags: filteredHashtags,
                              keywords: filteredKeywords,
                              domains: filteredDomains,
                            );
                            service.upsertFilter(update);
                            if (context.canPop()) {
                              context.pop();
                            }
                          },
                          child: Text(widget.id.isEmpty ? 'Add' : 'Update')),
                    ],
                  ),
                  const VerticalPadding(),
                ],
              ),
            )),
      ),
    );
  }

  Future<String?> promptForString(BuildContext context) async {
    return await showDialog(
        context: context,
        barrierDismissible: false,
        builder: (context) {
          final controller = TextEditingController();
          return AlertDialog(
            content: TextField(
              controller: controller,
              decoration: InputDecoration(
                labelText: 'Enter value',
                border: OutlineInputBorder(
                  borderSide: const BorderSide(),
                  borderRadius: BorderRadius.circular(5.0),
                ),
              ),
            ),
            actions: [
              ElevatedButton(
                onPressed: () => context.pop(controller.text),
                child: const Text('OK'),
              ),
              ElevatedButton(
                onPressed: () => context.pop(),
                child: const Text('Cancel'),
              ),
            ],
          );
        });
  }

  Future<Connection?> promptForConnection(BuildContext context) async {
    final focusNode = FocusNode();
    return await showDialog(
        context: context,
        barrierDismissible: false,
        builder: (dialogContext) {
          final controller = TextEditingController();
          return AlertDialog(
            content: MultiTriggerAutocomplete(
              textEditingController: controller,
              focusNode: focusNode,
              optionsAlignment: OptionsAlignment.top,
              autocompleteTriggers: [
                AutocompleteTrigger(
                  trigger: '@',
                  triggerOnlyAfterSpace: false,
                  optionsViewBuilder:
                      (ovbContext, autocompleteQuery, controller) {
                    return MentionAutocompleteOptions(
                      query: autocompleteQuery.query,
                      onMentionUserTap: (user) {
                        final autocomplete =
                            MultiTriggerAutocomplete.of(ovbContext);
                        return autocomplete
                            .acceptAutocompleteOption(user.handle);
                      },
                    );
                  },
                ),
              ],
              fieldViewBuilder: (fvbContext, controller, focusNode) =>
                  TextFormField(
                focusNode: focusNode,
                controller: controller,
                decoration: InputDecoration(
                  labelText: 'Author (@<user>@domain)',
                  alignLabelWithHint: true,
                  border: OutlineInputBorder(
                    borderSide: const BorderSide(),
                    borderRadius: BorderRadius.circular(5.0),
                  ),
                ),
              ),
            ),
            actions: [
              ElevatedButton(
                onPressed: () {
                  final rval =
                      getIt<ActiveProfileSelector<ConnectionsManager>>()
                          .activeEntry
                          .andThen((cm) {
                            var handle = controller.text.trim();
                            if (handle.startsWith('@')) {
                              handle = handle.substring(1);
                            }
                            return cm.getByHandle(handle);
                          })
                          .withError((error) => buildSnackbar(context,
                              "Error adding ${controller.text}: $error"))
                          .fold(onSuccess: (c) => c, onError: (_) => null);
                  dialogContext.pop(rval);
                },
                child: const Text('OK'),
              ),
              ElevatedButton(
                onPressed: () => context.pop(),
                child: const Text('Cancel'),
              ),
            ],
          );
        });
  }

  Future<String?> promptForHashtag(BuildContext context) async {
    final focusNode = FocusNode();
    return await showDialog(
        context: context,
        barrierDismissible: false,
        builder: (dialogContext) {
          final controller = TextEditingController();
          return AlertDialog(
            content: MultiTriggerAutocomplete(
              textEditingController: controller,
              focusNode: focusNode,
              optionsAlignment: OptionsAlignment.top,
              autocompleteTriggers: [
                AutocompleteTrigger(
                  trigger: '#',
                  triggerOnlyAfterSpace: false,
                  optionsViewBuilder:
                      (ovbContext, autocompleteQuery, controller) {
                    return HashtagAutocompleteOptions(
                      query: autocompleteQuery.query,
                      onHashtagTap: (hashtag) {
                        final autocomplete =
                            MultiTriggerAutocomplete.of(ovbContext);
                        return autocomplete.acceptAutocompleteOption(hashtag);
                      },
                    );
                  },
                ),
              ],
              fieldViewBuilder: (fvbContext, controller, focusNode) =>
                  TextFormField(
                focusNode: focusNode,
                controller: controller,
                decoration: InputDecoration(
                  labelText: 'Hashtag (#<hashtag>)',
                  alignLabelWithHint: true,
                  border: OutlineInputBorder(
                    borderSide: const BorderSide(),
                    borderRadius: BorderRadius.circular(5.0),
                  ),
                ),
              ),
            ),
            actions: [
              ElevatedButton(
                onPressed: () {
                  final rval = controller.text.trim();
                  if (rval.startsWith('#')) {
                    dialogContext.pop(rval.substring(1));
                  } else {
                    dialogContext.pop(rval);
                  }
                },
                child: const Text('OK'),
              ),
              ElevatedButton(
                onPressed: () => context.pop(),
                child: const Text('Cancel'),
              ),
            ],
          );
        });
  }
}

extension StringFilterLabel on StringFilter {
  String toLabel() {
    switch (type) {
      case ComparisonType.endsWithIgnoreCase:
        return '*$filterString';
      case ComparisonType.contains:
      case ComparisonType.containsIgnoreCase:
      case ComparisonType.equals:
      case ComparisonType.equalsIgnoreCase:
        return filterString;
    }
  }
}
