import 'package:PiliPlus/common/constants.dart';
import 'package:PiliPlus/common/widgets/button/icon_button.dart';
import 'package:PiliPlus/common/widgets/button/toolbar_icon_button.dart';
import 'package:PiliPlus/common/widgets/custom_icon.dart';
import 'package:PiliPlus/common/widgets/draggable_sheet/draggable_scrollable_sheet_dyn.dart'
    as dyn_sheet;
import 'package:PiliPlus/common/widgets/pair.dart';
import 'package:PiliPlus/common/widgets/text_field/controller.dart';
import 'package:PiliPlus/common/widgets/text_field/text_field.dart';
import 'package:PiliPlus/http/dynamics.dart';
import 'package:PiliPlus/models/common/publish_panel_type.dart';
import 'package:PiliPlus/models/common/reply/reply_option_type.dart';
import 'package:PiliPlus/models/dynamics/vote_model.dart';
import 'package:PiliPlus/models_new/dynamic/dyn_topic_top/topic_item.dart';
import 'package:PiliPlus/pages/common/publish/common_rich_text_pub_page.dart';
import 'package:PiliPlus/pages/dynamics_create_vote/view.dart';
import 'package:PiliPlus/pages/dynamics_mention/controller.dart';
import 'package:PiliPlus/pages/dynamics_select_topic/controller.dart';
import 'package:PiliPlus/pages/dynamics_select_topic/view.dart';
import 'package:PiliPlus/pages/emote/controller.dart';
import 'package:PiliPlus/pages/emote/view.dart';
import 'package:PiliPlus/utils/accounts.dart';
import 'package:PiliPlus/utils/date_util.dart';
import 'package:PiliPlus/utils/request_utils.dart';
import 'package:flutter/foundation.dart' show kDebugMode;
import 'package:flutter/material.dart' hide DraggableScrollableSheet;
import 'package:flutter/services.dart' show LengthLimitingTextInputFormatter;
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart';

class CreateDynPanel extends CommonRichTextPubPage {
  const CreateDynPanel({
    super.key,
    super.imageLengthLimit = 18,
    this.scrollController,
    this.topic,
  });

  final ScrollController? scrollController;
  final Pair<int, String>? topic;

  @override
  State<CreateDynPanel> createState() => _CreateDynPanelState();

  static void onCreateDyn(BuildContext context, {Pair<int, String>? topic}) =>
      showModalBottomSheet(
        context: context,
        useSafeArea: true,
        isScrollControlled: true,
        builder: (context) => dyn_sheet.DraggableScrollableSheet(
          snap: true,
          expand: false,
          initialChildSize: 1,
          minChildSize: 0,
          maxChildSize: 1,
          snapSizes: const [1],
          builder: (context, scrollController) => CreateDynPanel(
            scrollController: scrollController,
            topic: topic,
          ),
        ),
      );
}

class _CreateDynPanelState extends CommonRichTextPubPageState<CreateDynPanel> {
  final RxBool _isPrivate = false.obs;
  final Rx<DateTime?> _publishTime = Rx<DateTime?>(null);
  final Rx<ReplyOptionType> _replyOption = ReplyOptionType.allow.obs;
  final _titleEditCtr = TextEditingController();
  final Rx<Pair<int, String>?> topic = Rx<Pair<int, String>?>(null);

  @override
  void initState() {
    super.initState();
    topic.value = widget.topic;
  }

  @override
  void dispose() {
    _titleEditCtr.dispose();
    Get
      ..delete<EmotePanelController>()
      ..delete<SelectTopicController>()
      ..delete<DynMentionController>();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final ThemeData theme = Theme.of(context);
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        _buildAppBar(theme),
        Expanded(
          child: ListView(
            padding: EdgeInsets.zero,
            controller: widget.scrollController,
            physics: const ClampingScrollPhysics(),
            children: [
              Padding(
                padding: const EdgeInsets.symmetric(horizontal: 16),
                child: Obx(
                  () {
                    final hasTopic = topic.value != null;
                    return Row(
                      spacing: 10,
                      children: [
                        TextButton(
                          style: TextButton.styleFrom(
                            overlayColor: hasTopic ? Colors.transparent : null,
                            splashFactory:
                                hasTopic ? NoSplash.splashFactory : null,
                            shape: hasTopic
                                ? null
                                : RoundedRectangleBorder(
                                    side: BorderSide(
                                      color: hasTopic
                                          ? Colors.transparent
                                          : theme.colorScheme.outline
                                              .withValues(alpha: 0.2),
                                    ),
                                    borderRadius: const BorderRadius.all(
                                      Radius.circular(25),
                                    ),
                                  ),
                            minimumSize: Size.zero,
                            padding: hasTopic
                                ? const EdgeInsets.symmetric(vertical: 12)
                                : const EdgeInsets.all(12),
                            visualDensity: VisualDensity.compact,
                            tapTargetSize: MaterialTapTargetSize.shrinkWrap,
                          ),
                          onPressed: _onSelectTopic,
                          child: Text.rich(
                            TextSpan(
                              children: [
                                WidgetSpan(
                                  child: Padding(
                                    padding: const EdgeInsets.only(right: 5),
                                    child: Icon(
                                      CustomIcon.topic_tag,
                                      size: 18,
                                      color: hasTopic
                                          ? null
                                          : theme.colorScheme.outline,
                                    ),
                                  ),
                                ),
                                TextSpan(
                                  text: hasTopic ? topic.value!.second : '选择话题',
                                  style: TextStyle(
                                    color: hasTopic
                                        ? null
                                        : theme.colorScheme.outline,
                                  ),
                                ),
                              ],
                            ),
                          ),
                        ),
                        if (hasTopic)
                          iconButton(
                            size: 22,
                            iconSize: 16,
                            context: context,
                            icon: Icons.clear,
                            bgColor: theme.colorScheme.onInverseSurface,
                            iconColor: theme.colorScheme.onSurfaceVariant,
                            onPressed: () => topic.value = null,
                          ),
                      ],
                    );
                  },
                ),
              ),
              const SizedBox(height: 5),
              Padding(
                padding: const EdgeInsets.symmetric(horizontal: 16),
                child: TextField(
                  controller: _titleEditCtr,
                  style: const TextStyle(fontWeight: FontWeight.bold),
                  decoration: InputDecoration(
                    hintText: '标题，选填20字',
                    isDense: true,
                    contentPadding: EdgeInsets.zero,
                    border: const OutlineInputBorder(
                      gapPadding: 0,
                      borderSide: BorderSide.none,
                    ),
                    hintStyle: TextStyle(
                      fontWeight: FontWeight.bold,
                      color: theme.colorScheme.outline.withValues(alpha: 0.7),
                    ),
                  ),
                  inputFormatters: [LengthLimitingTextInputFormatter(20)],
                ),
              ),
              const SizedBox(height: 5),
              Padding(
                padding: const EdgeInsets.symmetric(horizontal: 16),
                child: _buildEditWidget(theme),
              ),
              const SizedBox(height: 16),
              Padding(
                padding: const EdgeInsets.symmetric(horizontal: 16),
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: [
                    Obx(() => _buildPubtimeWidget),
                    Column(
                      mainAxisSize: MainAxisSize.min,
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Obx(() => _buildReplyOptionWidget(theme)),
                        const SizedBox(height: 5),
                        Obx(() => _buildPrivateWidget(theme)),
                      ],
                    ),
                  ],
                ),
              ),
              const SizedBox(height: 10),
              _buildImageList(theme),
            ],
          ),
        ),
        _buildToolbar,
        buildPanelContainer(Colors.transparent),
      ],
    );
  }

  Widget _buildImageList(ThemeData theme) => SizedBox(
        height: 100,
        width: double.infinity,
        child: SingleChildScrollView(
          scrollDirection: Axis.horizontal,
          padding: const EdgeInsets.symmetric(horizontal: 16),
          child: Obx(
            () => Row(
              spacing: 10,
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                ...List.generate(
                    pathList.length, (index) => buildImage(index, 100)),
                if (pathList.length != limit)
                  Builder(
                    builder: (context) {
                      const borderRadius = StyleString.mdRadius;
                      return Material(
                        borderRadius: borderRadius,
                        child: InkWell(
                          borderRadius: borderRadius,
                          onTap: () => onPickImage(() {
                            if (pathList.isNotEmpty && !enablePublish.value) {
                              enablePublish.value = true;
                            }
                          }),
                          child: Ink(
                            width: 100,
                            height: 100,
                            decoration: BoxDecoration(
                              borderRadius: borderRadius,
                              color: theme.colorScheme.secondaryContainer,
                            ),
                            child:
                                const Center(child: Icon(Icons.add, size: 35)),
                          ),
                        ),
                      );
                    },
                  ),
              ],
            ),
          ),
        ),
      );

  PreferredSizeWidget _buildAppBar(ThemeData theme) => PreferredSize(
        preferredSize: const Size.fromHeight(66),
        child: Padding(
          padding: const EdgeInsets.all(16),
          child: Stack(
            clipBehavior: Clip.none,
            alignment: Alignment.center,
            children: [
              Align(
                alignment: Alignment.centerLeft,
                child: SizedBox(
                  width: 34,
                  height: 34,
                  child: IconButton(
                    tooltip: '返回',
                    style: ButtonStyle(
                      padding: WidgetStateProperty.all(EdgeInsets.zero),
                      backgroundColor: WidgetStateProperty.resolveWith(
                        (states) {
                          return theme.colorScheme.secondaryContainer;
                        },
                      ),
                    ),
                    onPressed: Get.back,
                    icon: Icon(
                      Icons.arrow_back_outlined,
                      size: 18,
                      color: theme.colorScheme.onSecondaryContainer,
                    ),
                  ),
                ),
              ),
              const Center(
                child: Text(
                  '发布动态',
                  style: TextStyle(fontSize: 15, fontWeight: FontWeight.bold),
                ),
              ),
              Align(
                alignment: Alignment.centerRight,
                child: Obx(
                  () => FilledButton.tonal(
                    onPressed: enablePublish.value ? onPublish : null,
                    style: FilledButton.styleFrom(
                      tapTargetSize: MaterialTapTargetSize.shrinkWrap,
                      padding: const EdgeInsets.symmetric(
                        horizontal: 20,
                        vertical: 10,
                      ),
                      visualDensity: VisualDensity.compact,
                    ),
                    child: Text(_publishTime.value == null ? '发布' : '定时发布'),
                  ),
                ),
              ),
            ],
          ),
        ),
      );

  Widget _buildPrivateWidget(ThemeData theme) {
    final color = _isPrivate.value
        ? theme.colorScheme.error
        : theme.colorScheme.secondary;
    return PopupMenuButton<bool>(
      requestFocus: false,
      initialValue: _isPrivate.value,
      onSelected: (value) => _isPrivate.value = value,
      itemBuilder: (context) => List.generate(
        2,
        (index) => PopupMenuItem<bool>(
          enabled: _publishTime.value != null && index == 1 ? false : true,
          value: index == 0 ? false : true,
          child: Row(
            mainAxisSize: MainAxisSize.min,
            children: [
              Icon(
                size: 19,
                index == 0 ? Icons.visibility : Icons.visibility_off,
              ),
              const SizedBox(width: 4),
              Text(index == 0 ? '所有人可见' : '仅自己可见'),
            ],
          ),
        ),
      ),
      child: Padding(
        padding: const EdgeInsets.symmetric(vertical: 2),
        child: Row(
          mainAxisSize: MainAxisSize.min,
          children: [
            Icon(
              size: 19,
              _isPrivate.value ? Icons.visibility_off : Icons.visibility,
              color: color,
            ),
            const SizedBox(width: 4),
            Text(
              _isPrivate.value ? '仅自己可见' : '所有人可见',
              style: TextStyle(
                height: 1,
                color: color,
              ),
              strutStyle: const StrutStyle(leading: 0, height: 1),
            ),
            Icon(
              size: 20,
              Icons.keyboard_arrow_right,
              color: color,
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildReplyOptionWidget(ThemeData theme) {
    final color = _replyOption.value == ReplyOptionType.close
        ? theme.colorScheme.error
        : theme.colorScheme.secondary;
    return PopupMenuButton<ReplyOptionType>(
      requestFocus: false,
      initialValue: _replyOption.value,
      onSelected: (item) => _replyOption.value = item,
      itemBuilder: (context) => ReplyOptionType.values
          .map(
            (item) => PopupMenuItem<ReplyOptionType>(
              value: item,
              child: Row(
                mainAxisSize: MainAxisSize.min,
                children: [
                  Icon(
                    size: 19,
                    item.iconData,
                  ),
                  const SizedBox(width: 4),
                  Text(item.title),
                ],
              ),
            ),
          )
          .toList(),
      child: Padding(
        padding: const EdgeInsets.symmetric(vertical: 2),
        child: Row(
          mainAxisSize: MainAxisSize.min,
          children: [
            Icon(
              size: 19,
              _replyOption.value.iconData,
              color: color,
            ),
            const SizedBox(width: 4),
            Text(
              _replyOption.value.title,
              style: TextStyle(
                height: 1,
                color: color,
              ),
              strutStyle: const StrutStyle(leading: 0, height: 1),
            ),
            Icon(
              size: 20,
              Icons.keyboard_arrow_right,
              color: color,
            ),
          ],
        ),
      ),
    );
  }

  Widget get _buildPubtimeWidget => _publishTime.value == null
      ? FilledButton.tonal(
          style: FilledButton.styleFrom(
            padding: const EdgeInsets.symmetric(
              horizontal: 16,
              vertical: 10,
            ),
            visualDensity: VisualDensity.compact,
          ),
          onPressed: _isPrivate.value
              ? null
              : () {
                  DateTime nowDate = DateTime.now();
                  showDatePicker(
                    context: context,
                    initialDate: nowDate,
                    firstDate: nowDate,
                    lastDate: DateTime(
                      nowDate.year,
                      nowDate.month,
                      nowDate.day + 7,
                    ),
                  ).then(
                    (selectedDate) {
                      if (selectedDate != null && mounted) {
                        TimeOfDay nowTime = TimeOfDay.now();
                        showTimePicker(
                          context: context,
                          initialTime: nowTime.replacing(
                            hour: nowTime.minute + 6 >= 60
                                ? (nowTime.hour + 1) % 24
                                : nowTime.hour,
                            minute: (nowTime.minute + 6) % 60,
                          ),
                        ).then((selectedTime) {
                          if (selectedTime != null) {
                            if (selectedDate.day == nowDate.day) {
                              if (selectedTime.hour < nowTime.hour) {
                                SmartDialog.showToast('时间设置错误，至少选择6分钟之后');
                                return;
                              } else if (selectedTime.hour == nowTime.hour) {
                                if (selectedTime.minute < nowTime.minute + 6) {
                                  if (selectedDate.day == nowDate.day) {
                                    SmartDialog.showToast('时间设置错误，至少选择6分钟之后');
                                  }
                                  return;
                                }
                              }
                            }
                            _publishTime.value = DateTime(
                              selectedDate.year,
                              selectedDate.month,
                              selectedDate.day,
                              selectedTime.hour,
                              selectedTime.minute,
                            );
                          }
                        });
                      }
                    },
                  );
                },
          child: const Text('定时发布'),
        )
      : OutlinedButton.icon(
          style: OutlinedButton.styleFrom(
            padding: const EdgeInsets.symmetric(
              horizontal: 16,
              vertical: 10,
            ),
            visualDensity: VisualDensity.compact,
          ),
          onPressed: () => _publishTime.value = null,
          label: Text(DateUtil.longFormatD.format(_publishTime.value!)),
          icon: const Icon(Icons.clear, size: 20),
          iconAlignment: IconAlignment.end,
        );

  Widget get _buildToolbar => Padding(
        padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
        child: Row(
          spacing: 16,
          children: [
            Obx(
              () => ToolbarIconButton(
                onPressed: () => updatePanelType(
                  panelType.value == PanelType.emoji
                      ? PanelType.keyboard
                      : PanelType.emoji,
                ),
                icon: const Icon(Icons.emoji_emotions, size: 22),
                tooltip: '表情',
                selected: panelType.value == PanelType.emoji,
              ),
            ),
            ToolbarIconButton(
              onPressed: () => onMention(true),
              icon: const Icon(Icons.alternate_email, size: 22),
              tooltip: '@',
              selected: false,
            ),
            ToolbarIconButton(
              onPressed: () async {
                controller.keepChatPanel();
                RichTextItem? voteItem = editController.items
                    .firstWhereOrNull((e) => e.type == RichTextType.vote);
                VoteInfo? voteInfo = await Navigator.of(context).push(
                  GetPageRoute(
                      page: () => CreateVotePage(
                          voteId: voteItem?.id == null
                              ? null
                              : int.parse(voteItem!.id!))),
                );
                if (voteInfo != null) {
                  if (voteItem != null) {
                    final range = voteItem.range;
                    final text = ' ${voteInfo.title} ';
                    final selection = TextSelection.collapsed(
                        offset: range.start + text.length);
                    final delta = RichTextEditingDeltaReplacement(
                      oldText: editController.text,
                      replacementText: text,
                      replacedRange: range,
                      selection: selection,
                      composing: TextRange.empty,
                      type: RichTextType.vote,
                      id: voteInfo.voteId.toString(),
                      rawText: voteInfo.title,
                    );
                    final newValue = delta.apply(editController.value);
                    editController
                      ..syncRichText(delta)
                      ..value = newValue;
                  } else {
                    onInsertText(
                      '我发起了一个投票',
                      RichTextType.text,
                    );
                    onInsertText(
                      ' ${voteInfo.title} ',
                      RichTextType.vote,
                      rawText: voteInfo.title,
                      id: voteInfo.voteId.toString(),
                    );
                  }
                }
                controller.restoreChatPanel();
              },
              icon: const Icon(Icons.bar_chart_rounded, size: 22),
              tooltip: '投票',
              selected: false,
            ),
            // if (kDebugMode)
            //   ToolbarIconButton(
            //     onPressed: editController.clear,
            //     icon: const Icon(Icons.clear, size: 22),
            //     selected: false,
            //   ),
          ],
        ),
      );

  Widget _buildEditWidget(ThemeData theme) => Form(
        autovalidateMode: AutovalidateMode.onUserInteraction,
        child: Listener(
          onPointerUp: (event) {
            if (readOnly.value) {
              updatePanelType(PanelType.keyboard);
            }
          },
          child: Obx(
            () => RichTextField(
              key: key,
              controller: editController,
              minLines: 4,
              maxLines: null,
              focusNode: focusNode,
              readOnly: readOnly.value,
              onChanged: onChanged,
              decoration: InputDecoration(
                hintText: '说点什么吧',
                hintStyle: TextStyle(color: theme.colorScheme.outline),
                border: const OutlineInputBorder(
                  borderSide: BorderSide.none,
                  gapPadding: 0,
                ),
                contentPadding: EdgeInsets.zero,
              ),
              // inputFormatters: [LengthLimitingTextInputFormatter(1000)],
            ),
          ),
        ),
      );

  @override
  Widget? get customPanel => EmotePanel(onChoose: onChooseEmote);

  @override
  Future<void> onCustomPublish({List? pictures}) async {
    SmartDialog.showLoading(msg: '正在发布');
    List<Map<String, dynamic>>? extraContent = getRichContent();
    final hasRichText = extraContent != null;
    var result = await DynamicsHttp.createDynamic(
      mid: Accounts.main.mid,
      rawText: hasRichText ? null : editController.text,
      pics: pictures,
      publishTime: _publishTime.value != null
          ? _publishTime.value!.millisecondsSinceEpoch ~/ 1000
          : null,
      replyOption: _replyOption.value,
      privatePub: _isPrivate.value ? 1 : null,
      title: _titleEditCtr.text,
      topic: topic.value,
      extraContent: extraContent,
    );
    SmartDialog.dismiss();
    if (result['status']) {
      hasPub = true;
      Get.back();
      SmartDialog.showToast('发布成功');
      var id = result['data']?['dyn_id'];
      RequestUtils.insertCreatedDyn(id);
      RequestUtils.checkCreatedDyn(
        id: id,
        dynText: editController.rawText,
      );
    } else {
      SmartDialog.showToast(result['msg']);
      if (kDebugMode) debugPrint('failed to publish: ${result['msg']}');
    }
  }

  double _topicOffset = 0;
  void _onSelectTopic() {
    SelectTopicPanel.onSelectTopic(
      context,
      offset: _topicOffset,
      callback: (offset) => _topicOffset = offset,
    ).then((TopicItem? res) {
      if (res != null) {
        topic.value = Pair(first: res.id, second: res.name);
      }
    });
  }

  @override
  void onSave() {}
}
