/// 聊天模板
library;

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'package:loopin/IM/controller/chat_controller.dart';
import 'package:loopin/IM/controller/chat_detail_controller.dart';
import 'package:loopin/IM/im_message.dart';
import 'package:loopin/IM/im_service.dart';
import 'package:shirne_dialog/shirne_dialog.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message.dart';

import '../../behavior/custom_scroll_behavior.dart';
import '../../components/image_group.dart';
import '../../styles/index.dart';
import '../../utils/index.dart';
import './components/redpacket.dart';
import './components/richtext.dart';
// import 'mock/chat_json.dart';
import 'mock/emoj_json.dart';

class ChatGroup extends StatefulWidget {
  const ChatGroup({super.key});

  @override
  State<ChatGroup> createState() => _ChatState();
}

class _ChatState extends State<ChatGroup> with SingleTickerProviderStateMixin {
  late final ChatDetailController controller;
  // 接收参数
  // Rx<V2TimConversation> arguments = Get.arguments.obs;
  late final Rx<V2TimConversation> arguments;

  late String selfUserId;

  // 聊天消息模块
  final bool isNeedScrollBottom = true;

  // final RxList<V2TimMessage> chatList = <V2TimMessage>[].obs;

  bool isLoading = false; // 是否在加载中
  bool hasMore = true; // 是否还有更多数据
  bool _throttleFlag = false; // 滚动节流锁

  // 表情json
  List emoJson = emotionData;

  // 底部操作栏模块
  TextEditingController editorController = TextEditingController();
  FocusNode editorFocusNode = FocusNode();
  bool voiceBtnEnable = false; // 语音按钮
  bool voicePanelEnable = false; // 语音操作面板
  bool voiceToTransfer = false; // 语音转文字中
  int voiceType = 0; // 语音操作类型
  Map voiceTypeMap = {
    0: '按住 说话', // 按住说话
    1: '松开 发送', // 松开发送
    2: '松开 取消', // 松开取消(左滑)
    3: '语音转文字', // 语音转文字(右滑)
  };
  bool toolbarEnable = false; // 显示表情/选择区域
  int toolbarIndex = 0; // 0 表情 1 选择
  double keyboardHeight = 157.6; // 键盘高度
  List chooseOptions = [
    {'key': 'photo', 'name': '相册', 'icon': 'assets/images/icon_photo.webp'},
    {'key': 'camera', 'name': '拍摄', 'icon': 'assets/images/icon_camera.webp'},
    {'key': 'location', 'name': '位置', 'icon': 'assets/images/icon_location.webp'},
    {'key': 'redpacket', 'name': '红包', 'icon': 'assets/images/icon_hb.webp'},
  ];

  // controller监听
  ScrollController chatController = ScrollController();
  ScrollController emojController = ScrollController();

  // 模拟开红包按钮动画
  late AnimationController animController;

  // 创建一个从 0 到 π 的旋转动画
  late Animation<double> animTurns;

  // 初始化状态
  @override
  void initState() {
    super.initState();
    final arg = Get.arguments as V2TimConversation;
    arguments = arg.obs;

    controller = Get.put(ChatDetailController(userID: arguments.value.userID ?? ''));

    animController = AnimationController(
      vsync: this,
      duration: Duration(milliseconds: 500),
    );
    animTurns = Tween<double>(begin: 0, end: 3.1415926).animate(animController);

    cleanUnRead();

    getUserId();

    getMsgData(initFlag: true);

    // 编辑框获取焦点
    editorFocusNode.addListener(() {
      if (editorFocusNode.hasFocus) {
        setState(() {
          toolbarEnable = false;
        });
        scrollToBottom();
      }
    });
    // 滚动监听
    chatController.addListener(() {
      if (_throttleFlag) return;
      if (chatController.position.pixels >= chatController.position.maxScrollExtent - 50) {
        _throttleFlag = true;
        getMsgData().then((_) {
          // 解锁
          Future.delayed(Duration(milliseconds: 300), () {
            _throttleFlag = false;
          });
        });
      }
    });
  }

  @override
  void dispose() {
    if (Get.isRegistered<ChatDetailController>()) {
      Get.delete<ChatDetailController>();
    }
    // 更新会话列表数据
    Get.find<ChatController>().getConversationList();
    chatController.dispose();
    emojController.dispose();
    editorFocusNode.dispose();
    animController.dispose();
    super.dispose();
  }

  // 设置好友备注
  void setRemark() async {
    String remark = '';
    await MyDialog.confirm(
      Column(
        mainAxisSize: MainAxisSize.min,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          const SizedBox(height: 8),
          TextField(
            onChanged: (value) => remark = value,
            maxLength: 16,
            maxLengthEnforcement: MaxLengthEnforcement.enforced, // 强制不能输入超过
            decoration: InputDecoration(
              hintText: '请输入备注',
              filled: true,
              fillColor: const Color(0xFFF5F5F5),
              contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 14),
              enabledBorder: OutlineInputBorder(
                borderRadius: BorderRadius.circular(8),
                borderSide: BorderSide.none,
              ),
              focusedBorder: OutlineInputBorder(
                borderRadius: BorderRadius.circular(8),
                borderSide: BorderSide(color: Color(0xFFBE4EFF), width: 1),
              ),
            ),
          )
        ],
      ),
      title: '设置备注',
      buttonText: '确认',
      cancelText: '取消',
      onConfirm: () async {
        // print('备注为：$remark');
        final res = await ImService.instance.setFriendInfo(userID: arguments.value.userID!, friendRemark: remark);
        if (res.success) {
          // 刷新会话列表数据
          // Get.find<ChatController>().getConversationList();
          arguments.update((val) {
            val?.showName = remark;
          });
        } else {
          print(res.desc);
          print(arguments.value.userID);
          MyDialog.toast(res.desc, icon: Icon(Icons.warning), style: ToastStyle(backgroundColor: Colors.red.withAlpha(200)));
        }
        return true;
      },
    );
  }

  void cleanUnRead() async {
    if ((arguments.value.unreadCount ?? 0) > 0) {
      final res = await ImService.instance.clearConversationUnreadCount(conversationID: arguments.value.conversationID);
      if (!res.success) {
        MyDialog.toast(res.desc, icon: Icon(Icons.warning), style: ToastStyle(backgroundColor: Colors.red.withAlpha(200)));
      }
    }
  }

  void getUserId() async {
    final idRes = await ImService.instance.selfUserId();
    if (idRes.success) {
      selfUserId = idRes.data;
    }
  }

  Future<void> getMsgData({bool initFlag = false}) async {
    if (isLoading || !hasMore) return; // 正在加载 or 没有更多了

    isLoading = true;

    // 获取最旧一条消息作为游标
    V2TimMessage? lastRealMsg;
    for (var msg in controller.chatList.reversed) {
      if (msg.localCustomData != 'time_label') {
        lastRealMsg = msg;
        break;
      }
    }
    final lastMsg = lastRealMsg ?? arguments.value.lastMessage; // 如果找不到，就用传入的参数

    // final lastMsg = controller.chatList.isNotEmpty ? controller.chatList.last : arguments.lastMessage;

    final res = await ImService.instance.getHistoryMessageList(
      userID: arguments.value.userID,
      lastMsg: lastMsg,
    );

    if (res.success) {
      final newMessages = res.data ?? [];

      if (newMessages.isEmpty) {
        hasMore = false;
        MyDialog.toast('没有更多了~', icon: Icon(Icons.warning), style: ToastStyle(backgroundColor: Colors.red.withAlpha(200)));
      } else {
        if (initFlag) {
          newMessages.insert(0, lastMsg!);
        }
        controller.updateChatListWithTimeLabels(newMessages);
        print('聊天数据加载成功');
      }
    } else {
      MyDialog.toast("获取聊天记录失败：${res.desc}", icon: Icon(Icons.warning), style: ToastStyle(backgroundColor: Colors.red.withAlpha(200)));
    }

    isLoading = false;
  }

  // 渲染聊天消息
  List<Widget> renderChatList() {
    List<Widget> msgtpl = [];
    for (var item in controller.chatList) {
      // 时间提示，公告提示
      if (item.localCustomData == 'time_label') {
        msgtpl.add(Container(
          margin: const EdgeInsets.only(bottom: 15.0),
          child: Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text(
                item.customElem!.data ?? '',
                style: TextStyle(color: Colors.grey[600], fontSize: 12.0),
              ),
            ],
          ),
        ));
      }
      // 文本消息模板
      else if (item.elemType == 1) {
        msgtpl.add(RenderChatItem(
          data: item,
          child: Ink(
            decoration: BoxDecoration(
              color: !(item.isSelf ?? false) ? Color(0xFFFFFFFF) : Color(0xFF89E45B),
              borderRadius: BorderRadius.circular(10.0),
            ),
            child: InkWell(
              overlayColor: WidgetStateProperty.all(Colors.transparent),
              borderRadius: BorderRadius.circular(10.0),
              child: Container(
                padding: const EdgeInsets.all(10.0),
                child: RichTextUtil.getRichText(item.textElem?.text ?? '', color: !(item.isSelf ?? false) ? Colors.black : Colors.white), // 可自定义解析emoj/网址/电话
              ),
              onLongPress: () {
                contextMenuDialog();
              },
            ),
          ),
        ));
      }
      // gif表情模板
      else if (item.elemType == 4) {
        msgtpl.add(RenderChatItem(
          data: item,
          child: Ink(
            child: InkWell(
              overlayColor: WidgetStateProperty.all(Colors.transparent),
              child: Container(
                constraints: const BoxConstraints(
                  maxHeight: 100.0,
                  maxWidth: 100.0,
                ),
                child: Image.asset('assets/images/emotion/${item.customElem?.data}'),
              ),
              onLongPress: () {
                contextMenuDialog();
              },
            ),
          ),
        ));
      }
      // 图片模板
      else if (item.elemType == 5) {
        List<String> imagePaths = item.imageElem?.imageList?.where((e) => e != null && e.url != null).map((e) => e!.url!).toList() ?? [];
        msgtpl.add(RenderChatItem(
          data: item,
          child: Ink(
            child: InkWell(
              overlayColor: WidgetStateProperty.all(Colors.transparent),
              child: ClipRRect(
                borderRadius: BorderRadius.circular(10.0),
                child: ImageGroup(
                  images: imagePaths,
                  width: 120,
                ),
              ),
              onLongPress: () {
                contextMenuDialog();
              },
            ),
          ),
        ));
      }
      // 视频模板
      else if (item.elemType == 6) {
        msgtpl.add(RenderChatItem(
          data: item,
          child: Ink(
            child: InkWell(
              overlayColor: WidgetStateProperty.all(Colors.transparent),
              child: SizedBox(
                width: 90.0,
                child: Stack(
                  alignment: Alignment.center,
                  children: [
                    ClipRRect(
                      borderRadius: BorderRadius.circular(10.0),
                      child: Image.network(
                        item.videoElem?.videoUrl ?? '',
                      ),
                    ),
                    const Align(
                      alignment: Alignment.center,
                      child: Icon(
                        Icons.play_circle,
                        color: Colors.white,
                        size: 30.0,
                      ),
                    ),
                  ],
                ),
              ),
              onTap: () {
                MyDialog.toast('该功能暂未支持~', icon: Icon(Icons.warning), style: ToastStyle(backgroundColor: Colors.red.withAlpha(200)));
              },
              onLongPress: () {
                contextMenuDialog();
              },
            ),
          ),
        ));
      }
      // 语音模板
      else if (item.elemType == 7) {
        List<Widget> audiobody = [
          Ink(
            decoration: BoxDecoration(
              color: !(item.isSelf ?? false) ? const Color(0xFFFFFFFF) : const Color(0xFF89E45B),
              borderRadius: BorderRadius.circular(10.0),
            ),
            child: InkWell(
              overlayColor: WidgetStateProperty.all(Colors.transparent),
              borderRadius: BorderRadius.circular(10.0),
              child: Container(
                padding: const EdgeInsets.all(10.0),
                constraints: BoxConstraints(
                  // maxWidth: 120.0,
                  maxWidth: (item.soundElem?.duration)! / 60 * 230,
                ),
                child: Row(
                  mainAxisAlignment: !(item.isSelf ?? false) ? MainAxisAlignment.start : MainAxisAlignment.end,
                  children: !(item.isSelf ?? false)
                      ? [
                          const Icon(Icons.multitrack_audio),
                          const SizedBox(
                            width: 5.0,
                          ),
                          Text('${item.soundElem?.duration}'),
                        ]
                      : [
                          Text('${item.soundElem?.duration}'),
                          const SizedBox(
                            width: 5.0,
                          ),
                          const Icon(Icons.multitrack_audio),
                        ],
                ),
              ),
              onTap: () {
                MyDialog.toast('该功能暂未支持~', icon: Icon(Icons.warning), style: ToastStyle(backgroundColor: Colors.red.withAlpha(200)));
              },
              onLongPress: () {
                contextMenuDialog();
              },
            ),
          ),
          const SizedBox(
            width: 5.0,
          ),
          FStyle.badge(0, isdot: true),
        ];

        if (item.isSelf ?? false) {
          // 内容反转
          audiobody = audiobody.reversed.toList();
        } else {
          audiobody = audiobody;
        }

        msgtpl.add(RenderChatItem(
            data: item,
            child: Row(
              mainAxisAlignment: !(item.isSelf ?? false) ? MainAxisAlignment.start : MainAxisAlignment.end,
              children: audiobody,
            )));
      }
      // 红包模板
      else if (item.elemType == 0 && item.customElem?.desc == 'hongbao') {
        msgtpl.add(RenderChatItem(
          data: item,
          child: Ink(
            decoration: BoxDecoration(
              color: const Color(0xFFFF7F43),
              borderRadius: BorderRadius.circular(10.0),
            ),
            child: InkWell(
              overlayColor: WidgetStateProperty.all(Colors.transparent),
              borderRadius: BorderRadius.circular(10.0),
              child: Container(
                constraints: const BoxConstraints(
                  maxWidth: 210.0,
                ),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Container(
                      padding: const EdgeInsets.all(10.0),
                      child: Row(
                        spacing: 10.0,
                        children: <Widget>[
                          Image.asset(
                            'assets/images/hbico.png',
                            width: 32.0,
                            fit: BoxFit.contain,
                          ),
                          Text(item.customElem?.data ?? '', style: const TextStyle(color: Colors.white, fontSize: 14.0)),
                        ],
                      ),
                    ),
                    Container(
                      margin: const EdgeInsets.symmetric(horizontal: 10.0),
                      padding: const EdgeInsets.symmetric(vertical: 5.0),
                      width: double.infinity,
                      decoration: const BoxDecoration(border: Border(top: BorderSide(color: Colors.white30, width: .5))),
                      child: const Text(
                        '拼手气红包',
                        style: TextStyle(color: Colors.white70, fontSize: 11.0),
                      ),
                    ),
                  ],
                ),
              ),
              onTap: () {
                receiveRedPacketDialog(item);
              },
              onLongPress: () {
                contextMenuDialog();
              },
            ),
          ),
        ));
      }
      // 位置模板
      else if (item.elemType == 9) {
        msgtpl.add(RenderChatItem(
          data: item,
          child: Ink(
            decoration: BoxDecoration(
              color: const Color(0xFFFFFFFF),
              borderRadius: BorderRadius.circular(10.0),
            ),
            child: InkWell(
              // splashColor: Colors.transparent,
              overlayColor: WidgetStateProperty.all(Colors.transparent),
              borderRadius: BorderRadius.circular(10.0),
              child: Container(
                constraints: const BoxConstraints(
                  maxWidth: 210.0,
                ),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Container(
                      padding: const EdgeInsets.symmetric(
                        horizontal: 10.0,
                        vertical: 5.0,
                      ),
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: <Widget>[
                          Text(
                            item.locationElem?.desc ?? '位置信息异常',
                            overflow: TextOverflow.ellipsis,
                          ),
                          Text(
                            "${item.locationElem?.latitude},${item.locationElem?.longitude}",
                            style: const TextStyle(color: Colors.grey, fontSize: 12.0),
                            overflow: TextOverflow.ellipsis,
                          ),
                        ],
                      ),
                    ),
                    ClipRRect(
                      borderRadius: const BorderRadius.vertical(bottom: Radius.circular(10.0)),
                      child: Image.asset('assets/images/map.jpg', width: 210.0, height: 70.0, fit: BoxFit.cover),
                    )
                  ],
                ),
              ),
              onTap: () {
                MyDialog.toast('该功能暂未支持~', icon: Icon(Icons.warning), style: ToastStyle(backgroundColor: Colors.red.withAlpha(200)));
              },
              onLongPress: () {
                contextMenuDialog();
              },
            ),
          ),
        ));
      }
    }
    return msgtpl;
  }

  // 表情列表集合
  List<Widget> renderEmojWidget() {
    return [
      // Tab切换
      Container(
        padding: const EdgeInsets.symmetric(horizontal: 5.0),
        child: Row(
          children: emoJson.map((item) {
            return InkWell(
              child: Container(
                margin: const EdgeInsets.all(5.0),
                alignment: Alignment.center,
                height: 40.0,
                width: 40.0,
                decoration: BoxDecoration(color: item['selected'] ? Colors.white : Colors.transparent, borderRadius: BorderRadius.circular(5.0)),
                child: item['index'] == 0
                    ? Text(
                        item['pathLabel'],
                        style: const TextStyle(fontSize: 22.0),
                      )
                    : Image.asset(item['pathLabel'], height: 24.0, width: 24.0, fit: BoxFit.cover),
              ),
              onTap: () {
                handleEmojTab(item['index']);
              },
            );
          }).toList(),
        ),
      ),
      Expanded(
        child: Container(
          decoration: BoxDecoration(
            color: Colors.grey[200],
            border: const Border(top: BorderSide(color: Colors.black54, width: .1)),
          ),
          child: ListView(
            controller: emojController,
            padding: const EdgeInsets.all(10.0),
            children: emoJson.map((item) {
              return Visibility(
                visible: item['selected'],
                child: GridView(
                  shrinkWrap: true,
                  physics: const NeverScrollableScrollPhysics(),
                  gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                    // 横轴元素个数
                    crossAxisCount: item['type'] == 'emoj' ? 8 : 5,
                    // 纵轴间距
                    mainAxisSpacing: 5.0,
                    // 横轴间距
                    crossAxisSpacing: 5.0,
                    // 子组件宽高比例
                    childAspectRatio: 1,
                  ),
                  children: item['nodes'].map<Widget>((emoj) {
                    if (item['type'] == 'emoj') {
                      return Material(
                        type: MaterialType.transparency,
                        child: InkWell(
                          borderRadius: BorderRadius.circular(5.0),
                          child: Container(
                            alignment: Alignment.center,
                            height: 40.0,
                            width: 40.0,
                            child: Text(
                              emoj,
                              style: const TextStyle(fontSize: 24.0),
                            ),
                          ),
                          onTap: () {
                            handleEmojClick(emoj);
                          },
                        ),
                      );
                    } else {
                      return Material(
                        type: MaterialType.transparency,
                        child: InkWell(
                          borderRadius: BorderRadius.circular(5.0),
                          child: Container(
                            alignment: Alignment.center,
                            padding: const EdgeInsets.all(5.0),
                            height: 68.0,
                            width: 68.0,
                            child: Image.asset(emoj),
                          ),
                          onTap: () {
                            handleGIFClick(emoj);
                          },
                        ),
                      );
                    }
                  }).toList(),
                ),
              );
            }).toList(),
          ),
        ),
      ),
    ];
  }

  // 选择功能列表
  List<Widget> renderChooseWidget() {
    return [
      Expanded(
        child: Container(
          padding: const EdgeInsets.fromLTRB(30.0, 35.0, 30.0, 15.0),
          decoration: BoxDecoration(
            color: Colors.grey[200],
            border: const Border(top: BorderSide(color: Colors.black38, width: .1)),
          ),
          child: GridView(
            shrinkWrap: true,
            physics: const NeverScrollableScrollPhysics(),
            gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
              // 横轴元素个数
              crossAxisCount: 4,
              // 纵轴间距
              mainAxisSpacing: 30.0,
              // 横轴间距
              crossAxisSpacing: 25.0,
              // 子组件宽高比例
              childAspectRatio: .8,
            ),
            children: chooseOptions.map((item) {
              return Column(
                children: [
                  Expanded(
                    child: Material(
                      type: MaterialType.transparency,
                      child: Ink(
                        decoration: BoxDecoration(
                          color: Colors.white,
                          borderRadius: BorderRadius.circular(15.0),
                        ),
                        child: InkWell(
                          borderRadius: BorderRadius.circular(15.0),
                          child: Image.asset(item['icon'], height: 40.0, fit: BoxFit.cover),
                          onTap: () {
                            handleChooseAction(item['key']);
                          },
                        ),
                      ),
                    ),
                  ),
                  const SizedBox(height: 5.0),
                  Text(
                    item['name'],
                    style: const TextStyle(color: Colors.black87, fontSize: 12.0),
                  )
                ],
              );
            }).toList(),
          ),
        ),
      ),
    ];
  }

  /* ---------- { 聊天消息模块 } ---------- */
  // 聊天消息滚动到底部
  // void scrollToBottom() async {
  //   chatList = await fetchChatList();
  //   chatController.animateTo(isNeedScrollBottom ? 0 : chatController.position.maxScrollExtent,
  //       duration: const Duration(milliseconds: 200), curve: Curves.easeIn);
  // }
  void scrollToBottom() {
    Future.delayed(Duration(milliseconds: 100), () {
      if (chatController.hasClients) {
        chatController.animateTo(
          0, // reverse: true 时滚动到底部是 offset: 0
          duration: Duration(milliseconds: 300),
          curve: Curves.easeOut,
        );
      }
    });
  }

  // 点击消息区域
  void handleClickChatArea() {
    hideKeyboard();
    setState(() {
      toolbarEnable = false;
    });
  }

  /* ---------- { 底部Toolbar模块 } ---------- */
  // 光标处插入内容
  void insertTextAtCursor(String html) {
    var editorNotifier = editorController.value; // The current value stored in this notifier.
    var start = editorNotifier.selection.baseOffset;
    var end = editorNotifier.selection.extentOffset;
    if (editorNotifier.selection.isValid) {
      String newText = '';
      if (editorNotifier.selection.isCollapsed) {
        if (end > 0) {
          newText += editorNotifier.text.substring(0, end);
        }
        newText += html;
        if (editorNotifier.text.length > end) {
          newText += editorNotifier.text.substring(end, editorNotifier.text.length);
        }
      } else {
        newText = editorNotifier.text.replaceRange(start, end, html);
        end = start;
      }
      editorController.value =
          editorNotifier.copyWith(text: newText, selection: editorNotifier.selection.copyWith(baseOffset: end + html.length, extentOffset: end + html.length));
    } else {
      editorController.value = TextEditingValue(
        text: html,
        selection: TextSelection.fromPosition(TextPosition(offset: html.length)),
      );
    }
  }

  // 发送消息队列
  void sendMessage(message) async {
    // 待插入的消息
    List<V2TimMessage> messagesToInsert = [];
    V2TimMessage? lastRealMsg;

    for (var msg in controller.chatList) {
      if (msg.localCustomData != 'time_label') {
        lastRealMsg = msg;
        break;
      }
    }

    // 如果有数据，检测时间，是否需要插入伪消息
    if (lastRealMsg != null &&
        needInsertTimeLabel(
          (lastRealMsg.timestamp ?? 0) * 1000, // 转为毫秒级
          DateTime.now().millisecondsSinceEpoch,
        )) {
      // 消息时间间隔超过3分钟插入伪消息
      final showLabel = Utils().formatChatTime(DateTime.now().millisecondsSinceEpoch ~/ 1000);
      final resMsg = await IMMessage().insertTimeLabel(showLabel, selfUserId);
      messagesToInsert.add(resMsg.data);
    } else {
      // 没数据的时候直接插入伪消息
      final showLabel = Utils().formatChatTime(DateTime.now().millisecondsSinceEpoch ~/ 1000);

      final resMsg = await IMMessage().insertTimeLabel(showLabel, selfUserId);
      messagesToInsert.add(resMsg.data);
    }

    // 不需要时间标签
    // final res = await IMMessage().sendText(
    //   text: message['content'],
    //   toUserID: arguments.value.userID,
    // );

    // if (res.success && res.data != null) {
    //   messagesToInsert.insert(0, res.data); // 加入消息本体

    //   controller.chatList.insertAll(0, messagesToInsert);

    //   scrollToBottom();
    //   print('发送成功');
    // } else {
    //   print('消息发送失败: ${res.code} - ${res.desc}');
    // }
  }

  bool needInsertTimeLabel(int lastTimestamp, int newTimestamp, {int interval = 3 * 60}) {
    return (newTimestamp - lastTimestamp) > interval * 1000;
  }

  // 隐藏键盘
  void hideKeyboard() {
    if (editorFocusNode.hasFocus) {
      editorFocusNode.unfocus();
    }
  }

  // 表情/选择切换
  void handleEmojChooseState(index) {
    hideKeyboard();
    setState(() {
      toolbarEnable = true;
      toolbarIndex = index;
      voiceBtnEnable = false;
    });
    scrollToBottom();
  }

  // 表情Tab切换
  void handleEmojTab(index) {
    var emols = emoJson;
    for (var i = 0, len = emols.length; i < len; i++) {
      emols[i]['selected'] = false;
    }
    emols[index]['selected'] = true;
    setState(() {
      emoJson = emols;
    });
    emojController.jumpTo(0);
  }

  // 点击表情
  void handleEmojClick(emoj) {
    insertTextAtCursor(emoj);
  }

  // 点击Gif大图
  void handleGIFClick(gifpath) {
    // 消息队列
    Map message = {
      'id': Utils.uuid(),
      'contentType': 4,
      'isme': true,
      'avatar': 'assets/images/avatar/img11.jpg',
      'author': 'Andy',
      'content': '',
      'image': gifpath,
      'video': '',
    };
    sendMessage(message);
  }

  // 提交消息
  void handleSubmit() {
    if (editorController.text.isEmpty) return;
    // 消息队列
    Map message = {
      'id': Utils.uuid(),
      'contentType': 3,
      'isme': true,
      'avatar': 'assets/images/avatar/img11.jpg',
      'author': 'Andy',
      'content': editorController.text,
      'image': '',
      'video': '',
    };
    sendMessage(message);
    editorController.clear();
  }

  // 选择区操作
  void handleChooseAction(key) {
    MyDialog.toast('$key');
    switch (key) {
      case 'photo':
        // ....
        break;
      case 'camera':
        // ....
        break;
      case 'redpacket':
        sendRedPacketDialog();
        break;
    }
  }

  /* ---------- { 弹窗功能模块 } ---------- */
  // 红包弹窗
  void receiveRedPacketDialog(data) {
    showDialog(
        context: context,
        builder: (context) {
          return Material(
              type: MaterialType.transparency,
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Container(
                    width: double.infinity,
                    margin: const EdgeInsets.symmetric(horizontal: 50.0),
                    padding: const EdgeInsets.symmetric(vertical: 50.0),
                    decoration: const BoxDecoration(
                      color: Color(0xFFFF7F43),
                      borderRadius: BorderRadius.all(Radius.circular(12.0)),
                    ),
                    child: Column(
                      children: [
                        ClipRRect(
                          borderRadius: BorderRadius.circular(5.0),
                          child: Image.asset(data['avatar'], height: 40.0, width: 40.0, fit: BoxFit.cover),
                        ),
                        const SizedBox(
                          height: 5.0,
                        ),
                        Text(
                          data['author'],
                          style: const TextStyle(color: Color(0xFFFFF9C7), fontWeight: FontWeight.w600),
                        ),
                        Text(
                          data['content'],
                          style: const TextStyle(color: Color(0xFFFFF9C7), fontWeight: FontWeight.w500, fontSize: 20.0),
                        ),
                        SizedBox(
                          height: 100.0,
                        ),
                        AnimatedBuilder(
                          animation: animTurns,
                          builder: (context, child) {
                            return Transform(
                              transform: Matrix4.rotationY(animTurns.value),
                              alignment: Alignment.center,
                              child: FilledButton(
                                style: ButtonStyle(
                                  backgroundColor: WidgetStateProperty.all(const Color(0xFFFFF9C7)),
                                  padding: WidgetStateProperty.all(EdgeInsets.zero),
                                  minimumSize: WidgetStateProperty.all(const Size(80.0, 80.0)),
                                  shape: WidgetStateProperty.all(const CircleBorder()),
                                  elevation: WidgetStateProperty.all(3.0),
                                ),
                                child: Text(
                                  '開',
                                  style: TextStyle(color: Color(0xFF3B3B3B), fontSize: 28.0),
                                ),
                                onPressed: () {
                                  // 开始动画
                                  animController.repeat();
                                  // 模拟开红包逻辑，1 秒后停止动画
                                  Future.delayed(Duration(seconds: 1), () {
                                    animController.stop();
                                    animController.reset();
                                    Get.back();
                                  });
                                },
                              ),
                            );
                          },
                        ),
                      ],
                    ),
                  ),
                  GestureDetector(
                    child: Container(
                      margin: const EdgeInsets.only(top: 20.0),
                      height: 30.0,
                      width: 30.0,
                      decoration: BoxDecoration(
                        border: Border.all(color: Colors.white, width: 1.5),
                        borderRadius: BorderRadius.circular(50.0),
                      ),
                      child: const Icon(
                        Icons.close_outlined,
                        color: Colors.white,
                        size: 18.0,
                      ),
                    ),
                    onTap: () {
                      Navigator.of(context).pop();
                    },
                  )
                ],
              ));
        });
  }

  // 长按消息菜单
  void contextMenuDialog() {
    showDialog(
      context: context,
      builder: (context) {
        return SimpleDialog(
          backgroundColor: Colors.white,
          surfaceTintColor: Colors.white,
          contentPadding: const EdgeInsets.symmetric(vertical: 5.0),
          shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15.0)),
          children: [
            SimpleDialogOption(
              child: const Padding(padding: EdgeInsets.symmetric(vertical: 5.0), child: Text('复制')),
              onPressed: () {},
            ),
            SimpleDialogOption(
              child: const Padding(padding: EdgeInsets.symmetric(vertical: 5.0), child: Text('发送给朋友')),
              onPressed: () {},
            ),
            SimpleDialogOption(
              child: const Padding(padding: EdgeInsets.symmetric(vertical: 5.0), child: Text('收藏')),
              onPressed: () {},
            ),
            SimpleDialogOption(
              child: const Padding(padding: EdgeInsets.symmetric(vertical: 5.0), child: Text('删除')),
              onPressed: () {},
            ),
          ],
        );
      },
    );
  }

  // 发群红包弹窗
  void sendRedPacketDialog() {
    showModalBottomSheet(
      backgroundColor: Colors.grey[50],
      shape: const RoundedRectangleBorder(borderRadius: BorderRadius.vertical(top: Radius.circular(15.0))),
      showDragHandle: true,
      clipBehavior: Clip.hardEdge,
      isScrollControlled: true, // 屏幕最大高度
      constraints: BoxConstraints(
        maxHeight: MediaQuery.of(context).size.height - 180, // 自定义最大高度
      ),
      context: context,
      builder: (context) {
        return RedPacket(
          flag: true,
        );
      },
    );
  }

  /* ---------- { 其它功能模块 } ---------- */

  @override
  Widget build(BuildContext context) {
    return Stack(
      fit: StackFit.expand,
      children: [
        // 页面主体(聊天消息区/底部操作区)
        Scaffold(
          backgroundColor: Colors.grey[200],
          appBar: AppBar(
            centerTitle: true,
            backgroundColor: Colors.transparent,
            foregroundColor: Colors.white,
            leading: IconButton(
              icon: Icon(
                Icons.arrow_back_ios_rounded,
                size: 20.0,
              ),
              onPressed: () {
                Get.back();
              },
            ),
            titleSpacing: 1.0,
            title: Obx(() {
              return Text(
                // '${arguments['title']}',
                '${arguments.value.showName}',
                style: const TextStyle(fontSize: 18.0, fontFamily: 'Arial'),
              );
            }),
            flexibleSpace: Container(
              decoration: const BoxDecoration(
                  gradient: LinearGradient(
                begin: Alignment.topLeft,
                end: Alignment.bottomRight,
                colors: [Color(0xFFBE4EFF), Color(0xFF1DFFC7)],
              )),
            ),
            actions: [
              IconButton(
                icon: const Icon(
                  Icons.more_horiz,
                  color: Colors.white,
                ),
                onPressed: () async {
                  final paddingTop = MediaQuery.of(Get.context!).padding.top;

                  final selected = await showMenu(
                    context: Get.context!,
                    position: RelativeRect.fromLTRB(
                      double.infinity,
                      kToolbarHeight + paddingTop - 12,
                      8,
                      double.infinity,
                    ),
                    color: FStyle.primaryColor,
                    elevation: 8,
                    items: [
                      PopupMenuItem<String>(
                        value: 'remark',
                        child: Row(
                          children: [
                            Icon(Icons.edit, color: Colors.white, size: 18),
                            SizedBox(width: 8),
                            Text(
                              '设置备注',
                              style: TextStyle(color: Colors.white),
                            ),
                          ],
                        ),
                      ),
                      PopupMenuItem<String>(
                        value: 'not',
                        child: Row(
                          children: [
                            Icon(Icons.do_not_disturb_on, color: Colors.white, size: 18),
                            SizedBox(width: 8),
                            Text(
                              '设为免打扰',
                              style: TextStyle(color: Colors.white),
                            ),
                          ],
                        ),
                      ),
                      PopupMenuItem<String>(
                        value: 'report',
                        child: Row(
                          children: [
                            Icon(Icons.report, color: Colors.white, size: 18),
                            SizedBox(width: 8),
                            Text(
                              '举报',
                              style: TextStyle(color: Colors.white),
                            ),
                          ],
                        ),
                      ),
                      PopupMenuItem<String>(
                        value: 'block',
                        child: Row(
                          children: [
                            Icon(Icons.block, color: Colors.white, size: 18),
                            SizedBox(width: 8),
                            Text(
                              '拉黑',
                              style: TextStyle(color: Colors.white),
                            ),
                          ],
                        ),
                      ),
                      PopupMenuItem<String>(
                        value: 'foucs',
                        child: Row(
                          children: [
                            Icon(Icons.person_remove_alt_1, color: Colors.white, size: 18),
                            SizedBox(width: 8),
                            Text(
                              '取消关注',
                              style: TextStyle(color: Colors.white),
                            ),
                          ],
                        ),
                      ),
                    ],
                  );

                  if (selected != null) {
                    switch (selected) {
                      case 'remark':
                        print('点击了备注');
                        setRemark();
                        break;
                      case 'not':
                        print('点击了免打扰');
                        break;
                      case 'report':
                        print('点击了举报');
                        break;
                      case 'block':
                        print('点击了拉黑');
                        break;
                      case 'foucs':
                        print('点击了取关');
                        break;
                    }
                  }
                },
              ),
            ],
          ),
          body: Flex(
            direction: Axis.vertical,
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              // 渲染聊天消息
              Expanded(
                child: ScrollConfiguration(
                  behavior: CustomScrollBehavior(),
                  child: GestureDetector(
                    child: Obx(() {
                      return ListView(
                        controller: chatController,
                        reverse: true,
                        padding: const EdgeInsets.all(10.0),
                        children: renderChatList(),
                      );
                    }),
                    onTap: () {
                      handleClickChatArea();
                    },
                  ),
                ),
              ),

              // 底部操作栏
              Container(
                  color: Colors.grey[100],
                  child: SafeArea(
                    bottom: true,
                    child: Container(
                      decoration: BoxDecoration(
                        color: Colors.grey[100],
                        border: const Border(top: BorderSide(color: Colors.black38, width: .1)),
                      ),
                      child: Column(
                        children: [
                          // 输入框编辑器模块
                          Container(
                            padding: const EdgeInsets.all(10.0),
                            child: Row(
                              children: [
                                InkWell(
                                  child: Icon(
                                    voiceBtnEnable ? Icons.keyboard_outlined : Icons.contactless_outlined,
                                    color: const Color(0xFF3B3B3B),
                                    size: 30.0,
                                  ),
                                  onTap: () {
                                    setState(() {
                                      toolbarEnable = false;
                                      if (voiceBtnEnable) {
                                        voiceBtnEnable = false;
                                        editorFocusNode.requestFocus();
                                      } else {
                                        voiceBtnEnable = true;
                                        editorFocusNode.unfocus();
                                      }
                                    });
                                  },
                                ),
                                const SizedBox(
                                  width: 10.0,
                                ),
                                Expanded(
                                  child: Container(
                                    constraints: const BoxConstraints(minHeight: 40.0),
                                    decoration: BoxDecoration(
                                      color: Colors.white,
                                      borderRadius: BorderRadius.circular(5),
                                    ),
                                    child: Stack(
                                      children: [
                                        // 输入框
                                        Offstage(
                                          offstage: voiceBtnEnable,
                                          child: TextField(
                                            decoration: const InputDecoration(
                                              isDense: true,
                                              hoverColor: Colors.transparent,
                                              contentPadding: EdgeInsets.all(8.0),
                                              border: OutlineInputBorder(borderSide: BorderSide.none),
                                            ),
                                            style: const TextStyle(
                                              fontSize: 16.0,
                                            ),
                                            maxLines: null,
                                            controller: editorController,
                                            focusNode: editorFocusNode,
                                            cursorColor: const Color(0xFF07C160),
                                            onChanged: (value) {},
                                          ),
                                        ),
                                        // 语音
                                        Offstage(
                                          offstage: !voiceBtnEnable,
                                          child: GestureDetector(
                                            child: Container(
                                              decoration: BoxDecoration(
                                                color: Colors.white,
                                                borderRadius: BorderRadius.circular(5),
                                              ),
                                              alignment: Alignment.center,
                                              height: 40.0,
                                              width: double.infinity,
                                              child: Text(
                                                voiceTypeMap[voiceType],
                                                style: const TextStyle(fontSize: 15.0),
                                              ),
                                            ),
                                            onPanStart: (details) {
                                              setState(() {
                                                voiceType = 1;
                                                voicePanelEnable = true;
                                              });
                                            },
                                            onPanUpdate: (details) {
                                              Offset pos = details.globalPosition;
                                              double swipeY = MediaQuery.of(context).size.height - 120;
                                              double swipeX = MediaQuery.of(context).size.width / 2 + 50;
                                              setState(() {
                                                if (pos.dy >= swipeY) {
                                                  voiceType = 1; // 松开发送
                                                } else if (pos.dy < swipeY && pos.dx < swipeX) {
                                                  voiceType = 2; // 左滑松开取消
                                                } else if (pos.dy < swipeY && pos.dx >= swipeX) {
                                                  voiceType = 3; // 右滑语音转文字
                                                }
                                              });
                                            },
                                            onPanEnd: (details) {
                                              // print('停止录音');
                                              setState(() {
                                                switch (voiceType) {
                                                  case 1:
                                                    MyDialog.toast('发送录音文件');
                                                    voicePanelEnable = false;
                                                    break;
                                                  case 2:
                                                    MyDialog.toast('取消发送');
                                                    voicePanelEnable = false;
                                                    break;
                                                  case 3:
                                                    MyDialog.toast('语音转文字');
                                                    voicePanelEnable = true;
                                                    voiceToTransfer = true;
                                                    break;
                                                }
                                                voiceType = 0;
                                              });
                                            },
                                          ),
                                        ),
                                      ],
                                    ),
                                  ),
                                ),
                                const SizedBox(
                                  width: 10.0,
                                ),
                                InkWell(
                                  child: const Icon(
                                    Icons.add_reaction_rounded,
                                    color: Color(0xFF3B3B3B),
                                    size: 30.0,
                                  ),
                                  onTap: () {
                                    handleEmojChooseState(0);
                                  },
                                ),
                                const SizedBox(
                                  width: 8.0,
                                ),
                                InkWell(
                                  child: const Icon(
                                    Icons.add,
                                    color: Color(0xFF3B3B3B),
                                    size: 30.0,
                                  ),
                                  onTap: () {
                                    handleEmojChooseState(1);
                                  },
                                ),
                                const SizedBox(
                                  width: 8.0,
                                ),
                                InkWell(
                                  child: Container(
                                    height: 25.0,
                                    width: 25.0,
                                    decoration: BoxDecoration(
                                      color: const Color(0xFF07C160),
                                      borderRadius: BorderRadius.circular(20.0),
                                    ),
                                    child: const Icon(
                                      Icons.arrow_upward,
                                      color: Colors.white,
                                      size: 20.0,
                                    ),
                                  ),
                                  onTap: () {
                                    handleSubmit();
                                  },
                                ),
                              ],
                            ),
                          ),

                          // 表情+选择模块
                          Visibility(
                            visible: toolbarEnable,
                            child: SizedBox(
                              height: keyboardHeight,
                              child: Column(
                                children: toolbarIndex == 0 ? renderEmojWidget() : renderChooseWidget(),
                              ),
                            ),
                          )
                        ],
                      ),
                    ),
                  ))
            ],
          ),
        ),
        // 录音主体(按住说话/松开取消/语音转文本)
        IgnorePointer(
          ignoring: false,
          child: Visibility(
            visible: voicePanelEnable,
            child: Material(
              color: const Color(0xDD1B1B1B),
              child: Stack(
                children: [
                  // 取消发送+语音转文字
                  Positioned(
                    bottom: 120,
                    left: 30,
                    right: 30,
                    child: Visibility(
                      visible: !voiceToTransfer,
                      child: Column(
                        crossAxisAlignment: voiceType == 2 ? CrossAxisAlignment.start : CrossAxisAlignment.center,
                        children: [
                          // 语音动画层
                          Stack(
                            alignment: Alignment.bottomCenter,
                            children: [
                              AnimatedContainer(
                                duration: Duration(milliseconds: 200),
                                height: 70.0,
                                width: voiceType == 2 ? 70.0 : 200.0,
                                decoration: BoxDecoration(
                                  color: voiceType == 2 ? Colors.red : Color(0xFF89E45B),
                                  borderRadius: BorderRadius.circular(15.0),
                                ),
                                clipBehavior: Clip.antiAlias,
                                child: Row(
                                  mainAxisAlignment: MainAxisAlignment.center,
                                  children: [
                                    Image.asset('assets/images/voice_waves.gif', height: 23.0, width: voiceType == 2 ? 30.0 : 70.0, fit: BoxFit.cover)
                                  ],
                                ),
                              ),
                              RotatedBox(
                                quarterTurns: 0,
                                child: CustomPaint(painter: ArrowShape(arrowColor: voiceType == 2 ? Colors.red : Color(0xFF89E45B), arrowSize: 10.0)),
                              )
                            ],
                          ),
                          const SizedBox(
                            height: 50.0,
                          ),
                          // 操作项
                          Row(
                            mainAxisAlignment: MainAxisAlignment.spaceBetween,
                            children: [
                              // 取消发送
                              Container(
                                height: 60.0,
                                width: 60.0,
                                decoration: BoxDecoration(
                                  borderRadius: BorderRadius.circular(50.0),
                                  color: voiceType == 2 ? Colors.red : Colors.black38,
                                ),
                                child: Icon(
                                  Icons.close,
                                  color: Colors.white54,
                                ),
                              ),
                              // 语音转文字
                              Container(
                                height: 60.0,
                                width: 60.0,
                                decoration: BoxDecoration(
                                  borderRadius: BorderRadius.circular(50.0),
                                  color: voiceType == 3 ? Color(0xFF89E45B) : Colors.black38,
                                ),
                                child: Icon(
                                  Icons.translate,
                                  color: Colors.white54,
                                ),
                              ),
                            ],
                          ),
                        ],
                      ),
                    ),
                  ),
                  // 语音转文字(识别结果状态)
                  Positioned(
                    bottom: 120,
                    left: 30,
                    right: 30,
                    child: Visibility(
                      visible: voiceToTransfer,
                      child: Column(
                        children: [
                          // 提示结果
                          Stack(
                            children: [
                              Container(
                                height: 100.0,
                                decoration: BoxDecoration(
                                  color: Colors.red,
                                  borderRadius: BorderRadius.circular(15.0),
                                ),
                                child: const Row(
                                  mainAxisAlignment: MainAxisAlignment.center,
                                  children: [
                                    Icon(
                                      Icons.info_outlined,
                                      color: Colors.white,
                                    ),
                                    Text(
                                      '未识别到文字。',
                                      style: TextStyle(color: Colors.white),
                                    ),
                                  ],
                                ),
                              ),
                              Positioned(
                                  right: 35.0,
                                  bottom: 1,
                                  child: RotatedBox(
                                    quarterTurns: 0,
                                    child: CustomPaint(painter: ArrowShape(arrowColor: Colors.red, arrowSize: 10.0)),
                                  )),
                            ],
                          ),
                          const SizedBox(
                            height: 50.0,
                          ),
                          // 操作项
                          Row(
                            mainAxisAlignment: MainAxisAlignment.spaceBetween,
                            children: [
                              GestureDetector(
                                child: Container(
                                  height: 60.0,
                                  width: 60.0,
                                  decoration: const BoxDecoration(
                                    color: Colors.transparent,
                                  ),
                                  child: const Column(
                                    mainAxisAlignment: MainAxisAlignment.center,
                                    children: [
                                      Icon(
                                        Icons.undo,
                                        color: Colors.white54,
                                      ),
                                      Text(
                                        '取消',
                                        style: TextStyle(color: Colors.white70),
                                      )
                                    ],
                                  ),
                                ),
                                onTap: () {
                                  setState(() {
                                    voicePanelEnable = false;
                                    voiceToTransfer = false;
                                  });
                                },
                              ),
                              GestureDetector(
                                child: Container(
                                  height: 60.0,
                                  width: 100.0,
                                  decoration: const BoxDecoration(
                                    color: Colors.transparent,
                                  ),
                                  child: const Column(
                                    mainAxisAlignment: MainAxisAlignment.center,
                                    children: [
                                      Icon(
                                        Icons.graphic_eq_rounded,
                                        color: Colors.white54,
                                      ),
                                      Text(
                                        '发送原语音',
                                        style: TextStyle(color: Colors.white70),
                                      )
                                    ],
                                  ),
                                ),
                                onTap: () {},
                              ),
                              GestureDetector(
                                child: Container(
                                  height: 60.0,
                                  width: 60.0,
                                  decoration: BoxDecoration(
                                    borderRadius: BorderRadius.circular(50.0),
                                    color: Colors.white12,
                                  ),
                                  child: const Icon(
                                    Icons.check,
                                    color: Colors.white12,
                                  ),
                                ),
                                onTap: () {},
                              ),
                            ],
                          ),
                        ],
                      ),
                    ),
                  ),
                  // 提示文字(操作状态)
                  Positioned(
                    bottom: 120,
                    left: 0,
                    width: MediaQuery.of(context).size.width,
                    child: Visibility(
                      visible: !voiceToTransfer,
                      child: Align(
                        child: Text(
                          voiceTypeMap[voiceType],
                          style: const TextStyle(color: Colors.white70),
                        ),
                      ),
                    ),
                  ),
                  // 背景
                  Align(
                    alignment: Alignment.bottomCenter,
                    child: Visibility(
                      visible: !voiceToTransfer,
                      child: Image.asset('assets/images/voice_bg.webp', width: double.infinity, height: 100.0, fit: BoxFit.fill),
                    ),
                  ),
                  // 背景图标
                  Positioned(
                    bottom: 25,
                    left: 0,
                    width: MediaQuery.of(context).size.width,
                    child: Visibility(
                      visible: !voiceToTransfer,
                      child: const Align(
                        child: Icon(
                          Icons.graphic_eq_rounded,
                          color: Colors.black54,
                        ),
                      ),
                    ),
                  ),
                ],
              ),
            ),
          ),
        )
      ],
    );
  }
}

// 渲染聊天消息公共部分
class RenderChatItem extends StatelessWidget {
  const RenderChatItem({
    super.key,
    required this.data,
    required this.child,
  });
  final V2TimMessage data; // 消息数据
  final Widget? child; // 消息体

  // 设置箭头颜色
  // Color arrowColor(data) {
  //   Color color = Colors.transparent;
  //   if ([8].contains(data.elemType)) {
  //     // 红包箭头颜色
  //     color = const Color(0xFFFFA52F);
  //   } else if ([9].contains(data.elemType)) {
  //     // 位置箭头颜色
  //     color = const Color(0xFFFFFFFF);
  //   } else {
  //     color = !data['isme'] ? const Color(0xFFFFFFFF) : const Color(0xFF9543FF);
  //   }
  //   return color;
  // }

  @override
  Widget build(BuildContext context) {
    return Container(
      margin: const EdgeInsets.only(bottom: 10.0),
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          !(data.isSelf ?? false)
              ? SizedBox(
                  height: 35.0,
                  width: 35.0,
                  child: ClipRRect(
                    borderRadius: const BorderRadius.all(Radius.circular(20.0)),
                    child: Image.network(data.faceUrl ?? 'https://wuzhongjie.com.cn/download/logo.png'),
                  ),
                )
              : const SizedBox.shrink(),
          Expanded(
            child: Padding(
              padding: !(data.isSelf ?? false) ? const EdgeInsets.only(left: 10.0, right: 40.0) : const EdgeInsets.only(left: 40.0, right: 10.0),
              child: Column(
                crossAxisAlignment: !(data.isSelf ?? false) ? CrossAxisAlignment.start : CrossAxisAlignment.end,
                children: [
                  Text(
                    data.friendRemark ?? data.nameCard ?? data.nickName ?? '未知昵称',
                    style: const TextStyle(color: Colors.grey, fontSize: 12.0),
                  ),
                  const SizedBox(
                    height: 3.0,
                  ),
                  Stack(
                    children: [
                      // 气泡箭头
                      /* Visibility(
                        // 显示箭头(消息+语音+红包+位置)
                        visible: [3, 7, 8, 9].contains(data['contentType']),
                        child: Positioned(
                          left: !data['isme'] ? 1 : null,
                          right: data['isme'] ? 1 : null,
                          top: 20.0,
                          child: RotatedBox(
                            quarterTurns: !data['isme'] ? 1 : -1,
                            child: CustomPaint(painter: ArrowShape(arrowColor: arrowColor(data))),
                          )
                        ),
                      ), */
                      Container(
                        child: child,
                      ),
                    ],
                  ),
                ],
              ),
            ),
          ),
          data.isSelf ?? false
              ? SizedBox(
                  height: 35.0,
                  width: 35.0,
                  child: ClipRRect(
                    borderRadius: const BorderRadius.all(Radius.circular(20.0)),
                    child: Image.network(data.faceUrl ?? 'https://wuzhongjie.com.cn/download/logo.png'),
                  ),
                )
              : const SizedBox.shrink(),
        ],
      ),
    );
  }
}

// 绘制气泡箭头
class ArrowShape extends CustomPainter {
  ArrowShape({
    required this.arrowColor,
    this.arrowSize = 7,
  });

  final Color arrowColor; // 箭头颜色
  final double arrowSize; // 箭头大小

  @override
  void paint(Canvas canvas, Size size) {
    var paint = Paint()..color = arrowColor;

    var path = Path();
    path.lineTo(-arrowSize, 0);
    path.lineTo(0, arrowSize);
    path.lineTo(arrowSize, 0);
    canvas.drawPath(path, paint);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return false;
  }
}
