import 'package:flutter_openim_sdk/flutter_openim_sdk.dart';

import 'im_service.dart';

/// 统一消息发送服务：所有消息（文字/表情/语音/图片/文件/通话信令）都走这里。
///
/// 职责：
/// 1. 发送前置校验：已登录、连接正常、接收方非空；
/// 2. 单聊时校验好友状态（非好友明确提示，不静默失败）；
/// 3. 失败时把 SDK 原始 code/message 记进日志（不含 token 与正文），
///    并返回可直接展示的中文错误，杜绝「只吞异常看不到原因」。
class MessageSendService {
  MessageSendService._();

  static final MessageSendService instance = MessageSendService._();

  /// 发送消息。成功返回 SDK 回执消息；失败抛出带中文提示的异常。
  /// 单聊且非好友时抛 [FriendRequiredException]。
  Future<Message> send({
    required Message message,
    String? userID,
    String? groupID,
    String? offlinePushInfo = '',
  }) async {
    final im = IMService.instance;

    if (!im.loggedIn || im.currentUserID == null) {
      throw const SendException('登录状态失效，请重新登录');
    }
    if (im.connectStatus != ConnectStatus.success) {
      throw const SendException('正在重连，请稍后再试');
    }

    final isGroup = groupID != null && groupID.isNotEmpty;
    final peer = userID ?? '';
    if (!isGroup && peer.isEmpty) {
      throw const SendException('请先添加对方为同事，再发起会话');
    }

    // 单聊：非好友提示先添加（OpenIM 服务端是否拦截交给服务端，但提示要明确）
    if (!isGroup) {
      final isFriend = await _isFriend(peer);
      if (!isFriend) {
        throw FriendRequiredException('请先添加对方为同事，再发送消息');
      }
    }

    try {
      final sent = await OpenIM.iMManager.messageManager.sendMessage(
        message: message,
        userID: isGroup ? null : peer,
        groupID: isGroup ? groupID : null,
        offlinePushInfo: OfflinePushInfo(),
      );
      return sent;
    } catch (e) {
      // 记录原始错误码（不含 token / 消息正文）
      // ignore: avoid_print
      print('[MessageSendService] 发送失败 peer=$peer groupID=$groupID err=$e');
      throw SendException(_mapError(e));
    }
  }

  /// 判断 peer 是否已是好友。查询失败按非好友处理（宁可让用户先加好友）。
  Future<bool> _isFriend(String userID) async {
    try {
      final friends = await OpenIM.iMManager.friendshipManager.getFriendList();
      return friends.any((f) => (f.userID ?? f.friendUserID) == userID);
    } catch (_) {
      return false;
    }
  }

  /// 把 SDK 原始错误映射成中文提示
  String _mapError(dynamic e) {
    final s = e.toString();
    // SDK 错误码常量，见 flutter_openim_sdk/lib/src/enum/sdk_error_code.dart
    if (s.contains('1303')) return '对方还不是你的同事，请先添加对方';
    if (s.contains('1304')) return '已经是同事了，可以正常聊天';
    if (s.contains('1302')) return '对方已把你加入黑名单，无法发送';
    if (s.contains('1101')) return '对方账号不存在';
    if (s.contains('1501')) return '登录已过期，请重新登录';
    if (s.contains('1502') || s.contains('1503')) return '登录凭证无效，请重新登录';
    if (s.contains('10000') || s.contains('10001') || s.contains('网络') || s.contains('timeout')) {
      return '网络异常，请检查网络后重试';
    }
    return '消息没发出去，请重试';
  }
}

/// 发送失败的中文提示
class SendException implements Exception {
  final String message;
  const SendException(this.message);

  @override
  String toString() => message;
}

/// 单聊非好友时的明确提示
class FriendRequiredException extends SendException {
  const FriendRequiredException(super.message);
}
