/// Types of WebSocket events from ComfyUI
enum WebSocketEventType {
  status,
  progress,
  executing,
  executed,
  executionStart,
  executionCached,
  executionSuccess,
  executionError,
  dataOutput,
  unknown
}

/// A typed event from the ComfyUI WebSocket
class WebSocketEvent {
  final WebSocketEventType eventType;
  final Map<String, dynamic> data;
  final String? promptId;
  final String rawType;

  WebSocketEvent({
    required this.eventType,
    required this.data,
    this.promptId,
    required this.rawType,
  });

  @override
  String toString() =>
      'WebSocketEvent{type: $eventType, rawType: $rawType, promptId: $promptId, data: ${data.keys.join(', ')}}';

  /// Creates a WebSocketEvent from JSON
  factory WebSocketEvent.fromJson(Map<String, dynamic> json) {
    WebSocketEventType type;
    Map<String, dynamic> eventData = {};
    String? promptId;
    String rawType = json['type']?.toString() ?? 'unknown';

    // Extract event type
    if (json.containsKey('type')) {
      final typeStr = json['type'].toString();

      // First, try to extract prompt_id from the data field
      if (json.containsKey('data') && json['data'] is Map) {
        final dataMap = Map<String, dynamic>.from(json['data'] as Map);
        if (dataMap.containsKey('prompt_id')) {
          promptId = dataMap['prompt_id'].toString();
        }
        eventData = dataMap;
      } else {
        // If no data field, use the root object
        eventData = Map<String, dynamic>.from(json);
      }

      // Try to extract prompt_id from other potential locations
      if (promptId == null && json.containsKey('prompt_id')) {
        promptId = json['prompt_id'].toString();
      }

      switch (typeStr) {
        case 'status':
          type = WebSocketEventType.status;
          break;
        case 'progress':
          type = WebSocketEventType.progress;
          break;
        case 'executing':
          type = WebSocketEventType.executing;
          break;
        case 'executed':
          type = WebSocketEventType.executed;
          break;
        case 'execution_start':
          type = WebSocketEventType.executionStart;
          break;
        case 'execution_cached':
          type = WebSocketEventType.executionCached;
          break;
        case 'execution_success':
          type = WebSocketEventType.executionSuccess;
          break;
        case 'execution_error':
          type = WebSocketEventType.executionError;
          break;
        default:
          if (typeStr.startsWith('data_output')) {
            type = WebSocketEventType.dataOutput;
          } else {
            // Default to unknown for unrecognized types
            type = WebSocketEventType.unknown;
            print('Unknown event type: $typeStr');
          }
      }
    } else {
      // If no type field, default to unknown
      type = WebSocketEventType.unknown;
      print('WebSocket event missing type field');
      eventData = Map<String, dynamic>.from(json);
    }

    return WebSocketEvent(
      eventType: type,
      data: eventData,
      promptId: promptId,
      rawType: rawType,
    );
  }
}
