import 'dart:convert';

import 'package:uuid/uuid.dart';

/// 下位机消息类型
///
/// 对应《下位机交互数据模型.md》中定义的四种 type 字段。
enum DeviceMessageType {
  /// 设备基本信息：门状态 / 任务运行状态 / 灯状态
  deviceInfo('device_info'),

  /// 下发任务：步骤列表 + 温度 + 吹气时间
  createTask('create_task'),

  /// 灯光控制：开 / 关
  lightControl('light_control'),

  /// 任务控制：继续 / 停止 / 暂停
  control('control');

  const DeviceMessageType(this.wireName);

  /// 协议层使用的字符串名称
  final String wireName;

  /// 从协议字符串解析消息类型；未知值返回 null
  static DeviceMessageType? fromWire(String? name) {
    if (name == null) return null;
    for (final t in values) {
      if (t.wireName == name) return t;
    }
    return null;
  }
}

/// 下位机消息
///
/// 完整对应数据模型：
/// ```json
/// {
///   "message_id": "uuid",
///   "type": "device_info",
///   "ack": "uuid-of-original",
///   "need_ack": true,
///   "data": { ... }
/// }
/// ```
class DeviceMessage {
  /// 唯一识别码。发送时由调用方生成（UUID 字符串）；
  /// 接收时来自协议，便于 ack 关联。
  final String messageId;

  /// 消息类型
  final DeviceMessageType type;

  /// 当本条消息是某条消息的响应时，填写被响应的 message_id；否则为 null
  final String? ack;

  /// 是否需要对方响应
  final bool needAck;

  /// 业务负载；具体结构由 [type] 决定
  final Map<String, dynamic> data;

  const DeviceMessage({
    required this.messageId,
    required this.type,
    required this.data,
    this.ack,
    this.needAck = false,
  });

  /// 构造主动请求时使用的便捷工厂
  factory DeviceMessage.request({
    required DeviceMessageType type,
    required Map<String, dynamic> data,
    required String messageId,
    bool needAck = false,
  }) {
    return DeviceMessage(
      messageId: messageId,
      type: type,
      data: data,
      ack: null,
      needAck: needAck,
    );
  }

  /// 构造应答时使用的便捷工厂
  factory DeviceMessage.ackFor(DeviceMessage original, Map<String, dynamic> data) {
    return DeviceMessage(
      messageId: '${original.messageId}-ack',
      type: original.type,
      data: data,
      ack: original.messageId,
      needAck: false,
    );
  }

  /// 序列化为协议层 Map
  Map<String, dynamic> toJson() => {
        'message_id': messageId,
        'type': type.wireName,
        'ack': ack,
        'need_ack': needAck,
        'data': data,
      };

  /// 序列化为 JSON 字符串
  String encode() => jsonEncode(toJson());

  /// 从 JSON Map 解析；不抛异常，解析失败时返回 null
  static DeviceMessage? fromJson(Map<String, dynamic> json) {
    final type = DeviceMessageType.fromWire(json['type'] as String?);
    if (type == null) return null;
    final messageId = json['message_id'] as String?;
    if (messageId == null || messageId.isEmpty) return null;
    return DeviceMessage(
      messageId: messageId,
      type: type,
      ack: (json['ack'] as String?)?.isEmpty == true ? null : json['ack'] as String?,
      needAck: json['need_ack'] as bool? ?? false,
      data: _coerceData(json['data']),
    );
  }

  /// 从 JSON 字符串解析；解析失败时返回 null
  static DeviceMessage? decode(String raw) {
    try {
      final map = jsonDecode(raw);
      if (map is! Map<String, dynamic>) return null;
      return fromJson(map);
    } catch (_) {
      return null;
    }
  }

  /// JSON 中的 data 既可能是 Map，也可能是字符串（容错处理）
  static Map<String, dynamic> _coerceData(dynamic raw) {
    if (raw is Map<String, dynamic>) return raw;
    if (raw is Map) return Map<String, dynamic>.from(raw);
    return <String, dynamic>{};
  }

  @override
  String toString() => 'DeviceMessage(id=$messageId, type=${type.wireName}, '
      'ack=$ack, needAck=$needAck, data=${data.keys.toList()})';
}

/// 消息 ID 生成器
///
/// 基于 [Uuid.v4] 生成全局唯一 ID（128 位随机，标准 36 字符 hex-with-dashes 形式）。
/// 例如 `550e8400-e29b-41d4-a716-446655440000`。
class MessageIdGenerator {
  static const Uuid _uuid = Uuid();

  /// 生成下一个唯一 ID
  String next() => _uuid.v4();
}
